Annotation of qemu/target-ppc/op_helper.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  *  PowerPC emulation helpers for qemu.
1.1.1.3 ! root        3:  *
        !             4:  *  Copyright (c) 2003-2007 Jocelyn Mayer
1.1       root        5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, write to the Free Software
                     18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     19:  */
                     20: #include "exec.h"
1.1.1.3 ! root       21: #include "host-utils.h"
        !            22: 
        !            23: #include "helper_regs.h"
        !            24: #include "op_helper.h"
1.1       root       25: 
                     26: #define MEMSUFFIX _raw
1.1.1.3 ! root       27: #include "op_helper.h"
1.1       root       28: #include "op_helper_mem.h"
                     29: #if !defined(CONFIG_USER_ONLY)
                     30: #define MEMSUFFIX _user
1.1.1.3 ! root       31: #include "op_helper.h"
1.1       root       32: #include "op_helper_mem.h"
                     33: #define MEMSUFFIX _kernel
1.1.1.3 ! root       34: #include "op_helper.h"
        !            35: #include "op_helper_mem.h"
        !            36: #define MEMSUFFIX _hypv
        !            37: #include "op_helper.h"
1.1       root       38: #include "op_helper_mem.h"
                     39: #endif
                     40: 
                     41: //#define DEBUG_OP
                     42: //#define DEBUG_EXCEPTIONS
1.1.1.3 ! root       43: //#define DEBUG_SOFTWARE_TLB
1.1       root       44: 
                     45: /*****************************************************************************/
                     46: /* Exceptions processing helpers */
                     47: 
                     48: void do_raise_exception_err (uint32_t exception, int error_code)
                     49: {
                     50: #if 0
                     51:     printf("Raise exception %3x code : %d\n", exception, error_code);
                     52: #endif
                     53:     env->exception_index = exception;
                     54:     env->error_code = error_code;
1.1.1.3 ! root       55:     cpu_loop_exit();
        !            56: }
1.1       root       57: 
                     58: void do_raise_exception (uint32_t exception)
                     59: {
                     60:     do_raise_exception_err(exception, 0);
                     61: }
                     62: 
1.1.1.3 ! root       63: void cpu_dump_EA (target_ulong EA);
        !            64: void do_print_mem_EA (target_ulong EA)
        !            65: {
        !            66:     cpu_dump_EA(EA);
        !            67: }
        !            68: 
1.1       root       69: /*****************************************************************************/
1.1.1.3 ! root       70: /* Registers load and stores */
        !            71: void do_load_cr (void)
1.1       root       72: {
1.1.1.3 ! root       73:     T0 = (env->crf[0] << 28) |
        !            74:         (env->crf[1] << 24) |
        !            75:         (env->crf[2] << 20) |
        !            76:         (env->crf[3] << 16) |
        !            77:         (env->crf[4] << 12) |
        !            78:         (env->crf[5] << 8) |
        !            79:         (env->crf[6] << 4) |
        !            80:         (env->crf[7] << 0);
        !            81: }
        !            82: 
        !            83: void do_store_cr (uint32_t mask)
        !            84: {
        !            85:     int i, sh;
        !            86: 
        !            87:     for (i = 0, sh = 7; i < 8; i++, sh--) {
        !            88:         if (mask & (1 << sh))
        !            89:             env->crf[i] = (T0 >> (sh * 4)) & 0xFUL;
1.1       root       90:     }
                     91: }
                     92: 
1.1.1.3 ! root       93: #if defined(TARGET_PPC64)
        !            94: void do_store_pri (int prio)
1.1       root       95: {
1.1.1.3 ! root       96:     env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
        !            97:     env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
        !            98: }
        !            99: #endif
        !           100: 
        !           101: target_ulong ppc_load_dump_spr (int sprn)
        !           102: {
        !           103:     if (loglevel != 0) {
        !           104:         fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
        !           105:                 sprn, sprn, env->spr[sprn]);
1.1       root      106:     }
1.1.1.3 ! root      107: 
        !           108:     return env->spr[sprn];
        !           109: }
        !           110: 
        !           111: void ppc_store_dump_spr (int sprn, target_ulong val)
        !           112: {
        !           113:     if (loglevel != 0) {
        !           114:         fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n",
        !           115:                 sprn, sprn, env->spr[sprn], val);
1.1       root      116:     }
1.1.1.3 ! root      117:     env->spr[sprn] = val;
1.1       root      118: }
                    119: 
1.1.1.3 ! root      120: /*****************************************************************************/
        !           121: /* Fixed point operations helpers */
1.1       root      122: void do_adde (void)
                    123: {
                    124:     T2 = T0;
                    125:     T0 += T1 + xer_ca;
1.1.1.3 ! root      126:     if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
        !           127:                  (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
1.1       root      128:         xer_ca = 0;
                    129:     } else {
                    130:         xer_ca = 1;
                    131:     }
                    132: }
                    133: 
1.1.1.3 ! root      134: #if defined(TARGET_PPC64)
        !           135: void do_adde_64 (void)
1.1       root      136: {
                    137:     T2 = T0;
                    138:     T0 += T1 + xer_ca;
1.1.1.3 ! root      139:     if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
        !           140:                  (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
1.1       root      141:         xer_ca = 0;
                    142:     } else {
                    143:         xer_ca = 1;
                    144:     }
                    145: }
1.1.1.3 ! root      146: #endif
1.1       root      147: 
                    148: void do_addmeo (void)
                    149: {
                    150:     T1 = T0;
                    151:     T0 += xer_ca + (-1);
1.1.1.3 ! root      152:     xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31;
        !           153:     xer_so |= xer_ov;
1.1       root      154:     if (likely(T1 != 0))
                    155:         xer_ca = 1;
1.1.1.3 ! root      156:     else
        !           157:         xer_ca = 0;
1.1       root      158: }
                    159: 
1.1.1.3 ! root      160: #if defined(TARGET_PPC64)
        !           161: void do_addmeo_64 (void)
1.1       root      162: {
                    163:     T1 = T0;
1.1.1.3 ! root      164:     T0 += xer_ca + (-1);
        !           165:     xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63;
        !           166:     xer_so |= xer_ov;
        !           167:     if (likely(T1 != 0))
        !           168:         xer_ca = 1;
        !           169:     else
        !           170:         xer_ca = 0;
        !           171: }
        !           172: #endif
        !           173: 
        !           174: void do_divwo (void)
        !           175: {
        !           176:     if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
        !           177:                  (int32_t)T1 == 0))) {
1.1       root      178:         xer_ov = 0;
1.1.1.3 ! root      179:         T0 = (int32_t)T0 / (int32_t)T1;
1.1       root      180:     } else {
                    181:         xer_ov = 1;
1.1.1.3 ! root      182:         T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1.1       root      183:     }
1.1.1.3 ! root      184:     xer_so |= xer_ov;
1.1       root      185: }
                    186: 
1.1.1.3 ! root      187: #if defined(TARGET_PPC64)
        !           188: void do_divdo (void)
1.1       root      189: {
1.1.1.3 ! root      190:     if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == (int64_t)-1LL) ||
        !           191:                  (int64_t)T1 == 0))) {
1.1       root      192:         xer_ov = 0;
1.1.1.3 ! root      193:         T0 = (int64_t)T0 / (int64_t)T1;
1.1       root      194:     } else {
                    195:         xer_ov = 1;
1.1.1.3 ! root      196:         T0 = UINT64_MAX * ((uint64_t)T0 >> 63);
1.1       root      197:     }
1.1.1.3 ! root      198:     xer_so |= xer_ov;
1.1       root      199: }
1.1.1.3 ! root      200: #endif
1.1       root      201: 
                    202: void do_divwuo (void)
                    203: {
                    204:     if (likely((uint32_t)T1 != 0)) {
                    205:         xer_ov = 0;
                    206:         T0 = (uint32_t)T0 / (uint32_t)T1;
                    207:     } else {
1.1.1.3 ! root      208:         xer_ov = 1;
1.1       root      209:         xer_so = 1;
1.1.1.3 ! root      210:         T0 = 0;
        !           211:     }
        !           212: }
        !           213: 
        !           214: #if defined(TARGET_PPC64)
        !           215: void do_divduo (void)
        !           216: {
        !           217:     if (likely((uint64_t)T1 != 0)) {
        !           218:         xer_ov = 0;
        !           219:         T0 = (uint64_t)T0 / (uint64_t)T1;
        !           220:     } else {
1.1       root      221:         xer_ov = 1;
1.1.1.3 ! root      222:         xer_so = 1;
1.1       root      223:         T0 = 0;
                    224:     }
                    225: }
1.1.1.3 ! root      226: #endif
1.1       root      227: 
                    228: void do_mullwo (void)
                    229: {
1.1.1.3 ! root      230:     int64_t res = (int64_t)T0 * (int64_t)T1;
1.1       root      231: 
                    232:     if (likely((int32_t)res == res)) {
                    233:         xer_ov = 0;
                    234:     } else {
                    235:         xer_ov = 1;
                    236:         xer_so = 1;
                    237:     }
                    238:     T0 = (int32_t)res;
                    239: }
                    240: 
1.1.1.3 ! root      241: #if defined(TARGET_PPC64)
        !           242: void do_mulldo (void)
1.1       root      243: {
1.1.1.3 ! root      244:     int64_t th;
        !           245:     uint64_t tl;
        !           246: 
        !           247:     muls64(&tl, &th, T0, T1);
        !           248:     T0 = (int64_t)tl;
        !           249:     /* If th != 0 && th != -1, then we had an overflow */
        !           250:     if (likely((uint64_t)(th + 1) <= 1)) {
1.1       root      251:         xer_ov = 0;
                    252:     } else {
                    253:         xer_ov = 1;
                    254:     }
1.1.1.3 ! root      255:     xer_so |= xer_ov;
1.1       root      256: }
1.1.1.3 ! root      257: #endif
1.1       root      258: 
1.1.1.3 ! root      259: void do_nego (void)
1.1       root      260: {
1.1.1.3 ! root      261:     if (likely((int32_t)T0 != INT32_MIN)) {
1.1       root      262:         xer_ov = 0;
1.1.1.3 ! root      263:         T0 = -(int32_t)T0;
1.1       root      264:     } else {
                    265:         xer_ov = 1;
1.1.1.3 ! root      266:         xer_so = 1;
1.1       root      267:     }
                    268: }
                    269: 
1.1.1.3 ! root      270: #if defined(TARGET_PPC64)
        !           271: void do_nego_64 (void)
1.1       root      272: {
1.1.1.3 ! root      273:     if (likely((int64_t)T0 != INT64_MIN)) {
1.1       root      274:         xer_ov = 0;
1.1.1.3 ! root      275:         T0 = -(int64_t)T0;
1.1       root      276:     } else {
                    277:         xer_ov = 1;
1.1.1.3 ! root      278:         xer_so = 1;
1.1       root      279:     }
                    280: }
1.1.1.3 ! root      281: #endif
1.1       root      282: 
                    283: void do_subfe (void)
                    284: {
                    285:     T0 = T1 + ~T0 + xer_ca;
1.1.1.3 ! root      286:     if (likely((uint32_t)T0 >= (uint32_t)T1 &&
        !           287:                (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
1.1       root      288:         xer_ca = 0;
                    289:     } else {
                    290:         xer_ca = 1;
                    291:     }
                    292: }
                    293: 
1.1.1.3 ! root      294: #if defined(TARGET_PPC64)
        !           295: void do_subfe_64 (void)
1.1       root      296: {
                    297:     T0 = T1 + ~T0 + xer_ca;
1.1.1.3 ! root      298:     if (likely((uint64_t)T0 >= (uint64_t)T1 &&
        !           299:                (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
1.1       root      300:         xer_ca = 0;
                    301:     } else {
                    302:         xer_ca = 1;
                    303:     }
                    304: }
1.1.1.3 ! root      305: #endif
1.1       root      306: 
                    307: void do_subfmeo (void)
                    308: {
                    309:     T1 = T0;
                    310:     T0 = ~T0 + xer_ca - 1;
1.1.1.3 ! root      311:     xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31;
        !           312:     xer_so |= xer_ov;
        !           313:     if (likely((uint32_t)T1 != UINT32_MAX))
        !           314:         xer_ca = 1;
        !           315:     else
        !           316:         xer_ca = 0;
        !           317: }
        !           318: 
        !           319: #if defined(TARGET_PPC64)
        !           320: void do_subfmeo_64 (void)
        !           321: {
        !           322:     T1 = T0;
        !           323:     T0 = ~T0 + xer_ca - 1;
        !           324:     xer_ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63;
        !           325:     xer_so |= xer_ov;
        !           326:     if (likely((uint64_t)T1 != UINT64_MAX))
1.1       root      327:         xer_ca = 1;
1.1.1.3 ! root      328:     else
        !           329:         xer_ca = 0;
1.1       root      330: }
1.1.1.3 ! root      331: #endif
1.1       root      332: 
                    333: void do_subfzeo (void)
                    334: {
                    335:     T1 = T0;
                    336:     T0 = ~T0 + xer_ca;
1.1.1.3 ! root      337:     xer_ov = (((uint32_t)~T1 ^ UINT32_MAX) &
        !           338:               ((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31;
        !           339:     xer_so |= xer_ov;
        !           340:     if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
        !           341:         xer_ca = 0;
1.1       root      342:     } else {
1.1.1.3 ! root      343:         xer_ca = 1;
1.1       root      344:     }
1.1.1.3 ! root      345: }
        !           346: 
        !           347: #if defined(TARGET_PPC64)
        !           348: void do_subfzeo_64 (void)
        !           349: {
        !           350:     T1 = T0;
        !           351:     T0 = ~T0 + xer_ca;
        !           352:     xer_ov = (((uint64_t)~T1 ^  UINT64_MAX) &
        !           353:               ((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63;
        !           354:     xer_so |= xer_ov;
        !           355:     if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
1.1       root      356:         xer_ca = 0;
                    357:     } else {
                    358:         xer_ca = 1;
                    359:     }
                    360: }
1.1.1.3 ! root      361: #endif
        !           362: 
        !           363: void do_cntlzw (void)
        !           364: {
        !           365:     T0 = clz32(T0);
        !           366: }
        !           367: 
        !           368: #if defined(TARGET_PPC64)
        !           369: void do_cntlzd (void)
        !           370: {
        !           371:     T0 = clz64(T0);
        !           372: }
        !           373: #endif
1.1       root      374: 
                    375: /* shift right arithmetic helper */
                    376: void do_sraw (void)
                    377: {
                    378:     int32_t ret;
                    379: 
                    380:     if (likely(!(T1 & 0x20UL))) {
1.1.1.3 ! root      381:         if (likely((uint32_t)T1 != 0)) {
1.1       root      382:             ret = (int32_t)T0 >> (T1 & 0x1fUL);
                    383:             if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
1.1.1.3 ! root      384:                 xer_ca = 0;
1.1       root      385:             } else {
1.1.1.3 ! root      386:                 xer_ca = 1;
1.1       root      387:             }
                    388:         } else {
1.1.1.3 ! root      389:             ret = T0;
1.1       root      390:             xer_ca = 0;
                    391:         }
                    392:     } else {
1.1.1.3 ! root      393:         ret = UINT32_MAX * ((uint32_t)T0 >> 31);
1.1       root      394:         if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
                    395:             xer_ca = 0;
1.1.1.3 ! root      396:         } else {
1.1       root      397:             xer_ca = 1;
1.1.1.3 ! root      398:         }
1.1       root      399:     }
1.1.1.3 ! root      400:     T0 = ret;
        !           401: }
        !           402: 
        !           403: #if defined(TARGET_PPC64)
        !           404: void do_srad (void)
        !           405: {
        !           406:     int64_t ret;
        !           407: 
        !           408:     if (likely(!(T1 & 0x40UL))) {
        !           409:         if (likely((uint64_t)T1 != 0)) {
        !           410:             ret = (int64_t)T0 >> (T1 & 0x3FUL);
        !           411:             if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) {
        !           412:                 xer_ca = 0;
        !           413:             } else {
        !           414:                 xer_ca = 1;
        !           415:             }
        !           416:         } else {
        !           417:             ret = T0;
        !           418:             xer_ca = 0;
        !           419:         }
        !           420:     } else {
        !           421:         ret = UINT64_MAX * ((uint64_t)T0 >> 63);
        !           422:         if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) {
        !           423:             xer_ca = 0;
        !           424:         } else {
        !           425:             xer_ca = 1;
        !           426:         }
1.1       root      427:     }
                    428:     T0 = ret;
                    429: }
1.1.1.3 ! root      430: #endif
        !           431: 
        !           432: void do_popcntb (void)
        !           433: {
        !           434:     uint32_t ret;
        !           435:     int i;
        !           436: 
        !           437:     ret = 0;
        !           438:     for (i = 0; i < 32; i += 8)
        !           439:         ret |= ctpop8((T0 >> i) & 0xFF) << i;
        !           440:     T0 = ret;
        !           441: }
        !           442: 
        !           443: #if defined(TARGET_PPC64)
        !           444: void do_popcntb_64 (void)
        !           445: {
        !           446:     uint64_t ret;
        !           447:     int i;
        !           448: 
        !           449:     ret = 0;
        !           450:     for (i = 0; i < 64; i += 8)
        !           451:         ret |= ctpop8((T0 >> i) & 0xFF) << i;
        !           452:     T0 = ret;
        !           453: }
        !           454: #endif
1.1       root      455: 
                    456: /*****************************************************************************/
                    457: /* Floating point operations helpers */
1.1.1.3 ! root      458: static always_inline int fpisneg (float64 f)
1.1       root      459: {
                    460:     union {
1.1.1.3 ! root      461:         float64 f;
        !           462:         uint64_t u;
        !           463:     } u;
1.1       root      464: 
1.1.1.3 ! root      465:     u.f = f;
        !           466: 
        !           467:     return u.u >> 63 != 0;
1.1       root      468: }
                    469: 
1.1.1.3 ! root      470: static always_inline int isden (float f)
1.1       root      471: {
                    472:     union {
1.1.1.3 ! root      473:         float64 f;
        !           474:         uint64_t u;
        !           475:     } u;
1.1       root      476: 
1.1.1.3 ! root      477:     u.f = f;
1.1       root      478: 
1.1.1.3 ! root      479:     return ((u.u >> 52) & 0x7FF) == 0;
1.1       root      480: }
                    481: 
1.1.1.3 ! root      482: static always_inline int iszero (float64 f)
1.1       root      483: {
1.1.1.3 ! root      484:     union {
        !           485:         float64 f;
        !           486:         uint64_t u;
        !           487:     } u;
        !           488: 
        !           489:     u.f = f;
        !           490: 
        !           491:     return (u.u & ~0x8000000000000000ULL) == 0;
1.1       root      492: }
                    493: 
1.1.1.3 ! root      494: static always_inline int isinfinity (float64 f)
1.1       root      495: {
1.1.1.3 ! root      496:     union {
        !           497:         float64 f;
        !           498:         uint64_t u;
        !           499:     } u;
        !           500: 
        !           501:     u.f = f;
        !           502: 
        !           503:     return ((u.u >> 52) & 0x7FF) == 0x7FF &&
        !           504:         (u.u & 0x000FFFFFFFFFFFFFULL) == 0;
1.1       root      505: }
                    506: 
1.1.1.3 ! root      507: void do_compute_fprf (int set_fprf)
1.1       root      508: {
1.1.1.3 ! root      509:     int isneg;
1.1       root      510: 
1.1.1.3 ! root      511:     isneg = fpisneg(FT0);
        !           512:     if (unlikely(float64_is_nan(FT0))) {
        !           513:         if (float64_is_signaling_nan(FT0)) {
        !           514:             /* Signaling NaN: flags are undefined */
        !           515:             T0 = 0x00;
1.1       root      516:         } else {
1.1.1.3 ! root      517:             /* Quiet NaN */
        !           518:             T0 = 0x11;
1.1       root      519:         }
1.1.1.3 ! root      520:     } else if (unlikely(isinfinity(FT0))) {
        !           521:         /* +/- infinity */
        !           522:         if (isneg)
        !           523:             T0 = 0x09;
        !           524:         else
        !           525:             T0 = 0x05;
        !           526:     } else {
        !           527:         if (iszero(FT0)) {
        !           528:             /* +/- zero */
        !           529:             if (isneg)
        !           530:                 T0 = 0x12;
        !           531:             else
        !           532:                 T0 = 0x02;
        !           533:         } else {
        !           534:             if (isden(FT0)) {
        !           535:                 /* Denormalized numbers */
        !           536:                 T0 = 0x10;
        !           537:             } else {
        !           538:                 /* Normalized numbers */
        !           539:                 T0 = 0x00;
        !           540:             }
        !           541:             if (isneg) {
        !           542:                 T0 |= 0x08;
        !           543:             } else {
        !           544:                 T0 |= 0x04;
        !           545:             }
        !           546:         }
        !           547:     }
        !           548:     if (set_fprf) {
        !           549:         /* We update FPSCR_FPRF */
        !           550:         env->fpscr &= ~(0x1F << FPSCR_FPRF);
        !           551:         env->fpscr |= T0 << FPSCR_FPRF;
        !           552:     }
        !           553:     /* We just need fpcc to update Rc1 */
        !           554:     T0 &= 0xF;
        !           555: }
        !           556: 
        !           557: /* Floating-point invalid operations exception */
        !           558: static always_inline void fload_invalid_op_excp (int op)
        !           559: {
        !           560:     int ve;
        !           561: 
        !           562:     ve = fpscr_ve;
        !           563:     if (op & POWERPC_EXCP_FP_VXSNAN) {
        !           564:         /* Operation on signaling NaN */
        !           565:         env->fpscr |= 1 << FPSCR_VXSNAN;
        !           566:     }
        !           567:     if (op & POWERPC_EXCP_FP_VXSOFT) {
        !           568:         /* Software-defined condition */
        !           569:         env->fpscr |= 1 << FPSCR_VXSOFT;
        !           570:     }
        !           571:     switch (op & ~(POWERPC_EXCP_FP_VXSOFT | POWERPC_EXCP_FP_VXSNAN)) {
        !           572:     case POWERPC_EXCP_FP_VXISI:
        !           573:         /* Magnitude subtraction of infinities */
        !           574:         env->fpscr |= 1 << FPSCR_VXISI;
        !           575:         goto update_arith;
        !           576:     case POWERPC_EXCP_FP_VXIDI:
        !           577:         /* Division of infinity by infinity */
        !           578:         env->fpscr |= 1 << FPSCR_VXIDI;
        !           579:         goto update_arith;
        !           580:     case POWERPC_EXCP_FP_VXZDZ:
        !           581:         /* Division of zero by zero */
        !           582:         env->fpscr |= 1 << FPSCR_VXZDZ;
        !           583:         goto update_arith;
        !           584:     case POWERPC_EXCP_FP_VXIMZ:
        !           585:         /* Multiplication of zero by infinity */
        !           586:         env->fpscr |= 1 << FPSCR_VXIMZ;
        !           587:         goto update_arith;
        !           588:     case POWERPC_EXCP_FP_VXVC:
        !           589:         /* Ordered comparison of NaN */
        !           590:         env->fpscr |= 1 << FPSCR_VXVC;
        !           591:         env->fpscr &= ~(0xF << FPSCR_FPCC);
        !           592:         env->fpscr |= 0x11 << FPSCR_FPCC;
        !           593:         /* We must update the target FPR before raising the exception */
        !           594:         if (ve != 0) {
        !           595:             env->exception_index = POWERPC_EXCP_PROGRAM;
        !           596:             env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
        !           597:             /* Update the floating-point enabled exception summary */
        !           598:             env->fpscr |= 1 << FPSCR_FEX;
        !           599:             /* Exception is differed */
        !           600:             ve = 0;
        !           601:         }
        !           602:         break;
        !           603:     case POWERPC_EXCP_FP_VXSQRT:
        !           604:         /* Square root of a negative number */
        !           605:         env->fpscr |= 1 << FPSCR_VXSQRT;
        !           606:     update_arith:
        !           607:         env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
        !           608:         if (ve == 0) {
        !           609:             /* Set the result to quiet NaN */
        !           610:             FT0 = UINT64_MAX;
        !           611:             env->fpscr &= ~(0xF << FPSCR_FPCC);
        !           612:             env->fpscr |= 0x11 << FPSCR_FPCC;
        !           613:         }
        !           614:         break;
        !           615:     case POWERPC_EXCP_FP_VXCVI:
        !           616:         /* Invalid conversion */
        !           617:         env->fpscr |= 1 << FPSCR_VXCVI;
        !           618:         env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
        !           619:         if (ve == 0) {
        !           620:             /* Set the result to quiet NaN */
        !           621:             FT0 = UINT64_MAX;
        !           622:             env->fpscr &= ~(0xF << FPSCR_FPCC);
        !           623:             env->fpscr |= 0x11 << FPSCR_FPCC;
        !           624:         }
        !           625:         break;
        !           626:     }
        !           627:     /* Update the floating-point invalid operation summary */
        !           628:     env->fpscr |= 1 << FPSCR_VX;
        !           629:     /* Update the floating-point exception summary */
        !           630:     env->fpscr |= 1 << FPSCR_FX;
        !           631:     if (ve != 0) {
        !           632:         /* Update the floating-point enabled exception summary */
        !           633:         env->fpscr |= 1 << FPSCR_FEX;
        !           634:         if (msr_fe0 != 0 || msr_fe1 != 0)
        !           635:             do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
1.1       root      636:     }
                    637: }
                    638: 
1.1.1.3 ! root      639: static always_inline void float_zero_divide_excp (void)
1.1       root      640: {
                    641:     union {
1.1.1.3 ! root      642:         float64 f;
        !           643:         uint64_t u;
        !           644:     } u0, u1;
        !           645: 
        !           646:     env->fpscr |= 1 << FPSCR_ZX;
        !           647:     env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
        !           648:     /* Update the floating-point exception summary */
        !           649:     env->fpscr |= 1 << FPSCR_FX;
        !           650:     if (fpscr_ze != 0) {
        !           651:         /* Update the floating-point enabled exception summary */
        !           652:         env->fpscr |= 1 << FPSCR_FEX;
        !           653:         if (msr_fe0 != 0 || msr_fe1 != 0) {
        !           654:             do_raise_exception_err(POWERPC_EXCP_PROGRAM,
        !           655:                                    POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
        !           656:         }
1.1       root      657:     } else {
1.1.1.3 ! root      658:         /* Set the result to infinity */
        !           659:         u0.f = FT0;
        !           660:         u1.f = FT1;
        !           661:         u0.u = ((u0.u ^ u1.u) & 0x8000000000000000ULL);
        !           662:         u0.u |= 0x7FFULL << 52;
        !           663:         FT0 = u0.f;
        !           664:     }
        !           665: }
        !           666: 
        !           667: static always_inline void float_overflow_excp (void)
        !           668: {
        !           669:     env->fpscr |= 1 << FPSCR_OX;
        !           670:     /* Update the floating-point exception summary */
        !           671:     env->fpscr |= 1 << FPSCR_FX;
        !           672:     if (fpscr_oe != 0) {
        !           673:         /* XXX: should adjust the result */
        !           674:         /* Update the floating-point enabled exception summary */
        !           675:         env->fpscr |= 1 << FPSCR_FEX;
        !           676:         /* We must update the target FPR before raising the exception */
        !           677:         env->exception_index = POWERPC_EXCP_PROGRAM;
        !           678:         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
        !           679:     } else {
        !           680:         env->fpscr |= 1 << FPSCR_XX;
        !           681:         env->fpscr |= 1 << FPSCR_FI;
        !           682:     }
        !           683: }
        !           684: 
        !           685: static always_inline void float_underflow_excp (void)
        !           686: {
        !           687:     env->fpscr |= 1 << FPSCR_UX;
        !           688:     /* Update the floating-point exception summary */
        !           689:     env->fpscr |= 1 << FPSCR_FX;
        !           690:     if (fpscr_ue != 0) {
        !           691:         /* XXX: should adjust the result */
        !           692:         /* Update the floating-point enabled exception summary */
        !           693:         env->fpscr |= 1 << FPSCR_FEX;
        !           694:         /* We must update the target FPR before raising the exception */
        !           695:         env->exception_index = POWERPC_EXCP_PROGRAM;
        !           696:         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
        !           697:     }
        !           698: }
        !           699: 
        !           700: static always_inline void float_inexact_excp (void)
        !           701: {
        !           702:     env->fpscr |= 1 << FPSCR_XX;
        !           703:     /* Update the floating-point exception summary */
        !           704:     env->fpscr |= 1 << FPSCR_FX;
        !           705:     if (fpscr_xe != 0) {
        !           706:         /* Update the floating-point enabled exception summary */
        !           707:         env->fpscr |= 1 << FPSCR_FEX;
        !           708:         /* We must update the target FPR before raising the exception */
        !           709:         env->exception_index = POWERPC_EXCP_PROGRAM;
        !           710:         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
        !           711:     }
        !           712: }
        !           713: 
        !           714: static always_inline void fpscr_set_rounding_mode (void)
        !           715: {
        !           716:     int rnd_type;
        !           717: 
        !           718:     /* Set rounding mode */
        !           719:     switch (fpscr_rn) {
        !           720:     case 0:
        !           721:         /* Best approximation (round to nearest) */
        !           722:         rnd_type = float_round_nearest_even;
        !           723:         break;
        !           724:     case 1:
        !           725:         /* Smaller magnitude (round toward zero) */
        !           726:         rnd_type = float_round_to_zero;
        !           727:         break;
        !           728:     case 2:
        !           729:         /* Round toward +infinite */
        !           730:         rnd_type = float_round_up;
        !           731:         break;
        !           732:     default:
        !           733:     case 3:
        !           734:         /* Round toward -infinite */
        !           735:         rnd_type = float_round_down;
        !           736:         break;
        !           737:     }
        !           738:     set_float_rounding_mode(rnd_type, &env->fp_status);
        !           739: }
        !           740: 
        !           741: void do_fpscr_setbit (int bit)
        !           742: {
        !           743:     int prev;
        !           744: 
        !           745:     prev = (env->fpscr >> bit) & 1;
        !           746:     env->fpscr |= 1 << bit;
        !           747:     if (prev == 0) {
        !           748:         switch (bit) {
        !           749:         case FPSCR_VX:
        !           750:             env->fpscr |= 1 << FPSCR_FX;
        !           751:             if (fpscr_ve)
        !           752:                 goto raise_ve;
        !           753:         case FPSCR_OX:
        !           754:             env->fpscr |= 1 << FPSCR_FX;
        !           755:             if (fpscr_oe)
        !           756:                 goto raise_oe;
        !           757:             break;
        !           758:         case FPSCR_UX:
        !           759:             env->fpscr |= 1 << FPSCR_FX;
        !           760:             if (fpscr_ue)
        !           761:                 goto raise_ue;
        !           762:             break;
        !           763:         case FPSCR_ZX:
        !           764:             env->fpscr |= 1 << FPSCR_FX;
        !           765:             if (fpscr_ze)
        !           766:                 goto raise_ze;
        !           767:             break;
        !           768:         case FPSCR_XX:
        !           769:             env->fpscr |= 1 << FPSCR_FX;
        !           770:             if (fpscr_xe)
        !           771:                 goto raise_xe;
        !           772:             break;
        !           773:         case FPSCR_VXSNAN:
        !           774:         case FPSCR_VXISI:
        !           775:         case FPSCR_VXIDI:
        !           776:         case FPSCR_VXZDZ:
        !           777:         case FPSCR_VXIMZ:
        !           778:         case FPSCR_VXVC:
        !           779:         case FPSCR_VXSOFT:
        !           780:         case FPSCR_VXSQRT:
        !           781:         case FPSCR_VXCVI:
        !           782:             env->fpscr |= 1 << FPSCR_VX;
        !           783:             env->fpscr |= 1 << FPSCR_FX;
        !           784:             if (fpscr_ve != 0)
        !           785:                 goto raise_ve;
        !           786:             break;
        !           787:         case FPSCR_VE:
        !           788:             if (fpscr_vx != 0) {
        !           789:             raise_ve:
        !           790:                 env->error_code = POWERPC_EXCP_FP;
        !           791:                 if (fpscr_vxsnan)
        !           792:                     env->error_code |= POWERPC_EXCP_FP_VXSNAN;
        !           793:                 if (fpscr_vxisi)
        !           794:                     env->error_code |= POWERPC_EXCP_FP_VXISI;
        !           795:                 if (fpscr_vxidi)
        !           796:                     env->error_code |= POWERPC_EXCP_FP_VXIDI;
        !           797:                 if (fpscr_vxzdz)
        !           798:                     env->error_code |= POWERPC_EXCP_FP_VXZDZ;
        !           799:                 if (fpscr_vximz)
        !           800:                     env->error_code |= POWERPC_EXCP_FP_VXIMZ;
        !           801:                 if (fpscr_vxvc)
        !           802:                     env->error_code |= POWERPC_EXCP_FP_VXVC;
        !           803:                 if (fpscr_vxsoft)
        !           804:                     env->error_code |= POWERPC_EXCP_FP_VXSOFT;
        !           805:                 if (fpscr_vxsqrt)
        !           806:                     env->error_code |= POWERPC_EXCP_FP_VXSQRT;
        !           807:                 if (fpscr_vxcvi)
        !           808:                     env->error_code |= POWERPC_EXCP_FP_VXCVI;
        !           809:                 goto raise_excp;
        !           810:             }
        !           811:             break;
        !           812:         case FPSCR_OE:
        !           813:             if (fpscr_ox != 0) {
        !           814:             raise_oe:
        !           815:                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
        !           816:                 goto raise_excp;
        !           817:             }
        !           818:             break;
        !           819:         case FPSCR_UE:
        !           820:             if (fpscr_ux != 0) {
        !           821:             raise_ue:
        !           822:                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
        !           823:                 goto raise_excp;
        !           824:             }
        !           825:             break;
        !           826:         case FPSCR_ZE:
        !           827:             if (fpscr_zx != 0) {
        !           828:             raise_ze:
        !           829:                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
        !           830:                 goto raise_excp;
        !           831:             }
        !           832:             break;
        !           833:         case FPSCR_XE:
        !           834:             if (fpscr_xx != 0) {
        !           835:             raise_xe:
        !           836:                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
        !           837:                 goto raise_excp;
        !           838:             }
        !           839:             break;
        !           840:         case FPSCR_RN1:
        !           841:         case FPSCR_RN:
        !           842:             fpscr_set_rounding_mode();
        !           843:             break;
        !           844:         default:
        !           845:             break;
        !           846:         raise_excp:
        !           847:             /* Update the floating-point enabled exception summary */
        !           848:             env->fpscr |= 1 << FPSCR_FEX;
        !           849:                 /* We have to update Rc1 before raising the exception */
        !           850:             env->exception_index = POWERPC_EXCP_PROGRAM;
        !           851:             break;
1.1       root      852:         }
                    853:     }
                    854: }
                    855: 
1.1.1.3 ! root      856: #if defined(WORDS_BIGENDIAN)
        !           857: #define WORD0 0
        !           858: #define WORD1 1
        !           859: #else
        !           860: #define WORD0 1
        !           861: #define WORD1 0
        !           862: #endif
        !           863: void do_store_fpscr (uint32_t mask)
1.1       root      864: {
1.1.1.3 ! root      865:     /*
        !           866:      * We use only the 32 LSB of the incoming fpr
        !           867:      */
        !           868:     union {
        !           869:         double d;
        !           870:         struct {
        !           871:             uint32_t u[2];
        !           872:         } s;
        !           873:     } u;
        !           874:     uint32_t prev, new;
        !           875:     int i;
        !           876: 
        !           877:     u.d = FT0;
        !           878:     prev = env->fpscr;
        !           879:     new = u.s.u[WORD1];
        !           880:     new &= ~0x90000000;
        !           881:     new |= prev & 0x90000000;
        !           882:     for (i = 0; i < 7; i++) {
        !           883:         if (mask & (1 << i)) {
        !           884:             env->fpscr &= ~(0xF << (4 * i));
        !           885:             env->fpscr |= new & (0xF << (4 * i));
        !           886:         }
        !           887:     }
        !           888:     /* Update VX and FEX */
        !           889:     if (fpscr_ix != 0)
        !           890:         env->fpscr |= 1 << FPSCR_VX;
        !           891:     if ((fpscr_ex & fpscr_eex) != 0) {
        !           892:         env->fpscr |= 1 << FPSCR_FEX;
        !           893:         env->exception_index = POWERPC_EXCP_PROGRAM;
        !           894:         /* XXX: we should compute it properly */
        !           895:         env->error_code = POWERPC_EXCP_FP;
        !           896:     }
        !           897:     fpscr_set_rounding_mode();
        !           898: }
        !           899: #undef WORD0
        !           900: #undef WORD1
        !           901: 
        !           902: #ifdef CONFIG_SOFTFLOAT
        !           903: void do_float_check_status (void)
        !           904: {
        !           905:     if (env->exception_index == POWERPC_EXCP_PROGRAM &&
        !           906:         (env->error_code & POWERPC_EXCP_FP)) {
        !           907:         /* Differred floating-point exception after target FPR update */
        !           908:         if (msr_fe0 != 0 || msr_fe1 != 0)
        !           909:             do_raise_exception_err(env->exception_index, env->error_code);
        !           910:     } else if (env->fp_status.float_exception_flags & float_flag_overflow) {
        !           911:         float_overflow_excp();
        !           912:     } else if (env->fp_status.float_exception_flags & float_flag_underflow) {
        !           913:         float_underflow_excp();
        !           914:     } else if (env->fp_status.float_exception_flags & float_flag_inexact) {
        !           915:         float_inexact_excp();
        !           916:     }
        !           917: }
        !           918: #endif
        !           919: 
        !           920: #if USE_PRECISE_EMULATION
        !           921: void do_fadd (void)
        !           922: {
        !           923:     if (unlikely(float64_is_signaling_nan(FT0) ||
        !           924:                  float64_is_signaling_nan(FT1))) {
        !           925:         /* sNaN addition */
        !           926:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !           927:     } else if (likely(isfinite(FT0) || isfinite(FT1) ||
        !           928:                       fpisneg(FT0) == fpisneg(FT1))) {
        !           929:         FT0 = float64_add(FT0, FT1, &env->fp_status);
        !           930:     } else {
        !           931:         /* Magnitude subtraction of infinities */
        !           932:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
        !           933:     }
        !           934: }
        !           935: 
        !           936: void do_fsub (void)
        !           937: {
        !           938:     if (unlikely(float64_is_signaling_nan(FT0) ||
        !           939:                  float64_is_signaling_nan(FT1))) {
        !           940:         /* sNaN subtraction */
        !           941:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !           942:     } else if (likely(isfinite(FT0) || isfinite(FT1) ||
        !           943:                       fpisneg(FT0) != fpisneg(FT1))) {
        !           944:         FT0 = float64_sub(FT0, FT1, &env->fp_status);
        !           945:     } else {
        !           946:         /* Magnitude subtraction of infinities */
        !           947:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
        !           948:     }
        !           949: }
        !           950: 
        !           951: void do_fmul (void)
        !           952: {
        !           953:     if (unlikely(float64_is_signaling_nan(FT0) ||
        !           954:                  float64_is_signaling_nan(FT1))) {
        !           955:         /* sNaN multiplication */
        !           956:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !           957:     } else if (unlikely((isinfinity(FT0) && iszero(FT1)) ||
        !           958:                         (iszero(FT0) && isinfinity(FT1)))) {
        !           959:         /* Multiplication of zero by infinity */
        !           960:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
        !           961:     } else {
        !           962:         FT0 = float64_mul(FT0, FT1, &env->fp_status);
        !           963:     }
        !           964: }
        !           965: 
        !           966: void do_fdiv (void)
        !           967: {
        !           968:     if (unlikely(float64_is_signaling_nan(FT0) ||
        !           969:                  float64_is_signaling_nan(FT1))) {
        !           970:         /* sNaN division */
        !           971:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !           972:     } else if (unlikely(isinfinity(FT0) && isinfinity(FT1))) {
        !           973:         /* Division of infinity by infinity */
        !           974:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
        !           975:     } else if (unlikely(iszero(FT1))) {
        !           976:         if (iszero(FT0)) {
        !           977:             /* Division of zero by zero */
        !           978:             fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
        !           979:         } else {
        !           980:             /* Division by zero */
        !           981:             float_zero_divide_excp();
        !           982:         }
        !           983:     } else {
        !           984:         FT0 = float64_div(FT0, FT1, &env->fp_status);
        !           985:     }
        !           986: }
        !           987: #endif /* USE_PRECISE_EMULATION */
        !           988: 
        !           989: void do_fctiw (void)
        !           990: {
        !           991:     union {
        !           992:         double d;
        !           993:         uint64_t i;
        !           994:     } p;
        !           995: 
        !           996:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !           997:         /* sNaN conversion */
        !           998:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
        !           999:     } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
        !          1000:         /* qNan / infinity conversion */
        !          1001:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
        !          1002:     } else {
        !          1003:         p.i = float64_to_int32(FT0, &env->fp_status);
        !          1004: #if USE_PRECISE_EMULATION
        !          1005:         /* XXX: higher bits are not supposed to be significant.
        !          1006:          *     to make tests easier, return the same as a real PowerPC 750
        !          1007:          */
        !          1008:         p.i |= 0xFFF80000ULL << 32;
        !          1009: #endif
        !          1010:         FT0 = p.d;
        !          1011:     }
        !          1012: }
        !          1013: 
        !          1014: void do_fctiwz (void)
        !          1015: {
        !          1016:     union {
        !          1017:         double d;
        !          1018:         uint64_t i;
        !          1019:     } p;
        !          1020: 
        !          1021:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !          1022:         /* sNaN conversion */
        !          1023:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
        !          1024:     } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
        !          1025:         /* qNan / infinity conversion */
        !          1026:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
        !          1027:     } else {
        !          1028:         p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
        !          1029: #if USE_PRECISE_EMULATION
        !          1030:         /* XXX: higher bits are not supposed to be significant.
        !          1031:          *     to make tests easier, return the same as a real PowerPC 750
        !          1032:          */
        !          1033:         p.i |= 0xFFF80000ULL << 32;
        !          1034: #endif
        !          1035:         FT0 = p.d;
        !          1036:     }
        !          1037: }
        !          1038: 
        !          1039: #if defined(TARGET_PPC64)
        !          1040: void do_fcfid (void)
        !          1041: {
        !          1042:     union {
        !          1043:         double d;
        !          1044:         uint64_t i;
        !          1045:     } p;
        !          1046: 
        !          1047:     p.d = FT0;
        !          1048:     FT0 = int64_to_float64(p.i, &env->fp_status);
        !          1049: }
        !          1050: 
        !          1051: void do_fctid (void)
        !          1052: {
        !          1053:     union {
        !          1054:         double d;
        !          1055:         uint64_t i;
        !          1056:     } p;
        !          1057: 
        !          1058:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !          1059:         /* sNaN conversion */
        !          1060:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
        !          1061:     } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
        !          1062:         /* qNan / infinity conversion */
        !          1063:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
        !          1064:     } else {
        !          1065:         p.i = float64_to_int64(FT0, &env->fp_status);
        !          1066:         FT0 = p.d;
        !          1067:     }
        !          1068: }
        !          1069: 
        !          1070: void do_fctidz (void)
        !          1071: {
        !          1072:     union {
        !          1073:         double d;
        !          1074:         uint64_t i;
        !          1075:     } p;
        !          1076: 
        !          1077:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !          1078:         /* sNaN conversion */
        !          1079:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
        !          1080:     } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
        !          1081:         /* qNan / infinity conversion */
        !          1082:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
        !          1083:     } else {
        !          1084:         p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
        !          1085:         FT0 = p.d;
        !          1086:     }
        !          1087: }
        !          1088: 
        !          1089: #endif
        !          1090: 
        !          1091: static always_inline void do_fri (int rounding_mode)
        !          1092: {
        !          1093:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !          1094:         /* sNaN round */
        !          1095:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
        !          1096:     } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
        !          1097:         /* qNan / infinity round */
        !          1098:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
        !          1099:     } else {
        !          1100:         set_float_rounding_mode(rounding_mode, &env->fp_status);
        !          1101:         FT0 = float64_round_to_int(FT0, &env->fp_status);
        !          1102:         /* Restore rounding mode from FPSCR */
        !          1103:         fpscr_set_rounding_mode();
        !          1104:     }
        !          1105: }
        !          1106: 
        !          1107: void do_frin (void)
        !          1108: {
        !          1109:     do_fri(float_round_nearest_even);
        !          1110: }
        !          1111: 
        !          1112: void do_friz (void)
        !          1113: {
        !          1114:     do_fri(float_round_to_zero);
        !          1115: }
        !          1116: 
        !          1117: void do_frip (void)
        !          1118: {
        !          1119:     do_fri(float_round_up);
        !          1120: }
        !          1121: 
        !          1122: void do_frim (void)
        !          1123: {
        !          1124:     do_fri(float_round_down);
        !          1125: }
        !          1126: 
        !          1127: #if USE_PRECISE_EMULATION
        !          1128: void do_fmadd (void)
        !          1129: {
        !          1130:     if (unlikely(float64_is_signaling_nan(FT0) ||
        !          1131:                  float64_is_signaling_nan(FT1) ||
        !          1132:                  float64_is_signaling_nan(FT2))) {
        !          1133:         /* sNaN operation */
        !          1134:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1135:     } else {
        !          1136: #ifdef FLOAT128
        !          1137:         /* This is the way the PowerPC specification defines it */
        !          1138:         float128 ft0_128, ft1_128;
        !          1139: 
        !          1140:         ft0_128 = float64_to_float128(FT0, &env->fp_status);
        !          1141:         ft1_128 = float64_to_float128(FT1, &env->fp_status);
        !          1142:         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
        !          1143:         ft1_128 = float64_to_float128(FT2, &env->fp_status);
        !          1144:         ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
        !          1145:         FT0 = float128_to_float64(ft0_128, &env->fp_status);
        !          1146: #else
        !          1147:         /* This is OK on x86 hosts */
        !          1148:         FT0 = (FT0 * FT1) + FT2;
        !          1149: #endif
        !          1150:     }
        !          1151: }
        !          1152: 
        !          1153: void do_fmsub (void)
        !          1154: {
        !          1155:     if (unlikely(float64_is_signaling_nan(FT0) ||
        !          1156:                  float64_is_signaling_nan(FT1) ||
        !          1157:                  float64_is_signaling_nan(FT2))) {
        !          1158:         /* sNaN operation */
        !          1159:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1160:     } else {
        !          1161: #ifdef FLOAT128
        !          1162:         /* This is the way the PowerPC specification defines it */
        !          1163:         float128 ft0_128, ft1_128;
        !          1164: 
        !          1165:         ft0_128 = float64_to_float128(FT0, &env->fp_status);
        !          1166:         ft1_128 = float64_to_float128(FT1, &env->fp_status);
        !          1167:         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
        !          1168:         ft1_128 = float64_to_float128(FT2, &env->fp_status);
        !          1169:         ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
        !          1170:         FT0 = float128_to_float64(ft0_128, &env->fp_status);
        !          1171: #else
        !          1172:         /* This is OK on x86 hosts */
        !          1173:         FT0 = (FT0 * FT1) - FT2;
        !          1174: #endif
        !          1175:     }
        !          1176: }
        !          1177: #endif /* USE_PRECISE_EMULATION */
        !          1178: 
        !          1179: void do_fnmadd (void)
        !          1180: {
        !          1181:     if (unlikely(float64_is_signaling_nan(FT0) ||
        !          1182:                  float64_is_signaling_nan(FT1) ||
        !          1183:                  float64_is_signaling_nan(FT2))) {
        !          1184:         /* sNaN operation */
        !          1185:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1186:     } else {
        !          1187: #if USE_PRECISE_EMULATION
        !          1188: #ifdef FLOAT128
        !          1189:         /* This is the way the PowerPC specification defines it */
        !          1190:         float128 ft0_128, ft1_128;
        !          1191: 
        !          1192:         ft0_128 = float64_to_float128(FT0, &env->fp_status);
        !          1193:         ft1_128 = float64_to_float128(FT1, &env->fp_status);
        !          1194:         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
        !          1195:         ft1_128 = float64_to_float128(FT2, &env->fp_status);
        !          1196:         ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
        !          1197:         FT0 = float128_to_float64(ft0_128, &env->fp_status);
        !          1198: #else
        !          1199:         /* This is OK on x86 hosts */
        !          1200:         FT0 = (FT0 * FT1) + FT2;
        !          1201: #endif
        !          1202: #else
        !          1203:         FT0 = float64_mul(FT0, FT1, &env->fp_status);
        !          1204:         FT0 = float64_add(FT0, FT2, &env->fp_status);
        !          1205: #endif
        !          1206:         if (likely(!isnan(FT0)))
        !          1207:             FT0 = float64_chs(FT0);
        !          1208:     }
        !          1209: }
        !          1210: 
        !          1211: void do_fnmsub (void)
        !          1212: {
        !          1213:     if (unlikely(float64_is_signaling_nan(FT0) ||
        !          1214:                  float64_is_signaling_nan(FT1) ||
        !          1215:                  float64_is_signaling_nan(FT2))) {
        !          1216:         /* sNaN operation */
        !          1217:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1218:     } else {
        !          1219: #if USE_PRECISE_EMULATION
        !          1220: #ifdef FLOAT128
        !          1221:         /* This is the way the PowerPC specification defines it */
        !          1222:         float128 ft0_128, ft1_128;
        !          1223: 
        !          1224:         ft0_128 = float64_to_float128(FT0, &env->fp_status);
        !          1225:         ft1_128 = float64_to_float128(FT1, &env->fp_status);
        !          1226:         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
        !          1227:         ft1_128 = float64_to_float128(FT2, &env->fp_status);
        !          1228:         ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
        !          1229:         FT0 = float128_to_float64(ft0_128, &env->fp_status);
        !          1230: #else
        !          1231:         /* This is OK on x86 hosts */
        !          1232:         FT0 = (FT0 * FT1) - FT2;
        !          1233: #endif
        !          1234: #else
        !          1235:         FT0 = float64_mul(FT0, FT1, &env->fp_status);
        !          1236:         FT0 = float64_sub(FT0, FT2, &env->fp_status);
        !          1237: #endif
        !          1238:         if (likely(!isnan(FT0)))
        !          1239:             FT0 = float64_chs(FT0);
        !          1240:     }
        !          1241: }
        !          1242: 
        !          1243: #if USE_PRECISE_EMULATION
        !          1244: void do_frsp (void)
        !          1245: {
        !          1246:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !          1247:         /* sNaN square root */
        !          1248:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1249:     } else {
        !          1250:         FT0 = float64_to_float32(FT0, &env->fp_status);
        !          1251:     }
        !          1252: }
        !          1253: #endif /* USE_PRECISE_EMULATION */
        !          1254: 
        !          1255: void do_fsqrt (void)
        !          1256: {
        !          1257:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !          1258:         /* sNaN square root */
        !          1259:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1260:     } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
        !          1261:         /* Square root of a negative nonzero number */
        !          1262:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
        !          1263:     } else {
        !          1264:         FT0 = float64_sqrt(FT0, &env->fp_status);
        !          1265:     }
        !          1266: }
        !          1267: 
        !          1268: void do_fre (void)
        !          1269: {
        !          1270:     union {
        !          1271:         double d;
        !          1272:         uint64_t i;
        !          1273:     } p;
        !          1274: 
        !          1275:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !          1276:         /* sNaN reciprocal */
        !          1277:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1278:     } else if (unlikely(iszero(FT0))) {
        !          1279:         /* Zero reciprocal */
        !          1280:         float_zero_divide_excp();
        !          1281:     } else if (likely(isnormal(FT0))) {
        !          1282:         FT0 = float64_div(1.0, FT0, &env->fp_status);
        !          1283:     } else {
        !          1284:         p.d = FT0;
        !          1285:         if (p.i == 0x8000000000000000ULL) {
        !          1286:             p.i = 0xFFF0000000000000ULL;
        !          1287:         } else if (p.i == 0x0000000000000000ULL) {
        !          1288:             p.i = 0x7FF0000000000000ULL;
        !          1289:         } else if (isnan(FT0)) {
        !          1290:             p.i = 0x7FF8000000000000ULL;
        !          1291:         } else if (fpisneg(FT0)) {
        !          1292:             p.i = 0x8000000000000000ULL;
        !          1293:         } else {
        !          1294:             p.i = 0x0000000000000000ULL;
        !          1295:         }
        !          1296:         FT0 = p.d;
        !          1297:     }
        !          1298: }
        !          1299: 
        !          1300: void do_fres (void)
        !          1301: {
        !          1302:     union {
        !          1303:         double d;
        !          1304:         uint64_t i;
        !          1305:     } p;
        !          1306: 
        !          1307:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !          1308:         /* sNaN reciprocal */
        !          1309:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1310:     } else if (unlikely(iszero(FT0))) {
        !          1311:         /* Zero reciprocal */
        !          1312:         float_zero_divide_excp();
        !          1313:     } else if (likely(isnormal(FT0))) {
        !          1314: #if USE_PRECISE_EMULATION
        !          1315:         FT0 = float64_div(1.0, FT0, &env->fp_status);
        !          1316:         FT0 = float64_to_float32(FT0, &env->fp_status);
        !          1317: #else
        !          1318:         FT0 = float32_div(1.0, FT0, &env->fp_status);
        !          1319: #endif
        !          1320:     } else {
        !          1321:         p.d = FT0;
        !          1322:         if (p.i == 0x8000000000000000ULL) {
        !          1323:             p.i = 0xFFF0000000000000ULL;
        !          1324:         } else if (p.i == 0x0000000000000000ULL) {
        !          1325:             p.i = 0x7FF0000000000000ULL;
        !          1326:         } else if (isnan(FT0)) {
        !          1327:             p.i = 0x7FF8000000000000ULL;
        !          1328:         } else if (fpisneg(FT0)) {
        !          1329:             p.i = 0x8000000000000000ULL;
        !          1330:         } else {
        !          1331:             p.i = 0x0000000000000000ULL;
        !          1332:         }
        !          1333:         FT0 = p.d;
        !          1334:     }
        !          1335: }
        !          1336: 
        !          1337: void do_frsqrte (void)
        !          1338: {
        !          1339:     union {
        !          1340:         double d;
        !          1341:         uint64_t i;
        !          1342:     } p;
        !          1343: 
        !          1344:     if (unlikely(float64_is_signaling_nan(FT0))) {
        !          1345:         /* sNaN reciprocal square root */
        !          1346:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1347:     } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
        !          1348:         /* Reciprocal square root of a negative nonzero number */
        !          1349:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
        !          1350:     } else if (likely(isnormal(FT0))) {
        !          1351:         FT0 = float64_sqrt(FT0, &env->fp_status);
        !          1352:         FT0 = float32_div(1.0, FT0, &env->fp_status);
        !          1353:     } else {
        !          1354:         p.d = FT0;
        !          1355:         if (p.i == 0x8000000000000000ULL) {
        !          1356:             p.i = 0xFFF0000000000000ULL;
        !          1357:         } else if (p.i == 0x0000000000000000ULL) {
        !          1358:             p.i = 0x7FF0000000000000ULL;
        !          1359:         } else if (isnan(FT0)) {
        !          1360:             p.i |= 0x000FFFFFFFFFFFFFULL;
        !          1361:         } else if (fpisneg(FT0)) {
        !          1362:             p.i = 0x7FF8000000000000ULL;
        !          1363:         } else {
        !          1364:             p.i = 0x0000000000000000ULL;
        !          1365:         }
        !          1366:         FT0 = p.d;
        !          1367:     }
        !          1368: }
        !          1369: 
        !          1370: void do_fsel (void)
        !          1371: {
        !          1372:     if (!fpisneg(FT0) || iszero(FT0))
        !          1373:         FT0 = FT1;
1.1       root     1374:     else
                   1375:         FT0 = FT2;
                   1376: }
                   1377: 
1.1.1.3 ! root     1378: void do_fcmpu (void)
        !          1379: {
        !          1380:     if (unlikely(float64_is_signaling_nan(FT0) ||
        !          1381:                  float64_is_signaling_nan(FT1))) {
        !          1382:         /* sNaN comparison */
        !          1383:         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
        !          1384:     } else {
        !          1385:         if (float64_lt(FT0, FT1, &env->fp_status)) {
        !          1386:             T0 = 0x08UL;
        !          1387:         } else if (!float64_le(FT0, FT1, &env->fp_status)) {
        !          1388:             T0 = 0x04UL;
        !          1389:         } else {
        !          1390:             T0 = 0x02UL;
        !          1391:         }
        !          1392:     }
        !          1393:     env->fpscr &= ~(0x0F << FPSCR_FPRF);
        !          1394:     env->fpscr |= T0 << FPSCR_FPRF;
        !          1395: }
        !          1396: 
        !          1397: void do_fcmpo (void)
        !          1398: {
        !          1399:     if (unlikely(float64_is_nan(FT0) ||
        !          1400:                  float64_is_nan(FT1))) {
        !          1401:         if (float64_is_signaling_nan(FT0) ||
        !          1402:             float64_is_signaling_nan(FT1)) {
        !          1403:             /* sNaN comparison */
        !          1404:             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
        !          1405:                                   POWERPC_EXCP_FP_VXVC);
        !          1406:         } else {
        !          1407:             /* qNaN comparison */
        !          1408:             fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
        !          1409:         }
        !          1410:     } else {
        !          1411:         if (float64_lt(FT0, FT1, &env->fp_status)) {
        !          1412:             T0 = 0x08UL;
        !          1413:         } else if (!float64_le(FT0, FT1, &env->fp_status)) {
        !          1414:             T0 = 0x04UL;
        !          1415:         } else {
        !          1416:             T0 = 0x02UL;
        !          1417:         }
        !          1418:     }
        !          1419:     env->fpscr &= ~(0x0F << FPSCR_FPRF);
        !          1420:     env->fpscr |= T0 << FPSCR_FPRF;
        !          1421: }
        !          1422: 
        !          1423: #if !defined (CONFIG_USER_ONLY)
        !          1424: void cpu_dump_rfi (target_ulong RA, target_ulong msr);
        !          1425: 
        !          1426: void do_store_msr (void)
        !          1427: {
        !          1428:     T0 = hreg_store_msr(env, T0, 0);
        !          1429:     if (T0 != 0) {
        !          1430:         env->interrupt_request |= CPU_INTERRUPT_EXITTB;
        !          1431:         do_raise_exception(T0);
        !          1432:     }
        !          1433: }
        !          1434: 
        !          1435: static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
        !          1436:                                     target_ulong msrm, int keep_msrh)
        !          1437: {
        !          1438: #if defined(TARGET_PPC64)
        !          1439:     if (msr & (1ULL << MSR_SF)) {
        !          1440:         nip = (uint64_t)nip;
        !          1441:         msr &= (uint64_t)msrm;
        !          1442:     } else {
        !          1443:         nip = (uint32_t)nip;
        !          1444:         msr = (uint32_t)(msr & msrm);
        !          1445:         if (keep_msrh)
        !          1446:             msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
        !          1447:     }
        !          1448: #else
        !          1449:     nip = (uint32_t)nip;
        !          1450:     msr &= (uint32_t)msrm;
        !          1451: #endif
        !          1452:     /* XXX: beware: this is false if VLE is supported */
        !          1453:     env->nip = nip & ~((target_ulong)0x00000003);
        !          1454:     hreg_store_msr(env, msr, 1);
        !          1455: #if defined (DEBUG_OP)
        !          1456:     cpu_dump_rfi(env->nip, env->msr);
        !          1457: #endif
        !          1458:     /* No need to raise an exception here,
        !          1459:      * as rfi is always the last insn of a TB
        !          1460:      */
        !          1461:     env->interrupt_request |= CPU_INTERRUPT_EXITTB;
        !          1462: }
        !          1463: 
        !          1464: void do_rfi (void)
        !          1465: {
        !          1466:     __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
        !          1467:              ~((target_ulong)0xFFFF0000), 1);
        !          1468: }
        !          1469: 
        !          1470: #if defined(TARGET_PPC64)
        !          1471: void do_rfid (void)
        !          1472: {
        !          1473:     __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
        !          1474:              ~((target_ulong)0xFFFF0000), 0);
        !          1475: }
        !          1476: 
        !          1477: void do_hrfid (void)
        !          1478: {
        !          1479:     __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
        !          1480:              ~((target_ulong)0xFFFF0000), 0);
        !          1481: }
        !          1482: #endif
        !          1483: #endif
        !          1484: 
        !          1485: void do_tw (int flags)
        !          1486: {
        !          1487:     if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
        !          1488:                   ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
        !          1489:                   ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
        !          1490:                   ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
        !          1491:                   ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
        !          1492:         do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
        !          1493:     }
        !          1494: }
        !          1495: 
        !          1496: #if defined(TARGET_PPC64)
        !          1497: void do_td (int flags)
        !          1498: {
        !          1499:     if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) ||
        !          1500:                   ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) ||
        !          1501:                   ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
        !          1502:                   ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
        !          1503:                   ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
        !          1504:         do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
        !          1505: }
        !          1506: #endif
        !          1507: 
        !          1508: /*****************************************************************************/
        !          1509: /* PowerPC 601 specific instructions (POWER bridge) */
        !          1510: void do_POWER_abso (void)
        !          1511: {
        !          1512:     if ((int32_t)T0 == INT32_MIN) {
        !          1513:         T0 = INT32_MAX;
        !          1514:         xer_ov = 1;
        !          1515:     } else if ((int32_t)T0 < 0) {
        !          1516:         T0 = -T0;
        !          1517:         xer_ov = 0;
        !          1518:     } else {
        !          1519:         xer_ov = 0;
        !          1520:     }
        !          1521:     xer_so |= xer_ov;
        !          1522: }
        !          1523: 
        !          1524: void do_POWER_clcs (void)
        !          1525: {
        !          1526:     switch (T0) {
        !          1527:     case 0x0CUL:
        !          1528:         /* Instruction cache line size */
        !          1529:         T0 = env->icache_line_size;
        !          1530:         break;
        !          1531:     case 0x0DUL:
        !          1532:         /* Data cache line size */
        !          1533:         T0 = env->dcache_line_size;
        !          1534:         break;
        !          1535:     case 0x0EUL:
        !          1536:         /* Minimum cache line size */
        !          1537:         T0 = env->icache_line_size < env->dcache_line_size ?
        !          1538:             env->icache_line_size : env->dcache_line_size;
        !          1539:         break;
        !          1540:     case 0x0FUL:
        !          1541:         /* Maximum cache line size */
        !          1542:         T0 = env->icache_line_size > env->dcache_line_size ?
        !          1543:             env->icache_line_size : env->dcache_line_size;
        !          1544:         break;
        !          1545:     default:
        !          1546:         /* Undefined */
        !          1547:         break;
        !          1548:     }
        !          1549: }
        !          1550: 
        !          1551: void do_POWER_div (void)
        !          1552: {
        !          1553:     uint64_t tmp;
        !          1554: 
        !          1555:     if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
        !          1556:         (int32_t)T1 == 0) {
        !          1557:         T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
        !          1558:         env->spr[SPR_MQ] = 0;
        !          1559:     } else {
        !          1560:         tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
        !          1561:         env->spr[SPR_MQ] = tmp % T1;
        !          1562:         T0 = tmp / (int32_t)T1;
        !          1563:     }
        !          1564: }
        !          1565: 
        !          1566: void do_POWER_divo (void)
        !          1567: {
        !          1568:     int64_t tmp;
        !          1569: 
        !          1570:     if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
        !          1571:         (int32_t)T1 == 0) {
        !          1572:         T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
        !          1573:         env->spr[SPR_MQ] = 0;
        !          1574:         xer_ov = 1;
        !          1575:     } else {
        !          1576:         tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
        !          1577:         env->spr[SPR_MQ] = tmp % T1;
        !          1578:         tmp /= (int32_t)T1;
        !          1579:         if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
        !          1580:             xer_ov = 1;
        !          1581:         } else {
        !          1582:             xer_ov = 0;
        !          1583:         }
        !          1584:         T0 = tmp;
        !          1585:     }
        !          1586:     xer_so |= xer_ov;
        !          1587: }
        !          1588: 
        !          1589: void do_POWER_divs (void)
        !          1590: {
        !          1591:     if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
        !          1592:         (int32_t)T1 == 0) {
        !          1593:         T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
        !          1594:         env->spr[SPR_MQ] = 0;
        !          1595:     } else {
        !          1596:         env->spr[SPR_MQ] = T0 % T1;
        !          1597:         T0 = (int32_t)T0 / (int32_t)T1;
        !          1598:     }
        !          1599: }
        !          1600: 
        !          1601: void do_POWER_divso (void)
        !          1602: {
        !          1603:     if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
        !          1604:         (int32_t)T1 == 0) {
        !          1605:         T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
        !          1606:         env->spr[SPR_MQ] = 0;
        !          1607:         xer_ov = 1;
        !          1608:     } else {
        !          1609:         T0 = (int32_t)T0 / (int32_t)T1;
        !          1610:         env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
        !          1611:         xer_ov = 0;
        !          1612:     }
        !          1613:     xer_so |= xer_ov;
        !          1614: }
        !          1615: 
        !          1616: void do_POWER_dozo (void)
        !          1617: {
        !          1618:     if ((int32_t)T1 > (int32_t)T0) {
        !          1619:         T2 = T0;
        !          1620:         T0 = T1 - T0;
        !          1621:         if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
        !          1622:             ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
        !          1623:             xer_ov = 1;
        !          1624:             xer_so = 1;
        !          1625:         } else {
        !          1626:             xer_ov = 0;
        !          1627:         }
        !          1628:     } else {
        !          1629:         T0 = 0;
        !          1630:         xer_ov = 0;
        !          1631:     }
        !          1632: }
        !          1633: 
        !          1634: void do_POWER_maskg (void)
        !          1635: {
        !          1636:     uint32_t ret;
        !          1637: 
        !          1638:     if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
        !          1639:         ret = UINT32_MAX;
        !          1640:     } else {
        !          1641:         ret = (UINT32_MAX >> ((uint32_t)T0)) ^
        !          1642:             ((UINT32_MAX >> ((uint32_t)T1)) >> 1);
        !          1643:         if ((uint32_t)T0 > (uint32_t)T1)
        !          1644:             ret = ~ret;
        !          1645:     }
        !          1646:     T0 = ret;
        !          1647: }
        !          1648: 
        !          1649: void do_POWER_mulo (void)
        !          1650: {
        !          1651:     uint64_t tmp;
        !          1652: 
        !          1653:     tmp = (uint64_t)T0 * (uint64_t)T1;
        !          1654:     env->spr[SPR_MQ] = tmp >> 32;
        !          1655:     T0 = tmp;
        !          1656:     if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
        !          1657:         xer_ov = 1;
        !          1658:         xer_so = 1;
        !          1659:     } else {
        !          1660:         xer_ov = 0;
        !          1661:     }
        !          1662: }
        !          1663: 
        !          1664: #if !defined (CONFIG_USER_ONLY)
        !          1665: void do_POWER_rac (void)
        !          1666: {
        !          1667:     mmu_ctx_t ctx;
        !          1668:     int nb_BATs;
        !          1669: 
        !          1670:     /* We don't have to generate many instances of this instruction,
        !          1671:      * as rac is supervisor only.
        !          1672:      */
        !          1673:     /* XXX: FIX THIS: Pretend we have no BAT */
        !          1674:     nb_BATs = env->nb_BATs;
        !          1675:     env->nb_BATs = 0;
        !          1676:     if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT) == 0)
        !          1677:         T0 = ctx.raddr;
        !          1678:     env->nb_BATs = nb_BATs;
        !          1679: }
        !          1680: 
        !          1681: void do_POWER_rfsvc (void)
        !          1682: {
        !          1683:     __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
        !          1684: }
        !          1685: 
        !          1686: void do_store_hid0_601 (void)
        !          1687: {
        !          1688:     uint32_t hid0;
        !          1689: 
        !          1690:     hid0 = env->spr[SPR_HID0];
        !          1691:     if ((T0 ^ hid0) & 0x00000008) {
        !          1692:         /* Change current endianness */
        !          1693:         env->hflags &= ~(1 << MSR_LE);
        !          1694:         env->hflags_nmsr &= ~(1 << MSR_LE);
        !          1695:         env->hflags_nmsr |= (1 << MSR_LE) & (((T0 >> 3) & 1) << MSR_LE);
        !          1696:         env->hflags |= env->hflags_nmsr;
        !          1697:         if (loglevel != 0) {
        !          1698:             fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
        !          1699:                     __func__, T0 & 0x8 ? 'l' : 'b', env->hflags);
        !          1700:         }
        !          1701:     }
        !          1702:     env->spr[SPR_HID0] = T0;
        !          1703: }
        !          1704: #endif
        !          1705: 
        !          1706: /*****************************************************************************/
        !          1707: /* 602 specific instructions */
        !          1708: /* mfrom is the most crazy instruction ever seen, imho ! */
        !          1709: /* Real implementation uses a ROM table. Do the same */
        !          1710: #define USE_MFROM_ROM_TABLE
        !          1711: void do_op_602_mfrom (void)
        !          1712: {
        !          1713:     if (likely(T0 < 602)) {
        !          1714: #if defined(USE_MFROM_ROM_TABLE)
        !          1715: #include "mfrom_table.c"
        !          1716:         T0 = mfrom_ROM_table[T0];
        !          1717: #else
        !          1718:         double d;
        !          1719:         /* Extremly decomposed:
        !          1720:          *                    -T0 / 256
        !          1721:          * T0 = 256 * log10(10          + 1.0) + 0.5
        !          1722:          */
        !          1723:         d = T0;
        !          1724:         d = float64_div(d, 256, &env->fp_status);
        !          1725:         d = float64_chs(d);
        !          1726:         d = exp10(d); // XXX: use float emulation function
        !          1727:         d = float64_add(d, 1.0, &env->fp_status);
        !          1728:         d = log10(d); // XXX: use float emulation function
        !          1729:         d = float64_mul(d, 256, &env->fp_status);
        !          1730:         d = float64_add(d, 0.5, &env->fp_status);
        !          1731:         T0 = float64_round_to_int(d, &env->fp_status);
        !          1732: #endif
        !          1733:     } else {
        !          1734:         T0 = 0;
        !          1735:     }
        !          1736: }
        !          1737: 
        !          1738: /*****************************************************************************/
        !          1739: /* Embedded PowerPC specific helpers */
        !          1740: void do_405_check_sat (void)
        !          1741: {
        !          1742:     if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
        !          1743:                 !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
        !          1744:         /* Saturate result */
        !          1745:         if (T2 >> 31) {
        !          1746:             T0 = INT32_MIN;
        !          1747:         } else {
        !          1748:             T0 = INT32_MAX;
        !          1749:         }
        !          1750:     }
        !          1751: }
        !          1752: 
        !          1753: /* XXX: to be improved to check access rights when in user-mode */
        !          1754: void do_load_dcr (void)
        !          1755: {
        !          1756:     target_ulong val;
        !          1757: 
        !          1758:     if (unlikely(env->dcr_env == NULL)) {
        !          1759:         if (loglevel != 0) {
        !          1760:             fprintf(logfile, "No DCR environment\n");
        !          1761:         }
        !          1762:         do_raise_exception_err(POWERPC_EXCP_PROGRAM,
        !          1763:                                POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
        !          1764:     } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
        !          1765:         if (loglevel != 0) {
        !          1766:             fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
        !          1767:         }
        !          1768:         do_raise_exception_err(POWERPC_EXCP_PROGRAM,
        !          1769:                                POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
        !          1770:     } else {
        !          1771:         T0 = val;
        !          1772:     }
        !          1773: }
        !          1774: 
        !          1775: void do_store_dcr (void)
        !          1776: {
        !          1777:     if (unlikely(env->dcr_env == NULL)) {
        !          1778:         if (loglevel != 0) {
        !          1779:             fprintf(logfile, "No DCR environment\n");
        !          1780:         }
        !          1781:         do_raise_exception_err(POWERPC_EXCP_PROGRAM,
        !          1782:                                POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
        !          1783:     } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
        !          1784:         if (loglevel != 0) {
        !          1785:             fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
        !          1786:         }
        !          1787:         do_raise_exception_err(POWERPC_EXCP_PROGRAM,
        !          1788:                                POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
        !          1789:     }
        !          1790: }
        !          1791: 
        !          1792: #if !defined(CONFIG_USER_ONLY)
        !          1793: void do_40x_rfci (void)
        !          1794: {
        !          1795:     __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
        !          1796:              ~((target_ulong)0xFFFF0000), 0);
        !          1797: }
        !          1798: 
        !          1799: void do_rfci (void)
        !          1800: {
        !          1801:     __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
        !          1802:              ~((target_ulong)0x3FFF0000), 0);
        !          1803: }
        !          1804: 
        !          1805: void do_rfdi (void)
        !          1806: {
        !          1807:     __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
        !          1808:              ~((target_ulong)0x3FFF0000), 0);
        !          1809: }
        !          1810: 
        !          1811: void do_rfmci (void)
        !          1812: {
        !          1813:     __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
        !          1814:              ~((target_ulong)0x3FFF0000), 0);
        !          1815: }
        !          1816: 
        !          1817: void do_load_403_pb (int num)
        !          1818: {
        !          1819:     T0 = env->pb[num];
        !          1820: }
        !          1821: 
        !          1822: void do_store_403_pb (int num)
        !          1823: {
        !          1824:     if (likely(env->pb[num] != T0)) {
        !          1825:         env->pb[num] = T0;
        !          1826:         /* Should be optimized */
        !          1827:         tlb_flush(env, 1);
        !          1828:     }
        !          1829: }
        !          1830: #endif
        !          1831: 
        !          1832: /* 440 specific */
        !          1833: void do_440_dlmzb (void)
        !          1834: {
        !          1835:     target_ulong mask;
        !          1836:     int i;
        !          1837: 
        !          1838:     i = 1;
        !          1839:     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
        !          1840:         if ((T0 & mask) == 0)
        !          1841:             goto done;
        !          1842:         i++;
        !          1843:     }
        !          1844:     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
        !          1845:         if ((T1 & mask) == 0)
        !          1846:             break;
        !          1847:         i++;
        !          1848:     }
        !          1849:  done:
        !          1850:     T0 = i;
        !          1851: }
        !          1852: 
        !          1853: /* SPE extension helpers */
        !          1854: /* Use a table to make this quicker */
        !          1855: static uint8_t hbrev[16] = {
        !          1856:     0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
        !          1857:     0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
        !          1858: };
        !          1859: 
        !          1860: static always_inline uint8_t byte_reverse (uint8_t val)
        !          1861: {
        !          1862:     return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
        !          1863: }
        !          1864: 
        !          1865: static always_inline uint32_t word_reverse (uint32_t val)
        !          1866: {
        !          1867:     return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
        !          1868:         (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
        !          1869: }
        !          1870: 
        !          1871: #define MASKBITS 16 // Random value - to be fixed (implementation dependant)
        !          1872: void do_brinc (void)
        !          1873: {
        !          1874:     uint32_t a, b, d, mask;
        !          1875: 
        !          1876:     mask = UINT32_MAX >> (32 - MASKBITS);
        !          1877:     a = T0 & mask;
        !          1878:     b = T1 & mask;
        !          1879:     d = word_reverse(1 + word_reverse(a | ~b));
        !          1880:     T0 = (T0 & ~mask) | (d & b);
        !          1881: }
        !          1882: 
        !          1883: #define DO_SPE_OP2(name)                                                      \
        !          1884: void do_ev##name (void)                                                       \
        !          1885: {                                                                             \
        !          1886:     T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) |         \
        !          1887:         (uint64_t)_do_e##name(T0_64, T1_64);                                  \
        !          1888: }
        !          1889: 
        !          1890: #define DO_SPE_OP1(name)                                                      \
        !          1891: void do_ev##name (void)                                                       \
        !          1892: {                                                                             \
        !          1893:     T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) |                      \
        !          1894:         (uint64_t)_do_e##name(T0_64);                                         \
        !          1895: }
        !          1896: 
        !          1897: /* Fixed-point vector arithmetic */
        !          1898: static always_inline uint32_t _do_eabs (uint32_t val)
        !          1899: {
        !          1900:     if ((val & 0x80000000) && val != 0x80000000)
        !          1901:         val -= val;
        !          1902: 
        !          1903:     return val;
        !          1904: }
        !          1905: 
        !          1906: static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
        !          1907: {
        !          1908:     return op1 + op2;
        !          1909: }
        !          1910: 
        !          1911: static always_inline int _do_ecntlsw (uint32_t val)
        !          1912: {
        !          1913:     if (val & 0x80000000)
        !          1914:         return clz32(~val);
        !          1915:     else
        !          1916:         return clz32(val);
        !          1917: }
        !          1918: 
        !          1919: static always_inline int _do_ecntlzw (uint32_t val)
        !          1920: {
        !          1921:     return clz32(val);
        !          1922: }
        !          1923: 
        !          1924: static always_inline uint32_t _do_eneg (uint32_t val)
        !          1925: {
        !          1926:     if (val != 0x80000000)
        !          1927:         val -= val;
        !          1928: 
        !          1929:     return val;
        !          1930: }
        !          1931: 
        !          1932: static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
        !          1933: {
        !          1934:     return rotl32(op1, op2);
        !          1935: }
        !          1936: 
        !          1937: static always_inline uint32_t _do_erndw (uint32_t val)
        !          1938: {
        !          1939:     return (val + 0x000080000000) & 0xFFFF0000;
        !          1940: }
        !          1941: 
        !          1942: static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
        !          1943: {
        !          1944:     /* No error here: 6 bits are used */
        !          1945:     return op1 << (op2 & 0x3F);
        !          1946: }
        !          1947: 
        !          1948: static always_inline int32_t _do_esrws (int32_t op1, uint32_t op2)
        !          1949: {
        !          1950:     /* No error here: 6 bits are used */
        !          1951:     return op1 >> (op2 & 0x3F);
        !          1952: }
        !          1953: 
        !          1954: static always_inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
        !          1955: {
        !          1956:     /* No error here: 6 bits are used */
        !          1957:     return op1 >> (op2 & 0x3F);
        !          1958: }
        !          1959: 
        !          1960: static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
        !          1961: {
        !          1962:     return op2 - op1;
        !          1963: }
        !          1964: 
        !          1965: /* evabs */
        !          1966: DO_SPE_OP1(abs);
        !          1967: /* evaddw */
        !          1968: DO_SPE_OP2(addw);
        !          1969: /* evcntlsw */
        !          1970: DO_SPE_OP1(cntlsw);
        !          1971: /* evcntlzw */
        !          1972: DO_SPE_OP1(cntlzw);
        !          1973: /* evneg */
        !          1974: DO_SPE_OP1(neg);
        !          1975: /* evrlw */
        !          1976: DO_SPE_OP2(rlw);
        !          1977: /* evrnd */
        !          1978: DO_SPE_OP1(rndw);
        !          1979: /* evslw */
        !          1980: DO_SPE_OP2(slw);
        !          1981: /* evsrws */
        !          1982: DO_SPE_OP2(srws);
        !          1983: /* evsrwu */
        !          1984: DO_SPE_OP2(srwu);
        !          1985: /* evsubfw */
        !          1986: DO_SPE_OP2(subfw);
        !          1987: 
        !          1988: /* evsel is a little bit more complicated... */
        !          1989: static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
        !          1990: {
        !          1991:     if (n)
        !          1992:         return op1;
        !          1993:     else
        !          1994:         return op2;
        !          1995: }
        !          1996: 
        !          1997: void do_evsel (void)
        !          1998: {
        !          1999:     T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
        !          2000:         (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
        !          2001: }
        !          2002: 
        !          2003: /* Fixed-point vector comparisons */
        !          2004: #define DO_SPE_CMP(name)                                                      \
        !          2005: void do_ev##name (void)                                                       \
        !          2006: {                                                                             \
        !          2007:     T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32,                   \
        !          2008:                                                T1_64 >> 32) << 32,            \
        !          2009:                          _do_e##name(T0_64, T1_64));                          \
        !          2010: }
        !          2011: 
        !          2012: static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
        !          2013: {
        !          2014:     return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
        !          2015: }
        !          2016: static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
        !          2017: {
        !          2018:     return op1 == op2 ? 1 : 0;
        !          2019: }
        !          2020: 
        !          2021: static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
        !          2022: {
        !          2023:     return op1 > op2 ? 1 : 0;
        !          2024: }
        !          2025: 
        !          2026: static always_inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
        !          2027: {
        !          2028:     return op1 > op2 ? 1 : 0;
        !          2029: }
        !          2030: 
        !          2031: static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
        !          2032: {
        !          2033:     return op1 < op2 ? 1 : 0;
        !          2034: }
        !          2035: 
        !          2036: static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
        !          2037: {
        !          2038:     return op1 < op2 ? 1 : 0;
        !          2039: }
        !          2040: 
        !          2041: /* evcmpeq */
        !          2042: DO_SPE_CMP(cmpeq);
        !          2043: /* evcmpgts */
        !          2044: DO_SPE_CMP(cmpgts);
        !          2045: /* evcmpgtu */
        !          2046: DO_SPE_CMP(cmpgtu);
        !          2047: /* evcmplts */
        !          2048: DO_SPE_CMP(cmplts);
        !          2049: /* evcmpltu */
        !          2050: DO_SPE_CMP(cmpltu);
        !          2051: 
        !          2052: /* Single precision floating-point conversions from/to integer */
        !          2053: static always_inline uint32_t _do_efscfsi (int32_t val)
        !          2054: {
        !          2055:     union {
        !          2056:         uint32_t u;
        !          2057:         float32 f;
        !          2058:     } u;
        !          2059: 
        !          2060:     u.f = int32_to_float32(val, &env->spe_status);
        !          2061: 
        !          2062:     return u.u;
        !          2063: }
        !          2064: 
        !          2065: static always_inline uint32_t _do_efscfui (uint32_t val)
        !          2066: {
        !          2067:     union {
        !          2068:         uint32_t u;
        !          2069:         float32 f;
        !          2070:     } u;
        !          2071: 
        !          2072:     u.f = uint32_to_float32(val, &env->spe_status);
        !          2073: 
        !          2074:     return u.u;
        !          2075: }
        !          2076: 
        !          2077: static always_inline int32_t _do_efsctsi (uint32_t val)
        !          2078: {
        !          2079:     union {
        !          2080:         int32_t u;
        !          2081:         float32 f;
        !          2082:     } u;
        !          2083: 
        !          2084:     u.u = val;
        !          2085:     /* NaN are not treated the same way IEEE 754 does */
        !          2086:     if (unlikely(isnan(u.f)))
        !          2087:         return 0;
        !          2088: 
        !          2089:     return float32_to_int32(u.f, &env->spe_status);
        !          2090: }
        !          2091: 
        !          2092: static always_inline uint32_t _do_efsctui (uint32_t val)
        !          2093: {
        !          2094:     union {
        !          2095:         int32_t u;
        !          2096:         float32 f;
        !          2097:     } u;
        !          2098: 
        !          2099:     u.u = val;
        !          2100:     /* NaN are not treated the same way IEEE 754 does */
        !          2101:     if (unlikely(isnan(u.f)))
        !          2102:         return 0;
        !          2103: 
        !          2104:     return float32_to_uint32(u.f, &env->spe_status);
        !          2105: }
        !          2106: 
        !          2107: static always_inline int32_t _do_efsctsiz (uint32_t val)
        !          2108: {
        !          2109:     union {
        !          2110:         int32_t u;
        !          2111:         float32 f;
        !          2112:     } u;
        !          2113: 
        !          2114:     u.u = val;
        !          2115:     /* NaN are not treated the same way IEEE 754 does */
        !          2116:     if (unlikely(isnan(u.f)))
        !          2117:         return 0;
        !          2118: 
        !          2119:     return float32_to_int32_round_to_zero(u.f, &env->spe_status);
        !          2120: }
        !          2121: 
        !          2122: static always_inline uint32_t _do_efsctuiz (uint32_t val)
        !          2123: {
        !          2124:     union {
        !          2125:         int32_t u;
        !          2126:         float32 f;
        !          2127:     } u;
        !          2128: 
        !          2129:     u.u = val;
        !          2130:     /* NaN are not treated the same way IEEE 754 does */
        !          2131:     if (unlikely(isnan(u.f)))
        !          2132:         return 0;
        !          2133: 
        !          2134:     return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
        !          2135: }
        !          2136: 
        !          2137: void do_efscfsi (void)
        !          2138: {
        !          2139:     T0_64 = _do_efscfsi(T0_64);
        !          2140: }
        !          2141: 
        !          2142: void do_efscfui (void)
        !          2143: {
        !          2144:     T0_64 = _do_efscfui(T0_64);
        !          2145: }
        !          2146: 
        !          2147: void do_efsctsi (void)
        !          2148: {
        !          2149:     T0_64 = _do_efsctsi(T0_64);
        !          2150: }
        !          2151: 
        !          2152: void do_efsctui (void)
        !          2153: {
        !          2154:     T0_64 = _do_efsctui(T0_64);
        !          2155: }
        !          2156: 
        !          2157: void do_efsctsiz (void)
        !          2158: {
        !          2159:     T0_64 = _do_efsctsiz(T0_64);
        !          2160: }
        !          2161: 
        !          2162: void do_efsctuiz (void)
        !          2163: {
        !          2164:     T0_64 = _do_efsctuiz(T0_64);
        !          2165: }
        !          2166: 
        !          2167: /* Single precision floating-point conversion to/from fractional */
        !          2168: static always_inline uint32_t _do_efscfsf (uint32_t val)
        !          2169: {
        !          2170:     union {
        !          2171:         uint32_t u;
        !          2172:         float32 f;
        !          2173:     } u;
        !          2174:     float32 tmp;
        !          2175: 
        !          2176:     u.f = int32_to_float32(val, &env->spe_status);
        !          2177:     tmp = int64_to_float32(1ULL << 32, &env->spe_status);
        !          2178:     u.f = float32_div(u.f, tmp, &env->spe_status);
        !          2179: 
        !          2180:     return u.u;
        !          2181: }
        !          2182: 
        !          2183: static always_inline uint32_t _do_efscfuf (uint32_t val)
        !          2184: {
        !          2185:     union {
        !          2186:         uint32_t u;
        !          2187:         float32 f;
        !          2188:     } u;
        !          2189:     float32 tmp;
        !          2190: 
        !          2191:     u.f = uint32_to_float32(val, &env->spe_status);
        !          2192:     tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
        !          2193:     u.f = float32_div(u.f, tmp, &env->spe_status);
        !          2194: 
        !          2195:     return u.u;
        !          2196: }
        !          2197: 
        !          2198: static always_inline int32_t _do_efsctsf (uint32_t val)
        !          2199: {
        !          2200:     union {
        !          2201:         int32_t u;
        !          2202:         float32 f;
        !          2203:     } u;
        !          2204:     float32 tmp;
        !          2205: 
        !          2206:     u.u = val;
        !          2207:     /* NaN are not treated the same way IEEE 754 does */
        !          2208:     if (unlikely(isnan(u.f)))
        !          2209:         return 0;
        !          2210:     tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
        !          2211:     u.f = float32_mul(u.f, tmp, &env->spe_status);
        !          2212: 
        !          2213:     return float32_to_int32(u.f, &env->spe_status);
        !          2214: }
        !          2215: 
        !          2216: static always_inline uint32_t _do_efsctuf (uint32_t val)
        !          2217: {
        !          2218:     union {
        !          2219:         int32_t u;
        !          2220:         float32 f;
        !          2221:     } u;
        !          2222:     float32 tmp;
        !          2223: 
        !          2224:     u.u = val;
        !          2225:     /* NaN are not treated the same way IEEE 754 does */
        !          2226:     if (unlikely(isnan(u.f)))
        !          2227:         return 0;
        !          2228:     tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
        !          2229:     u.f = float32_mul(u.f, tmp, &env->spe_status);
        !          2230: 
        !          2231:     return float32_to_uint32(u.f, &env->spe_status);
        !          2232: }
        !          2233: 
        !          2234: static always_inline int32_t _do_efsctsfz (uint32_t val)
        !          2235: {
        !          2236:     union {
        !          2237:         int32_t u;
        !          2238:         float32 f;
        !          2239:     } u;
        !          2240:     float32 tmp;
        !          2241: 
        !          2242:     u.u = val;
        !          2243:     /* NaN are not treated the same way IEEE 754 does */
        !          2244:     if (unlikely(isnan(u.f)))
        !          2245:         return 0;
        !          2246:     tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
        !          2247:     u.f = float32_mul(u.f, tmp, &env->spe_status);
        !          2248: 
        !          2249:     return float32_to_int32_round_to_zero(u.f, &env->spe_status);
        !          2250: }
        !          2251: 
        !          2252: static always_inline uint32_t _do_efsctufz (uint32_t val)
        !          2253: {
        !          2254:     union {
        !          2255:         int32_t u;
        !          2256:         float32 f;
        !          2257:     } u;
        !          2258:     float32 tmp;
        !          2259: 
        !          2260:     u.u = val;
        !          2261:     /* NaN are not treated the same way IEEE 754 does */
        !          2262:     if (unlikely(isnan(u.f)))
        !          2263:         return 0;
        !          2264:     tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
        !          2265:     u.f = float32_mul(u.f, tmp, &env->spe_status);
        !          2266: 
        !          2267:     return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
        !          2268: }
        !          2269: 
        !          2270: void do_efscfsf (void)
        !          2271: {
        !          2272:     T0_64 = _do_efscfsf(T0_64);
        !          2273: }
        !          2274: 
        !          2275: void do_efscfuf (void)
1.1       root     2276: {
1.1.1.3 ! root     2277:     T0_64 = _do_efscfuf(T0_64);
1.1       root     2278: }
                   2279: 
1.1.1.3 ! root     2280: void do_efsctsf (void)
1.1       root     2281: {
1.1.1.3 ! root     2282:     T0_64 = _do_efsctsf(T0_64);
1.1       root     2283: }
                   2284: 
1.1.1.3 ! root     2285: void do_efsctuf (void)
1.1       root     2286: {
1.1.1.3 ! root     2287:     T0_64 = _do_efsctuf(T0_64);
1.1       root     2288: }
                   2289: 
1.1.1.3 ! root     2290: void do_efsctsfz (void)
1.1       root     2291: {
1.1.1.3 ! root     2292:     T0_64 = _do_efsctsfz(T0_64);
1.1       root     2293: }
                   2294: 
1.1.1.3 ! root     2295: void do_efsctufz (void)
1.1       root     2296: {
1.1.1.3 ! root     2297:     T0_64 = _do_efsctufz(T0_64);
1.1       root     2298: }
                   2299: 
1.1.1.3 ! root     2300: /* Double precision floating point helpers */
        !          2301: static always_inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
1.1       root     2302: {
1.1.1.3 ! root     2303:     /* XXX: TODO: test special values (NaN, infinites, ...) */
        !          2304:     return _do_efdtstlt(op1, op2);
        !          2305: }
        !          2306: 
        !          2307: static always_inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
        !          2308: {
        !          2309:     /* XXX: TODO: test special values (NaN, infinites, ...) */
        !          2310:     return _do_efdtstgt(op1, op2);
        !          2311: }
        !          2312: 
        !          2313: static always_inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
        !          2314: {
        !          2315:     /* XXX: TODO: test special values (NaN, infinites, ...) */
        !          2316:     return _do_efdtsteq(op1, op2);
        !          2317: }
        !          2318: 
        !          2319: void do_efdcmplt (void)
        !          2320: {
        !          2321:     T0 = _do_efdcmplt(T0_64, T1_64);
        !          2322: }
        !          2323: 
        !          2324: void do_efdcmpgt (void)
        !          2325: {
        !          2326:     T0 = _do_efdcmpgt(T0_64, T1_64);
        !          2327: }
        !          2328: 
        !          2329: void do_efdcmpeq (void)
        !          2330: {
        !          2331:     T0 = _do_efdcmpeq(T0_64, T1_64);
        !          2332: }
        !          2333: 
        !          2334: /* Double precision floating-point conversion to/from integer */
        !          2335: static always_inline uint64_t _do_efdcfsi (int64_t val)
        !          2336: {
        !          2337:     union {
        !          2338:         uint64_t u;
        !          2339:         float64 f;
        !          2340:     } u;
        !          2341: 
        !          2342:     u.f = int64_to_float64(val, &env->spe_status);
        !          2343: 
        !          2344:     return u.u;
        !          2345: }
        !          2346: 
        !          2347: static always_inline uint64_t _do_efdcfui (uint64_t val)
        !          2348: {
        !          2349:     union {
        !          2350:         uint64_t u;
        !          2351:         float64 f;
        !          2352:     } u;
        !          2353: 
        !          2354:     u.f = uint64_to_float64(val, &env->spe_status);
        !          2355: 
        !          2356:     return u.u;
        !          2357: }
        !          2358: 
        !          2359: static always_inline int64_t _do_efdctsi (uint64_t val)
        !          2360: {
        !          2361:     union {
        !          2362:         int64_t u;
        !          2363:         float64 f;
        !          2364:     } u;
        !          2365: 
        !          2366:     u.u = val;
        !          2367:     /* NaN are not treated the same way IEEE 754 does */
        !          2368:     if (unlikely(isnan(u.f)))
        !          2369:         return 0;
        !          2370: 
        !          2371:     return float64_to_int64(u.f, &env->spe_status);
        !          2372: }
        !          2373: 
        !          2374: static always_inline uint64_t _do_efdctui (uint64_t val)
        !          2375: {
        !          2376:     union {
        !          2377:         int64_t u;
        !          2378:         float64 f;
        !          2379:     } u;
        !          2380: 
        !          2381:     u.u = val;
        !          2382:     /* NaN are not treated the same way IEEE 754 does */
        !          2383:     if (unlikely(isnan(u.f)))
        !          2384:         return 0;
        !          2385: 
        !          2386:     return float64_to_uint64(u.f, &env->spe_status);
        !          2387: }
        !          2388: 
        !          2389: static always_inline int64_t _do_efdctsiz (uint64_t val)
        !          2390: {
        !          2391:     union {
        !          2392:         int64_t u;
        !          2393:         float64 f;
        !          2394:     } u;
        !          2395: 
        !          2396:     u.u = val;
        !          2397:     /* NaN are not treated the same way IEEE 754 does */
        !          2398:     if (unlikely(isnan(u.f)))
        !          2399:         return 0;
        !          2400: 
        !          2401:     return float64_to_int64_round_to_zero(u.f, &env->spe_status);
        !          2402: }
        !          2403: 
        !          2404: static always_inline uint64_t _do_efdctuiz (uint64_t val)
        !          2405: {
        !          2406:     union {
        !          2407:         int64_t u;
        !          2408:         float64 f;
        !          2409:     } u;
        !          2410: 
        !          2411:     u.u = val;
        !          2412:     /* NaN are not treated the same way IEEE 754 does */
        !          2413:     if (unlikely(isnan(u.f)))
        !          2414:         return 0;
        !          2415: 
        !          2416:     return float64_to_uint64_round_to_zero(u.f, &env->spe_status);
        !          2417: }
        !          2418: 
        !          2419: void do_efdcfsi (void)
        !          2420: {
        !          2421:     T0_64 = _do_efdcfsi(T0_64);
        !          2422: }
        !          2423: 
        !          2424: void do_efdcfui (void)
        !          2425: {
        !          2426:     T0_64 = _do_efdcfui(T0_64);
        !          2427: }
        !          2428: 
        !          2429: void do_efdctsi (void)
        !          2430: {
        !          2431:     T0_64 = _do_efdctsi(T0_64);
        !          2432: }
        !          2433: 
        !          2434: void do_efdctui (void)
        !          2435: {
        !          2436:     T0_64 = _do_efdctui(T0_64);
        !          2437: }
        !          2438: 
        !          2439: void do_efdctsiz (void)
        !          2440: {
        !          2441:     T0_64 = _do_efdctsiz(T0_64);
        !          2442: }
        !          2443: 
        !          2444: void do_efdctuiz (void)
        !          2445: {
        !          2446:     T0_64 = _do_efdctuiz(T0_64);
        !          2447: }
        !          2448: 
        !          2449: /* Double precision floating-point conversion to/from fractional */
        !          2450: static always_inline uint64_t _do_efdcfsf (int64_t val)
        !          2451: {
        !          2452:     union {
        !          2453:         uint64_t u;
        !          2454:         float64 f;
        !          2455:     } u;
        !          2456:     float64 tmp;
        !          2457: 
        !          2458:     u.f = int32_to_float64(val, &env->spe_status);
        !          2459:     tmp = int64_to_float64(1ULL << 32, &env->spe_status);
        !          2460:     u.f = float64_div(u.f, tmp, &env->spe_status);
        !          2461: 
        !          2462:     return u.u;
        !          2463: }
        !          2464: 
        !          2465: static always_inline uint64_t _do_efdcfuf (uint64_t val)
        !          2466: {
        !          2467:     union {
        !          2468:         uint64_t u;
        !          2469:         float64 f;
        !          2470:     } u;
        !          2471:     float64 tmp;
        !          2472: 
        !          2473:     u.f = uint32_to_float64(val, &env->spe_status);
        !          2474:     tmp = int64_to_float64(1ULL << 32, &env->spe_status);
        !          2475:     u.f = float64_div(u.f, tmp, &env->spe_status);
        !          2476: 
        !          2477:     return u.u;
        !          2478: }
        !          2479: 
        !          2480: static always_inline int64_t _do_efdctsf (uint64_t val)
        !          2481: {
        !          2482:     union {
        !          2483:         int64_t u;
        !          2484:         float64 f;
        !          2485:     } u;
        !          2486:     float64 tmp;
        !          2487: 
        !          2488:     u.u = val;
        !          2489:     /* NaN are not treated the same way IEEE 754 does */
        !          2490:     if (unlikely(isnan(u.f)))
        !          2491:         return 0;
        !          2492:     tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
        !          2493:     u.f = float64_mul(u.f, tmp, &env->spe_status);
        !          2494: 
        !          2495:     return float64_to_int32(u.f, &env->spe_status);
        !          2496: }
        !          2497: 
        !          2498: static always_inline uint64_t _do_efdctuf (uint64_t val)
        !          2499: {
        !          2500:     union {
        !          2501:         int64_t u;
        !          2502:         float64 f;
        !          2503:     } u;
        !          2504:     float64 tmp;
        !          2505: 
        !          2506:     u.u = val;
        !          2507:     /* NaN are not treated the same way IEEE 754 does */
        !          2508:     if (unlikely(isnan(u.f)))
        !          2509:         return 0;
        !          2510:     tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
        !          2511:     u.f = float64_mul(u.f, tmp, &env->spe_status);
        !          2512: 
        !          2513:     return float64_to_uint32(u.f, &env->spe_status);
        !          2514: }
        !          2515: 
        !          2516: static always_inline int64_t _do_efdctsfz (uint64_t val)
        !          2517: {
        !          2518:     union {
        !          2519:         int64_t u;
        !          2520:         float64 f;
        !          2521:     } u;
        !          2522:     float64 tmp;
        !          2523: 
        !          2524:     u.u = val;
        !          2525:     /* NaN are not treated the same way IEEE 754 does */
        !          2526:     if (unlikely(isnan(u.f)))
        !          2527:         return 0;
        !          2528:     tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
        !          2529:     u.f = float64_mul(u.f, tmp, &env->spe_status);
        !          2530: 
        !          2531:     return float64_to_int32_round_to_zero(u.f, &env->spe_status);
        !          2532: }
        !          2533: 
        !          2534: static always_inline uint64_t _do_efdctufz (uint64_t val)
        !          2535: {
        !          2536:     union {
        !          2537:         int64_t u;
        !          2538:         float64 f;
        !          2539:     } u;
        !          2540:     float64 tmp;
        !          2541: 
        !          2542:     u.u = val;
        !          2543:     /* NaN are not treated the same way IEEE 754 does */
        !          2544:     if (unlikely(isnan(u.f)))
        !          2545:         return 0;
        !          2546:     tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
        !          2547:     u.f = float64_mul(u.f, tmp, &env->spe_status);
        !          2548: 
        !          2549:     return float64_to_uint32_round_to_zero(u.f, &env->spe_status);
        !          2550: }
        !          2551: 
        !          2552: void do_efdcfsf (void)
        !          2553: {
        !          2554:     T0_64 = _do_efdcfsf(T0_64);
        !          2555: }
        !          2556: 
        !          2557: void do_efdcfuf (void)
        !          2558: {
        !          2559:     T0_64 = _do_efdcfuf(T0_64);
        !          2560: }
        !          2561: 
        !          2562: void do_efdctsf (void)
        !          2563: {
        !          2564:     T0_64 = _do_efdctsf(T0_64);
        !          2565: }
        !          2566: 
        !          2567: void do_efdctuf (void)
        !          2568: {
        !          2569:     T0_64 = _do_efdctuf(T0_64);
        !          2570: }
        !          2571: 
        !          2572: void do_efdctsfz (void)
        !          2573: {
        !          2574:     T0_64 = _do_efdctsfz(T0_64);
        !          2575: }
        !          2576: 
        !          2577: void do_efdctufz (void)
        !          2578: {
        !          2579:     T0_64 = _do_efdctufz(T0_64);
        !          2580: }
        !          2581: 
        !          2582: /* Floating point conversion between single and double precision */
        !          2583: static always_inline uint32_t _do_efscfd (uint64_t val)
        !          2584: {
        !          2585:     union {
        !          2586:         uint64_t u;
        !          2587:         float64 f;
        !          2588:     } u1;
        !          2589:     union {
        !          2590:         uint32_t u;
        !          2591:         float32 f;
        !          2592:     } u2;
        !          2593: 
        !          2594:     u1.u = val;
        !          2595:     u2.f = float64_to_float32(u1.f, &env->spe_status);
        !          2596: 
        !          2597:     return u2.u;
        !          2598: }
        !          2599: 
        !          2600: static always_inline uint64_t _do_efdcfs (uint32_t val)
        !          2601: {
        !          2602:     union {
        !          2603:         uint64_t u;
        !          2604:         float64 f;
        !          2605:     } u2;
        !          2606:     union {
        !          2607:         uint32_t u;
        !          2608:         float32 f;
        !          2609:     } u1;
        !          2610: 
        !          2611:     u1.u = val;
        !          2612:     u2.f = float32_to_float64(u1.f, &env->spe_status);
        !          2613: 
        !          2614:     return u2.u;
        !          2615: }
        !          2616: 
        !          2617: void do_efscfd (void)
        !          2618: {
        !          2619:     T0_64 = _do_efscfd(T0_64);
        !          2620: }
        !          2621: 
        !          2622: void do_efdcfs (void)
        !          2623: {
        !          2624:     T0_64 = _do_efdcfs(T0_64);
        !          2625: }
        !          2626: 
        !          2627: /* Single precision fixed-point vector arithmetic */
        !          2628: /* evfsabs */
        !          2629: DO_SPE_OP1(fsabs);
        !          2630: /* evfsnabs */
        !          2631: DO_SPE_OP1(fsnabs);
        !          2632: /* evfsneg */
        !          2633: DO_SPE_OP1(fsneg);
        !          2634: /* evfsadd */
        !          2635: DO_SPE_OP2(fsadd);
        !          2636: /* evfssub */
        !          2637: DO_SPE_OP2(fssub);
        !          2638: /* evfsmul */
        !          2639: DO_SPE_OP2(fsmul);
        !          2640: /* evfsdiv */
        !          2641: DO_SPE_OP2(fsdiv);
        !          2642: 
        !          2643: /* Single-precision floating-point comparisons */
        !          2644: static always_inline int _do_efscmplt (uint32_t op1, uint32_t op2)
        !          2645: {
        !          2646:     /* XXX: TODO: test special values (NaN, infinites, ...) */
        !          2647:     return _do_efststlt(op1, op2);
        !          2648: }
        !          2649: 
        !          2650: static always_inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
        !          2651: {
        !          2652:     /* XXX: TODO: test special values (NaN, infinites, ...) */
        !          2653:     return _do_efststgt(op1, op2);
        !          2654: }
        !          2655: 
        !          2656: static always_inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
        !          2657: {
        !          2658:     /* XXX: TODO: test special values (NaN, infinites, ...) */
        !          2659:     return _do_efststeq(op1, op2);
        !          2660: }
        !          2661: 
        !          2662: void do_efscmplt (void)
        !          2663: {
        !          2664:     T0 = _do_efscmplt(T0_64, T1_64);
        !          2665: }
        !          2666: 
        !          2667: void do_efscmpgt (void)
        !          2668: {
        !          2669:     T0 = _do_efscmpgt(T0_64, T1_64);
        !          2670: }
        !          2671: 
        !          2672: void do_efscmpeq (void)
        !          2673: {
        !          2674:     T0 = _do_efscmpeq(T0_64, T1_64);
1.1       root     2675: }
                   2676: 
1.1.1.3 ! root     2677: /* Single-precision floating-point vector comparisons */
        !          2678: /* evfscmplt */
        !          2679: DO_SPE_CMP(fscmplt);
        !          2680: /* evfscmpgt */
        !          2681: DO_SPE_CMP(fscmpgt);
        !          2682: /* evfscmpeq */
        !          2683: DO_SPE_CMP(fscmpeq);
        !          2684: /* evfststlt */
        !          2685: DO_SPE_CMP(fststlt);
        !          2686: /* evfststgt */
        !          2687: DO_SPE_CMP(fststgt);
        !          2688: /* evfststeq */
        !          2689: DO_SPE_CMP(fststeq);
        !          2690: 
        !          2691: /* Single-precision floating-point vector conversions */
        !          2692: /* evfscfsi */
        !          2693: DO_SPE_OP1(fscfsi);
        !          2694: /* evfscfui */
        !          2695: DO_SPE_OP1(fscfui);
        !          2696: /* evfscfuf */
        !          2697: DO_SPE_OP1(fscfuf);
        !          2698: /* evfscfsf */
        !          2699: DO_SPE_OP1(fscfsf);
        !          2700: /* evfsctsi */
        !          2701: DO_SPE_OP1(fsctsi);
        !          2702: /* evfsctui */
        !          2703: DO_SPE_OP1(fsctui);
        !          2704: /* evfsctsiz */
        !          2705: DO_SPE_OP1(fsctsiz);
        !          2706: /* evfsctuiz */
        !          2707: DO_SPE_OP1(fsctuiz);
        !          2708: /* evfsctsf */
        !          2709: DO_SPE_OP1(fsctsf);
        !          2710: /* evfsctuf */
        !          2711: DO_SPE_OP1(fsctuf);
        !          2712: 
1.1       root     2713: /*****************************************************************************/
                   2714: /* Softmmu support */
                   2715: #if !defined (CONFIG_USER_ONLY)
                   2716: 
                   2717: #define MMUSUFFIX _mmu
1.1.1.3 ! root     2718: #ifdef __s390__
        !          2719: # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
        !          2720: #else
        !          2721: # define GETPC() (__builtin_return_address(0))
        !          2722: #endif
1.1       root     2723: 
                   2724: #define SHIFT 0
                   2725: #include "softmmu_template.h"
                   2726: 
                   2727: #define SHIFT 1
                   2728: #include "softmmu_template.h"
                   2729: 
                   2730: #define SHIFT 2
                   2731: #include "softmmu_template.h"
                   2732: 
                   2733: #define SHIFT 3
                   2734: #include "softmmu_template.h"
                   2735: 
                   2736: /* try to fill the TLB and return an exception if error. If retaddr is
                   2737:    NULL, it means that the function was called in C code (i.e. not
                   2738:    from generated code or from helper.c) */
                   2739: /* XXX: fix it to restore all registers */
1.1.1.3 ! root     2740: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1       root     2741: {
                   2742:     TranslationBlock *tb;
                   2743:     CPUState *saved_env;
1.1.1.3 ! root     2744:     unsigned long pc;
1.1       root     2745:     int ret;
                   2746: 
                   2747:     /* XXX: hack to restore env in all cases, even if not called from
                   2748:        generated code */
                   2749:     saved_env = env;
                   2750:     env = cpu_single_env;
1.1.1.3 ! root     2751:     ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
        !          2752:     if (unlikely(ret != 0)) {
1.1       root     2753:         if (likely(retaddr)) {
                   2754:             /* now we have a real cpu fault */
1.1.1.3 ! root     2755:             pc = (unsigned long)retaddr;
1.1       root     2756:             tb = tb_find_pc(pc);
                   2757:             if (likely(tb)) {
                   2758:                 /* the PC is inside the translated code. It means that we have
                   2759:                    a virtual CPU fault */
                   2760:                 cpu_restore_state(tb, env, pc, NULL);
1.1.1.3 ! root     2761:             }
1.1       root     2762:         }
                   2763:         do_raise_exception_err(env->exception_index, env->error_code);
                   2764:     }
                   2765:     env = saved_env;
                   2766: }
                   2767: 
1.1.1.3 ! root     2768: /* Software driven TLBs management */
        !          2769: /* PowerPC 602/603 software TLB load instructions helpers */
        !          2770: void do_load_6xx_tlb (int is_code)
        !          2771: {
        !          2772:     target_ulong RPN, CMP, EPN;
        !          2773:     int way;
        !          2774: 
        !          2775:     RPN = env->spr[SPR_RPA];
        !          2776:     if (is_code) {
        !          2777:         CMP = env->spr[SPR_ICMP];
        !          2778:         EPN = env->spr[SPR_IMISS];
        !          2779:     } else {
        !          2780:         CMP = env->spr[SPR_DCMP];
        !          2781:         EPN = env->spr[SPR_DMISS];
        !          2782:     }
        !          2783:     way = (env->spr[SPR_SRR1] >> 17) & 1;
        !          2784: #if defined (DEBUG_SOFTWARE_TLB)
        !          2785:     if (loglevel != 0) {
        !          2786:         fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX
        !          2787:                 " PTE1 " ADDRX " way %d\n",
        !          2788:                 __func__, T0, EPN, CMP, RPN, way);
        !          2789:     }
        !          2790: #endif
        !          2791:     /* Store this TLB */
        !          2792:     ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
        !          2793:                      way, is_code, CMP, RPN);
        !          2794: }
        !          2795: 
        !          2796: void do_load_74xx_tlb (int is_code)
        !          2797: {
        !          2798:     target_ulong RPN, CMP, EPN;
        !          2799:     int way;
        !          2800: 
        !          2801:     RPN = env->spr[SPR_PTELO];
        !          2802:     CMP = env->spr[SPR_PTEHI];
        !          2803:     EPN = env->spr[SPR_TLBMISS] & ~0x3;
        !          2804:     way = env->spr[SPR_TLBMISS] & 0x3;
        !          2805: #if defined (DEBUG_SOFTWARE_TLB)
        !          2806:     if (loglevel != 0) {
        !          2807:         fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX
        !          2808:                 " PTE1 " ADDRX " way %d\n",
        !          2809:                 __func__, T0, EPN, CMP, RPN, way);
        !          2810:     }
        !          2811: #endif
        !          2812:     /* Store this TLB */
        !          2813:     ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
        !          2814:                      way, is_code, CMP, RPN);
        !          2815: }
        !          2816: 
        !          2817: static always_inline target_ulong booke_tlb_to_page_size (int size)
        !          2818: {
        !          2819:     return 1024 << (2 * size);
        !          2820: }
        !          2821: 
        !          2822: static always_inline int booke_page_size_to_tlb (target_ulong page_size)
        !          2823: {
        !          2824:     int size;
        !          2825: 
        !          2826:     switch (page_size) {
        !          2827:     case 0x00000400UL:
        !          2828:         size = 0x0;
        !          2829:         break;
        !          2830:     case 0x00001000UL:
        !          2831:         size = 0x1;
        !          2832:         break;
        !          2833:     case 0x00004000UL:
        !          2834:         size = 0x2;
        !          2835:         break;
        !          2836:     case 0x00010000UL:
        !          2837:         size = 0x3;
        !          2838:         break;
        !          2839:     case 0x00040000UL:
        !          2840:         size = 0x4;
        !          2841:         break;
        !          2842:     case 0x00100000UL:
        !          2843:         size = 0x5;
        !          2844:         break;
        !          2845:     case 0x00400000UL:
        !          2846:         size = 0x6;
        !          2847:         break;
        !          2848:     case 0x01000000UL:
        !          2849:         size = 0x7;
        !          2850:         break;
        !          2851:     case 0x04000000UL:
        !          2852:         size = 0x8;
        !          2853:         break;
        !          2854:     case 0x10000000UL:
        !          2855:         size = 0x9;
        !          2856:         break;
        !          2857:     case 0x40000000UL:
        !          2858:         size = 0xA;
        !          2859:         break;
        !          2860: #if defined (TARGET_PPC64)
        !          2861:     case 0x000100000000ULL:
        !          2862:         size = 0xB;
        !          2863:         break;
        !          2864:     case 0x000400000000ULL:
        !          2865:         size = 0xC;
        !          2866:         break;
        !          2867:     case 0x001000000000ULL:
        !          2868:         size = 0xD;
        !          2869:         break;
        !          2870:     case 0x004000000000ULL:
        !          2871:         size = 0xE;
        !          2872:         break;
        !          2873:     case 0x010000000000ULL:
        !          2874:         size = 0xF;
        !          2875:         break;
        !          2876: #endif
        !          2877:     default:
        !          2878:         size = -1;
        !          2879:         break;
        !          2880:     }
        !          2881: 
        !          2882:     return size;
        !          2883: }
        !          2884: 
        !          2885: /* Helpers for 4xx TLB management */
        !          2886: void do_4xx_tlbre_lo (void)
        !          2887: {
        !          2888:     ppcemb_tlb_t *tlb;
        !          2889:     int size;
        !          2890: 
        !          2891:     T0 &= 0x3F;
        !          2892:     tlb = &env->tlb[T0].tlbe;
        !          2893:     T0 = tlb->EPN;
        !          2894:     if (tlb->prot & PAGE_VALID)
        !          2895:         T0 |= 0x400;
        !          2896:     size = booke_page_size_to_tlb(tlb->size);
        !          2897:     if (size < 0 || size > 0x7)
        !          2898:         size = 1;
        !          2899:     T0 |= size << 7;
        !          2900:     env->spr[SPR_40x_PID] = tlb->PID;
        !          2901: }
        !          2902: 
        !          2903: void do_4xx_tlbre_hi (void)
        !          2904: {
        !          2905:     ppcemb_tlb_t *tlb;
        !          2906: 
        !          2907:     T0 &= 0x3F;
        !          2908:     tlb = &env->tlb[T0].tlbe;
        !          2909:     T0 = tlb->RPN;
        !          2910:     if (tlb->prot & PAGE_EXEC)
        !          2911:         T0 |= 0x200;
        !          2912:     if (tlb->prot & PAGE_WRITE)
        !          2913:         T0 |= 0x100;
        !          2914: }
        !          2915: 
        !          2916: void do_4xx_tlbwe_hi (void)
        !          2917: {
        !          2918:     ppcemb_tlb_t *tlb;
        !          2919:     target_ulong page, end;
        !          2920: 
        !          2921: #if defined (DEBUG_SOFTWARE_TLB)
        !          2922:     if (loglevel != 0) {
        !          2923:         fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
        !          2924:     }
        !          2925: #endif
        !          2926:     T0 &= 0x3F;
        !          2927:     tlb = &env->tlb[T0].tlbe;
        !          2928:     /* Invalidate previous TLB (if it's valid) */
        !          2929:     if (tlb->prot & PAGE_VALID) {
        !          2930:         end = tlb->EPN + tlb->size;
        !          2931: #if defined (DEBUG_SOFTWARE_TLB)
        !          2932:         if (loglevel != 0) {
        !          2933:             fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
        !          2934:                     " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
        !          2935:         }
        !          2936: #endif
        !          2937:         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
        !          2938:             tlb_flush_page(env, page);
        !          2939:     }
        !          2940:     tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
        !          2941:     /* We cannot handle TLB size < TARGET_PAGE_SIZE.
        !          2942:      * If this ever occurs, one should use the ppcemb target instead
        !          2943:      * of the ppc or ppc64 one
        !          2944:      */
        !          2945:     if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
        !          2946:         cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
        !          2947:                   "are not supported (%d)\n",
        !          2948:                   tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
        !          2949:     }
        !          2950:     tlb->EPN = T1 & ~(tlb->size - 1);
        !          2951:     if (T1 & 0x40)
        !          2952:         tlb->prot |= PAGE_VALID;
        !          2953:     else
        !          2954:         tlb->prot &= ~PAGE_VALID;
        !          2955:     if (T1 & 0x20) {
        !          2956:         /* XXX: TO BE FIXED */
        !          2957:         cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
        !          2958:     }
        !          2959:     tlb->PID = env->spr[SPR_40x_PID]; /* PID */
        !          2960:     tlb->attr = T1 & 0xFF;
        !          2961: #if defined (DEBUG_SOFTWARE_TLB)
        !          2962:     if (loglevel != 0) {
        !          2963:         fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
        !          2964:                 " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
        !          2965:                 (int)T0, tlb->RPN, tlb->EPN, tlb->size,
        !          2966:                 tlb->prot & PAGE_READ ? 'r' : '-',
        !          2967:                 tlb->prot & PAGE_WRITE ? 'w' : '-',
        !          2968:                 tlb->prot & PAGE_EXEC ? 'x' : '-',
        !          2969:                 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
        !          2970:     }
        !          2971: #endif
        !          2972:     /* Invalidate new TLB (if valid) */
        !          2973:     if (tlb->prot & PAGE_VALID) {
        !          2974:         end = tlb->EPN + tlb->size;
        !          2975: #if defined (DEBUG_SOFTWARE_TLB)
        !          2976:         if (loglevel != 0) {
        !          2977:             fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
        !          2978:                     " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
        !          2979:         }
        !          2980: #endif
        !          2981:         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
        !          2982:             tlb_flush_page(env, page);
        !          2983:     }
        !          2984: }
        !          2985: 
        !          2986: void do_4xx_tlbwe_lo (void)
        !          2987: {
        !          2988:     ppcemb_tlb_t *tlb;
        !          2989: 
        !          2990: #if defined (DEBUG_SOFTWARE_TLB)
        !          2991:     if (loglevel != 0) {
        !          2992:         fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
        !          2993:     }
        !          2994: #endif
        !          2995:     T0 &= 0x3F;
        !          2996:     tlb = &env->tlb[T0].tlbe;
        !          2997:     tlb->RPN = T1 & 0xFFFFFC00;
        !          2998:     tlb->prot = PAGE_READ;
        !          2999:     if (T1 & 0x200)
        !          3000:         tlb->prot |= PAGE_EXEC;
        !          3001:     if (T1 & 0x100)
        !          3002:         tlb->prot |= PAGE_WRITE;
        !          3003: #if defined (DEBUG_SOFTWARE_TLB)
        !          3004:     if (loglevel != 0) {
        !          3005:         fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
        !          3006:                 " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
        !          3007:                 (int)T0, tlb->RPN, tlb->EPN, tlb->size,
        !          3008:                 tlb->prot & PAGE_READ ? 'r' : '-',
        !          3009:                 tlb->prot & PAGE_WRITE ? 'w' : '-',
        !          3010:                 tlb->prot & PAGE_EXEC ? 'x' : '-',
        !          3011:                 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
        !          3012:     }
        !          3013: #endif
        !          3014: }
        !          3015: 
        !          3016: /* PowerPC 440 TLB management */
        !          3017: void do_440_tlbwe (int word)
        !          3018: {
        !          3019:     ppcemb_tlb_t *tlb;
        !          3020:     target_ulong EPN, RPN, size;
        !          3021:     int do_flush_tlbs;
        !          3022: 
        !          3023: #if defined (DEBUG_SOFTWARE_TLB)
        !          3024:     if (loglevel != 0) {
        !          3025:         fprintf(logfile, "%s word %d T0 " TDX " T1 " TDX "\n",
        !          3026:                 __func__, word, T0, T1);
        !          3027:     }
        !          3028: #endif
        !          3029:     do_flush_tlbs = 0;
        !          3030:     T0 &= 0x3F;
        !          3031:     tlb = &env->tlb[T0].tlbe;
        !          3032:     switch (word) {
        !          3033:     default:
        !          3034:         /* Just here to please gcc */
        !          3035:     case 0:
        !          3036:         EPN = T1 & 0xFFFFFC00;
        !          3037:         if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
        !          3038:             do_flush_tlbs = 1;
        !          3039:         tlb->EPN = EPN;
        !          3040:         size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
        !          3041:         if ((tlb->prot & PAGE_VALID) && tlb->size < size)
        !          3042:             do_flush_tlbs = 1;
        !          3043:         tlb->size = size;
        !          3044:         tlb->attr &= ~0x1;
        !          3045:         tlb->attr |= (T1 >> 8) & 1;
        !          3046:         if (T1 & 0x200) {
        !          3047:             tlb->prot |= PAGE_VALID;
        !          3048:         } else {
        !          3049:             if (tlb->prot & PAGE_VALID) {
        !          3050:                 tlb->prot &= ~PAGE_VALID;
        !          3051:                 do_flush_tlbs = 1;
        !          3052:             }
        !          3053:         }
        !          3054:         tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
        !          3055:         if (do_flush_tlbs)
        !          3056:             tlb_flush(env, 1);
        !          3057:         break;
        !          3058:     case 1:
        !          3059:         RPN = T1 & 0xFFFFFC0F;
        !          3060:         if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
        !          3061:             tlb_flush(env, 1);
        !          3062:         tlb->RPN = RPN;
        !          3063:         break;
        !          3064:     case 2:
        !          3065:         tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
        !          3066:         tlb->prot = tlb->prot & PAGE_VALID;
        !          3067:         if (T1 & 0x1)
        !          3068:             tlb->prot |= PAGE_READ << 4;
        !          3069:         if (T1 & 0x2)
        !          3070:             tlb->prot |= PAGE_WRITE << 4;
        !          3071:         if (T1 & 0x4)
        !          3072:             tlb->prot |= PAGE_EXEC << 4;
        !          3073:         if (T1 & 0x8)
        !          3074:             tlb->prot |= PAGE_READ;
        !          3075:         if (T1 & 0x10)
        !          3076:             tlb->prot |= PAGE_WRITE;
        !          3077:         if (T1 & 0x20)
        !          3078:             tlb->prot |= PAGE_EXEC;
        !          3079:         break;
        !          3080:     }
        !          3081: }
        !          3082: 
        !          3083: void do_440_tlbre (int word)
        !          3084: {
        !          3085:     ppcemb_tlb_t *tlb;
        !          3086:     int size;
        !          3087: 
        !          3088:     T0 &= 0x3F;
        !          3089:     tlb = &env->tlb[T0].tlbe;
        !          3090:     switch (word) {
        !          3091:     default:
        !          3092:         /* Just here to please gcc */
        !          3093:     case 0:
        !          3094:         T0 = tlb->EPN;
        !          3095:         size = booke_page_size_to_tlb(tlb->size);
        !          3096:         if (size < 0 || size > 0xF)
        !          3097:             size = 1;
        !          3098:         T0 |= size << 4;
        !          3099:         if (tlb->attr & 0x1)
        !          3100:             T0 |= 0x100;
        !          3101:         if (tlb->prot & PAGE_VALID)
        !          3102:             T0 |= 0x200;
        !          3103:         env->spr[SPR_440_MMUCR] &= ~0x000000FF;
        !          3104:         env->spr[SPR_440_MMUCR] |= tlb->PID;
        !          3105:         break;
        !          3106:     case 1:
        !          3107:         T0 = tlb->RPN;
        !          3108:         break;
        !          3109:     case 2:
        !          3110:         T0 = tlb->attr & ~0x1;
        !          3111:         if (tlb->prot & (PAGE_READ << 4))
        !          3112:             T0 |= 0x1;
        !          3113:         if (tlb->prot & (PAGE_WRITE << 4))
        !          3114:             T0 |= 0x2;
        !          3115:         if (tlb->prot & (PAGE_EXEC << 4))
        !          3116:             T0 |= 0x4;
        !          3117:         if (tlb->prot & PAGE_READ)
        !          3118:             T0 |= 0x8;
        !          3119:         if (tlb->prot & PAGE_WRITE)
        !          3120:             T0 |= 0x10;
        !          3121:         if (tlb->prot & PAGE_EXEC)
        !          3122:             T0 |= 0x20;
        !          3123:         break;
        !          3124:     }
        !          3125: }
        !          3126: #endif /* !CONFIG_USER_ONLY */

unix.superglobalmegacorp.com

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