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

1.1       root        1: /*
                      2:  *  S/390 helper routines
                      3:  *
1.1.1.3 ! root        4:  *  Copyright (c) 2009 Ulrich Hecht
1.1       root        5:  *  Copyright (c) 2009 Alexander Graf
                      6:  *
                      7:  * This library is free software; you can redistribute it and/or
                      8:  * modify it under the terms of the GNU Lesser General Public
                      9:  * License as published by the Free Software Foundation; either
                     10:  * version 2 of the License, or (at your option) any later version.
                     11:  *
                     12:  * This library is distributed in the hope that it will be useful,
                     13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * Lesser General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU Lesser General Public
1.1.1.2   root       18:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1       root       19:  */
                     20: 
                     21: #include "exec.h"
1.1.1.3 ! root       22: #include "host-utils.h"
        !            23: #include "helpers.h"
        !            24: #include <string.h>
        !            25: #include "kvm.h"
        !            26: #include "qemu-timer.h"
        !            27: #ifdef CONFIG_KVM
        !            28: #include <linux/kvm.h>
        !            29: #endif
1.1       root       30: 
                     31: /*****************************************************************************/
                     32: /* Softmmu support */
                     33: #if !defined (CONFIG_USER_ONLY)
                     34: 
                     35: #define MMUSUFFIX _mmu
                     36: 
                     37: #define SHIFT 0
                     38: #include "softmmu_template.h"
                     39: 
                     40: #define SHIFT 1
                     41: #include "softmmu_template.h"
                     42: 
                     43: #define SHIFT 2
                     44: #include "softmmu_template.h"
                     45: 
                     46: #define SHIFT 3
                     47: #include "softmmu_template.h"
                     48: 
                     49: /* try to fill the TLB and return an exception if error. If retaddr is
                     50:    NULL, it means that the function was called in C code (i.e. not
                     51:    from generated code or from helper.c) */
                     52: /* XXX: fix it to restore all registers */
                     53: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
                     54: {
                     55:     TranslationBlock *tb;
                     56:     CPUState *saved_env;
                     57:     unsigned long pc;
                     58:     int ret;
                     59: 
                     60:     /* XXX: hack to restore env in all cases, even if not called from
                     61:        generated code */
                     62:     saved_env = env;
                     63:     env = cpu_single_env;
                     64:     ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
                     65:     if (unlikely(ret != 0)) {
                     66:         if (likely(retaddr)) {
                     67:             /* now we have a real cpu fault */
                     68:             pc = (unsigned long)retaddr;
                     69:             tb = tb_find_pc(pc);
                     70:             if (likely(tb)) {
                     71:                 /* the PC is inside the translated code. It means that we have
                     72:                    a virtual CPU fault */
1.1.1.3 ! root       73:                 cpu_restore_state(tb, env, pc);
1.1       root       74:             }
                     75:         }
1.1.1.3 ! root       76:         cpu_loop_exit(env);
1.1       root       77:     }
                     78:     env = saved_env;
                     79: }
                     80: 
                     81: #endif
1.1.1.3 ! root       82: 
        !            83: /* #define DEBUG_HELPER */
        !            84: #ifdef DEBUG_HELPER
        !            85: #define HELPER_LOG(x...) qemu_log(x)
        !            86: #else
        !            87: #define HELPER_LOG(x...)
        !            88: #endif
        !            89: 
        !            90: /* raise an exception */
        !            91: void HELPER(exception)(uint32_t excp)
        !            92: {
        !            93:     HELPER_LOG("%s: exception %d\n", __FUNCTION__, excp);
        !            94:     env->exception_index = excp;
        !            95:     cpu_loop_exit(env);
        !            96: }
        !            97: 
        !            98: #ifndef CONFIG_USER_ONLY
        !            99: static void mvc_fast_memset(CPUState *env, uint32_t l, uint64_t dest,
        !           100:                             uint8_t byte)
        !           101: {
        !           102:     target_phys_addr_t dest_phys;
        !           103:     target_phys_addr_t len = l;
        !           104:     void *dest_p;
        !           105:     uint64_t asc = env->psw.mask & PSW_MASK_ASC;
        !           106:     int flags;
        !           107: 
        !           108:     if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
        !           109:         stb(dest, byte);
        !           110:         cpu_abort(env, "should never reach here");
        !           111:     }
        !           112:     dest_phys |= dest & ~TARGET_PAGE_MASK;
        !           113: 
        !           114:     dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
        !           115: 
        !           116:     memset(dest_p, byte, len);
        !           117: 
        !           118:     cpu_physical_memory_unmap(dest_p, 1, len, len);
        !           119: }
        !           120: 
        !           121: static void mvc_fast_memmove(CPUState *env, uint32_t l, uint64_t dest,
        !           122:                              uint64_t src)
        !           123: {
        !           124:     target_phys_addr_t dest_phys;
        !           125:     target_phys_addr_t src_phys;
        !           126:     target_phys_addr_t len = l;
        !           127:     void *dest_p;
        !           128:     void *src_p;
        !           129:     uint64_t asc = env->psw.mask & PSW_MASK_ASC;
        !           130:     int flags;
        !           131: 
        !           132:     if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
        !           133:         stb(dest, 0);
        !           134:         cpu_abort(env, "should never reach here");
        !           135:     }
        !           136:     dest_phys |= dest & ~TARGET_PAGE_MASK;
        !           137: 
        !           138:     if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) {
        !           139:         ldub(src);
        !           140:         cpu_abort(env, "should never reach here");
        !           141:     }
        !           142:     src_phys |= src & ~TARGET_PAGE_MASK;
        !           143: 
        !           144:     dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
        !           145:     src_p = cpu_physical_memory_map(src_phys, &len, 0);
        !           146: 
        !           147:     memmove(dest_p, src_p, len);
        !           148: 
        !           149:     cpu_physical_memory_unmap(dest_p, 1, len, len);
        !           150:     cpu_physical_memory_unmap(src_p, 0, len, len);
        !           151: }
        !           152: #endif
        !           153: 
        !           154: /* and on array */
        !           155: uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src)
        !           156: {
        !           157:     int i;
        !           158:     unsigned char x;
        !           159:     uint32_t cc = 0;
        !           160: 
        !           161:     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
        !           162:                __FUNCTION__, l, dest, src);
        !           163:     for (i = 0; i <= l; i++) {
        !           164:         x = ldub(dest + i) & ldub(src + i);
        !           165:         if (x) {
        !           166:             cc = 1;
        !           167:         }
        !           168:         stb(dest + i, x);
        !           169:     }
        !           170:     return cc;
        !           171: }
        !           172: 
        !           173: /* xor on array */
        !           174: uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src)
        !           175: {
        !           176:     int i;
        !           177:     unsigned char x;
        !           178:     uint32_t cc = 0;
        !           179: 
        !           180:     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
        !           181:                __FUNCTION__, l, dest, src);
        !           182: 
        !           183: #ifndef CONFIG_USER_ONLY
        !           184:     /* xor with itself is the same as memset(0) */
        !           185:     if ((l > 32) && (src == dest) &&
        !           186:         (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) {
        !           187:         mvc_fast_memset(env, l + 1, dest, 0);
        !           188:         return 0;
        !           189:     }
        !           190: #else
        !           191:     if (src == dest) {
        !           192:         memset(g2h(dest), 0, l + 1);
        !           193:         return 0;
        !           194:     }
        !           195: #endif
        !           196: 
        !           197:     for (i = 0; i <= l; i++) {
        !           198:         x = ldub(dest + i) ^ ldub(src + i);
        !           199:         if (x) {
        !           200:             cc = 1;
        !           201:         }
        !           202:         stb(dest + i, x);
        !           203:     }
        !           204:     return cc;
        !           205: }
        !           206: 
        !           207: /* or on array */
        !           208: uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src)
        !           209: {
        !           210:     int i;
        !           211:     unsigned char x;
        !           212:     uint32_t cc = 0;
        !           213: 
        !           214:     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
        !           215:                __FUNCTION__, l, dest, src);
        !           216:     for (i = 0; i <= l; i++) {
        !           217:         x = ldub(dest + i) | ldub(src + i);
        !           218:         if (x) {
        !           219:             cc = 1;
        !           220:         }
        !           221:         stb(dest + i, x);
        !           222:     }
        !           223:     return cc;
        !           224: }
        !           225: 
        !           226: /* memmove */
        !           227: void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
        !           228: {
        !           229:     int i = 0;
        !           230:     int x = 0;
        !           231:     uint32_t l_64 = (l + 1) / 8;
        !           232: 
        !           233:     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
        !           234:                __FUNCTION__, l, dest, src);
        !           235: 
        !           236: #ifndef CONFIG_USER_ONLY
        !           237:     if ((l > 32) &&
        !           238:         (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) &&
        !           239:         (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) {
        !           240:         if (dest == (src + 1)) {
        !           241:             mvc_fast_memset(env, l + 1, dest, ldub(src));
        !           242:             return;
        !           243:         } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
        !           244:             mvc_fast_memmove(env, l + 1, dest, src);
        !           245:             return;
        !           246:         }
        !           247:     }
        !           248: #else
        !           249:     if (dest == (src + 1)) {
        !           250:         memset(g2h(dest), ldub(src), l + 1);
        !           251:         return;
        !           252:     } else {
        !           253:         memmove(g2h(dest), g2h(src), l + 1);
        !           254:         return;
        !           255:     }
        !           256: #endif
        !           257: 
        !           258:     /* handle the parts that fit into 8-byte loads/stores */
        !           259:     if (dest != (src + 1)) {
        !           260:         for (i = 0; i < l_64; i++) {
        !           261:             stq(dest + x, ldq(src + x));
        !           262:             x += 8;
        !           263:         }
        !           264:     }
        !           265: 
        !           266:     /* slow version crossing pages with byte accesses */
        !           267:     for (i = x; i <= l; i++) {
        !           268:         stb(dest + i, ldub(src + i));
        !           269:     }
        !           270: }
        !           271: 
        !           272: /* compare unsigned byte arrays */
        !           273: uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
        !           274: {
        !           275:     int i;
        !           276:     unsigned char x,y;
        !           277:     uint32_t cc;
        !           278:     HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
        !           279:                __FUNCTION__, l, s1, s2);
        !           280:     for (i = 0; i <= l; i++) {
        !           281:         x = ldub(s1 + i);
        !           282:         y = ldub(s2 + i);
        !           283:         HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
        !           284:         if (x < y) {
        !           285:             cc = 1;
        !           286:             goto done;
        !           287:         } else if (x > y) {
        !           288:             cc = 2;
        !           289:             goto done;
        !           290:         }
        !           291:     }
        !           292:     cc = 0;
        !           293: done:
        !           294:     HELPER_LOG("\n");
        !           295:     return cc;
        !           296: }
        !           297: 
        !           298: /* compare logical under mask */
        !           299: uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
        !           300: {
        !           301:     uint8_t r,d;
        !           302:     uint32_t cc;
        !           303:     HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __FUNCTION__, r1,
        !           304:                mask, addr);
        !           305:     cc = 0;
        !           306:     while (mask) {
        !           307:         if (mask & 8) {
        !           308:             d = ldub(addr);
        !           309:             r = (r1 & 0xff000000UL) >> 24;
        !           310:             HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
        !           311:                         addr);
        !           312:             if (r < d) {
        !           313:                 cc = 1;
        !           314:                 break;
        !           315:             } else if (r > d) {
        !           316:                 cc = 2;
        !           317:                 break;
        !           318:             }
        !           319:             addr++;
        !           320:         }
        !           321:         mask = (mask << 1) & 0xf;
        !           322:         r1 <<= 8;
        !           323:     }
        !           324:     HELPER_LOG("\n");
        !           325:     return cc;
        !           326: }
        !           327: 
        !           328: /* store character under mask */
        !           329: void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
        !           330: {
        !           331:     uint8_t r;
        !           332:     HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __FUNCTION__, r1, mask,
        !           333:                addr);
        !           334:     while (mask) {
        !           335:         if (mask & 8) {
        !           336:             r = (r1 & 0xff000000UL) >> 24;
        !           337:             stb(addr, r);
        !           338:             HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr);
        !           339:             addr++;
        !           340:         }
        !           341:         mask = (mask << 1) & 0xf;
        !           342:         r1 <<= 8;
        !           343:     }
        !           344:     HELPER_LOG("\n");
        !           345: }
        !           346: 
        !           347: /* 64/64 -> 128 unsigned multiplication */
        !           348: void HELPER(mlg)(uint32_t r1, uint64_t v2)
        !           349: {
        !           350: #if HOST_LONG_BITS == 64 && defined(__GNUC__)
        !           351:     /* assuming 64-bit hosts have __uint128_t */
        !           352:     __uint128_t res = (__uint128_t)env->regs[r1 + 1];
        !           353:     res *= (__uint128_t)v2;
        !           354:     env->regs[r1] = (uint64_t)(res >> 64);
        !           355:     env->regs[r1 + 1] = (uint64_t)res;
        !           356: #else
        !           357:     mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
        !           358: #endif
        !           359: }
        !           360: 
        !           361: /* 128 -> 64/64 unsigned division */
        !           362: void HELPER(dlg)(uint32_t r1, uint64_t v2)
        !           363: {
        !           364:     uint64_t divisor = v2;
        !           365: 
        !           366:     if (!env->regs[r1]) {
        !           367:         /* 64 -> 64/64 case */
        !           368:         env->regs[r1] = env->regs[r1+1] % divisor;
        !           369:         env->regs[r1+1] = env->regs[r1+1] / divisor;
        !           370:         return;
        !           371:     } else {
        !           372: 
        !           373: #if HOST_LONG_BITS == 64 && defined(__GNUC__)
        !           374:         /* assuming 64-bit hosts have __uint128_t */
        !           375:         __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
        !           376:                                (env->regs[r1+1]);
        !           377:         __uint128_t quotient = dividend / divisor;
        !           378:         env->regs[r1+1] = quotient;
        !           379:         __uint128_t remainder = dividend % divisor;
        !           380:         env->regs[r1] = remainder;
        !           381: #else
        !           382:         /* 32-bit hosts would need special wrapper functionality - just abort if
        !           383:            we encounter such a case; it's very unlikely anyways. */
        !           384:         cpu_abort(env, "128 -> 64/64 division not implemented\n");
        !           385: #endif
        !           386:     }
        !           387: }
        !           388: 
        !           389: static inline uint64_t get_address(int x2, int b2, int d2)
        !           390: {
        !           391:     uint64_t r = d2;
        !           392: 
        !           393:     if (x2) {
        !           394:         r += env->regs[x2];
        !           395:     }
        !           396: 
        !           397:     if (b2) {
        !           398:         r += env->regs[b2];
        !           399:     }
        !           400: 
        !           401:     /* 31-Bit mode */
        !           402:     if (!(env->psw.mask & PSW_MASK_64)) {
        !           403:         r &= 0x7fffffff;
        !           404:     }
        !           405: 
        !           406:     return r;
        !           407: }
        !           408: 
        !           409: static inline uint64_t get_address_31fix(int reg)
        !           410: {
        !           411:     uint64_t r = env->regs[reg];
        !           412: 
        !           413:     /* 31-Bit mode */
        !           414:     if (!(env->psw.mask & PSW_MASK_64)) {
        !           415:         r &= 0x7fffffff;
        !           416:     }
        !           417: 
        !           418:     return r;
        !           419: }
        !           420: 
        !           421: /* search string (c is byte to search, r2 is string, r1 end of string) */
        !           422: uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2)
        !           423: {
        !           424:     uint64_t i;
        !           425:     uint32_t cc = 2;
        !           426:     uint64_t str = get_address_31fix(r2);
        !           427:     uint64_t end = get_address_31fix(r1);
        !           428: 
        !           429:     HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __FUNCTION__,
        !           430:                c, env->regs[r1], env->regs[r2]);
        !           431: 
        !           432:     for (i = str; i != end; i++) {
        !           433:         if (ldub(i) == c) {
        !           434:             env->regs[r1] = i;
        !           435:             cc = 1;
        !           436:             break;
        !           437:         }
        !           438:     }
        !           439: 
        !           440:     return cc;
        !           441: }
        !           442: 
        !           443: /* unsigned string compare (c is string terminator) */
        !           444: uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2)
        !           445: {
        !           446:     uint64_t s1 = get_address_31fix(r1);
        !           447:     uint64_t s2 = get_address_31fix(r2);
        !           448:     uint8_t v1, v2;
        !           449:     uint32_t cc;
        !           450:     c = c & 0xff;
        !           451: #ifdef CONFIG_USER_ONLY
        !           452:     if (!c) {
        !           453:         HELPER_LOG("%s: comparing '%s' and '%s'\n",
        !           454:                    __FUNCTION__, (char*)g2h(s1), (char*)g2h(s2));
        !           455:     }
        !           456: #endif
        !           457:     for (;;) {
        !           458:         v1 = ldub(s1);
        !           459:         v2 = ldub(s2);
        !           460:         if ((v1 == c || v2 == c) || (v1 != v2)) {
        !           461:             break;
        !           462:         }
        !           463:         s1++;
        !           464:         s2++;
        !           465:     }
        !           466: 
        !           467:     if (v1 == v2) {
        !           468:         cc = 0;
        !           469:     } else {
        !           470:         cc = (v1 < v2) ? 1 : 2;
        !           471:         /* FIXME: 31-bit mode! */
        !           472:         env->regs[r1] = s1;
        !           473:         env->regs[r2] = s2;
        !           474:     }
        !           475:     return cc;
        !           476: }
        !           477: 
        !           478: /* move page */
        !           479: void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2)
        !           480: {
        !           481:     /* XXX missing r0 handling */
        !           482: #ifdef CONFIG_USER_ONLY
        !           483:     int i;
        !           484: 
        !           485:     for (i = 0; i < TARGET_PAGE_SIZE; i++) {
        !           486:         stb(r1 + i, ldub(r2 + i));
        !           487:     }
        !           488: #else
        !           489:     mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
        !           490: #endif
        !           491: }
        !           492: 
        !           493: /* string copy (c is string terminator) */
        !           494: void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2)
        !           495: {
        !           496:     uint64_t dest = get_address_31fix(r1);
        !           497:     uint64_t src = get_address_31fix(r2);
        !           498:     uint8_t v;
        !           499:     c = c & 0xff;
        !           500: #ifdef CONFIG_USER_ONLY
        !           501:     if (!c) {
        !           502:         HELPER_LOG("%s: copy '%s' to 0x%lx\n", __FUNCTION__, (char*)g2h(src),
        !           503:                    dest);
        !           504:     }
        !           505: #endif
        !           506:     for (;;) {
        !           507:         v = ldub(src);
        !           508:         stb(dest, v);
        !           509:         if (v == c) {
        !           510:             break;
        !           511:         }
        !           512:         src++;
        !           513:         dest++;
        !           514:     }
        !           515:     env->regs[r1] = dest; /* FIXME: 31-bit mode! */
        !           516: }
        !           517: 
        !           518: /* compare and swap 64-bit */
        !           519: uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3)
        !           520: {
        !           521:     /* FIXME: locking? */
        !           522:     uint32_t cc;
        !           523:     uint64_t v2 = ldq(a2);
        !           524:     if (env->regs[r1] == v2) {
        !           525:         cc = 0;
        !           526:         stq(a2, env->regs[r3]);
        !           527:     } else {
        !           528:         cc = 1;
        !           529:         env->regs[r1] = v2;
        !           530:     }
        !           531:     return cc;
        !           532: }
        !           533: 
        !           534: /* compare double and swap 64-bit */
        !           535: uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3)
        !           536: {
        !           537:     /* FIXME: locking? */
        !           538:     uint32_t cc;
        !           539:     uint64_t v2_hi = ldq(a2);
        !           540:     uint64_t v2_lo = ldq(a2 + 8);
        !           541:     uint64_t v1_hi = env->regs[r1];
        !           542:     uint64_t v1_lo = env->regs[r1 + 1];
        !           543: 
        !           544:     if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) {
        !           545:         cc = 0;
        !           546:         stq(a2, env->regs[r3]);
        !           547:         stq(a2 + 8, env->regs[r3 + 1]);
        !           548:     } else {
        !           549:         cc = 1;
        !           550:         env->regs[r1] = v2_hi;
        !           551:         env->regs[r1 + 1] = v2_lo;
        !           552:     }
        !           553: 
        !           554:     return cc;
        !           555: }
        !           556: 
        !           557: /* compare and swap 32-bit */
        !           558: uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3)
        !           559: {
        !           560:     /* FIXME: locking? */
        !           561:     uint32_t cc;
        !           562:     HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __FUNCTION__, r1, a2, r3);
        !           563:     uint32_t v2 = ldl(a2);
        !           564:     if (((uint32_t)env->regs[r1]) == v2) {
        !           565:         cc = 0;
        !           566:         stl(a2, (uint32_t)env->regs[r3]);
        !           567:     } else {
        !           568:         cc = 1;
        !           569:         env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
        !           570:     }
        !           571:     return cc;
        !           572: }
        !           573: 
        !           574: static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
        !           575: {
        !           576:     int pos = 24; /* top of the lower half of r1 */
        !           577:     uint64_t rmask = 0xff000000ULL;
        !           578:     uint8_t val = 0;
        !           579:     int ccd = 0;
        !           580:     uint32_t cc = 0;
        !           581: 
        !           582:     while (mask) {
        !           583:         if (mask & 8) {
        !           584:             env->regs[r1] &= ~rmask;
        !           585:             val = ldub(address);
        !           586:             if ((val & 0x80) && !ccd) {
        !           587:                 cc = 1;
        !           588:             }
        !           589:             ccd = 1;
        !           590:             if (val && cc == 0) {
        !           591:                 cc = 2;
        !           592:             }
        !           593:             env->regs[r1] |= (uint64_t)val << pos;
        !           594:             address++;
        !           595:         }
        !           596:         mask = (mask << 1) & 0xf;
        !           597:         pos -= 8;
        !           598:         rmask >>= 8;
        !           599:     }
        !           600: 
        !           601:     return cc;
        !           602: }
        !           603: 
        !           604: /* execute instruction
        !           605:    this instruction executes an insn modified with the contents of r1
        !           606:    it does not change the executed instruction in memory
        !           607:    it does not change the program counter
        !           608:    in other words: tricky...
        !           609:    currently implemented by interpreting the cases it is most commonly used in
        !           610:  */
        !           611: uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
        !           612: {
        !           613:     uint16_t insn = lduw_code(addr);
        !           614:     HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __FUNCTION__, v1, addr,
        !           615:              insn);
        !           616:     if ((insn & 0xf0ff) == 0xd000) {
        !           617:         uint32_t l, insn2, b1, b2, d1, d2;
        !           618:         l = v1 & 0xff;
        !           619:         insn2 = ldl_code(addr + 2);
        !           620:         b1 = (insn2 >> 28) & 0xf;
        !           621:         b2 = (insn2 >> 12) & 0xf;
        !           622:         d1 = (insn2 >> 16) & 0xfff;
        !           623:         d2 = insn2 & 0xfff;
        !           624:         switch (insn & 0xf00) {
        !           625:         case 0x200:
        !           626:             helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2));
        !           627:             break;
        !           628:         case 0x500:
        !           629:             cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2));
        !           630:             break;
        !           631:         case 0x700:
        !           632:             cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2));
        !           633:             break;
        !           634:         default:
        !           635:             goto abort;
        !           636:             break;
        !           637:         }
        !           638:     } else if ((insn & 0xff00) == 0x0a00) {
        !           639:         /* supervisor call */
        !           640:         HELPER_LOG("%s: svc %ld via execute\n", __FUNCTION__, (insn|v1) & 0xff);
        !           641:         env->psw.addr = ret - 4;
        !           642:         env->int_svc_code = (insn|v1) & 0xff;
        !           643:         env->int_svc_ilc = 4;
        !           644:         helper_exception(EXCP_SVC);
        !           645:     } else if ((insn & 0xff00) == 0xbf00) {
        !           646:         uint32_t insn2, r1, r3, b2, d2;
        !           647:         insn2 = ldl_code(addr + 2);
        !           648:         r1 = (insn2 >> 20) & 0xf;
        !           649:         r3 = (insn2 >> 16) & 0xf;
        !           650:         b2 = (insn2 >> 12) & 0xf;
        !           651:         d2 = insn2 & 0xfff;
        !           652:         cc = helper_icm(r1, get_address(0, b2, d2), r3);
        !           653:     } else {
        !           654: abort:
        !           655:         cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n",
        !           656:                   insn);
        !           657:     }
        !           658:     return cc;
        !           659: }
        !           660: 
        !           661: /* absolute value 32-bit */
        !           662: uint32_t HELPER(abs_i32)(int32_t val)
        !           663: {
        !           664:     if (val < 0) {
        !           665:         return -val;
        !           666:     } else {
        !           667:         return val;
        !           668:     }
        !           669: }
        !           670: 
        !           671: /* negative absolute value 32-bit */
        !           672: int32_t HELPER(nabs_i32)(int32_t val)
        !           673: {
        !           674:     if (val < 0) {
        !           675:         return val;
        !           676:     } else {
        !           677:         return -val;
        !           678:     }
        !           679: }
        !           680: 
        !           681: /* absolute value 64-bit */
        !           682: uint64_t HELPER(abs_i64)(int64_t val)
        !           683: {
        !           684:     HELPER_LOG("%s: val 0x%" PRIx64 "\n", __FUNCTION__, val);
        !           685: 
        !           686:     if (val < 0) {
        !           687:         return -val;
        !           688:     } else {
        !           689:         return val;
        !           690:     }
        !           691: }
        !           692: 
        !           693: /* negative absolute value 64-bit */
        !           694: int64_t HELPER(nabs_i64)(int64_t val)
        !           695: {
        !           696:     if (val < 0) {
        !           697:         return val;
        !           698:     } else {
        !           699:         return -val;
        !           700:     }
        !           701: }
        !           702: 
        !           703: /* add with carry 32-bit unsigned */
        !           704: uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
        !           705: {
        !           706:     uint32_t res;
        !           707: 
        !           708:     res = v1 + v2;
        !           709:     if (cc & 2) {
        !           710:         res++;
        !           711:     }
        !           712: 
        !           713:     return res;
        !           714: }
        !           715: 
        !           716: /* store character under mask high operates on the upper half of r1 */
        !           717: void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
        !           718: {
        !           719:     int pos = 56; /* top of the upper half of r1 */
        !           720: 
        !           721:     while (mask) {
        !           722:         if (mask & 8) {
        !           723:             stb(address, (env->regs[r1] >> pos) & 0xff);
        !           724:             address++;
        !           725:         }
        !           726:         mask = (mask << 1) & 0xf;
        !           727:         pos -= 8;
        !           728:     }
        !           729: }
        !           730: 
        !           731: /* insert character under mask high; same as icm, but operates on the
        !           732:    upper half of r1 */
        !           733: uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
        !           734: {
        !           735:     int pos = 56; /* top of the upper half of r1 */
        !           736:     uint64_t rmask = 0xff00000000000000ULL;
        !           737:     uint8_t val = 0;
        !           738:     int ccd = 0;
        !           739:     uint32_t cc = 0;
        !           740: 
        !           741:     while (mask) {
        !           742:         if (mask & 8) {
        !           743:             env->regs[r1] &= ~rmask;
        !           744:             val = ldub(address);
        !           745:             if ((val & 0x80) && !ccd) {
        !           746:                 cc = 1;
        !           747:             }
        !           748:             ccd = 1;
        !           749:             if (val && cc == 0) {
        !           750:                 cc = 2;
        !           751:             }
        !           752:             env->regs[r1] |= (uint64_t)val << pos;
        !           753:             address++;
        !           754:         }
        !           755:         mask = (mask << 1) & 0xf;
        !           756:         pos -= 8;
        !           757:         rmask >>= 8;
        !           758:     }
        !           759: 
        !           760:     return cc;
        !           761: }
        !           762: 
        !           763: /* insert psw mask and condition code into r1 */
        !           764: void HELPER(ipm)(uint32_t cc, uint32_t r1)
        !           765: {
        !           766:     uint64_t r = env->regs[r1];
        !           767: 
        !           768:     r &= 0xffffffff00ffffffULL;
        !           769:     r |= (cc << 28) | ( (env->psw.mask >> 40) & 0xf );
        !           770:     env->regs[r1] = r;
        !           771:     HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __FUNCTION__,
        !           772:                cc, env->psw.mask, r);
        !           773: }
        !           774: 
        !           775: /* load access registers r1 to r3 from memory at a2 */
        !           776: void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3)
        !           777: {
        !           778:     int i;
        !           779: 
        !           780:     for (i = r1;; i = (i + 1) % 16) {
        !           781:         env->aregs[i] = ldl(a2);
        !           782:         a2 += 4;
        !           783: 
        !           784:         if (i == r3) {
        !           785:             break;
        !           786:         }
        !           787:     }
        !           788: }
        !           789: 
        !           790: /* store access registers r1 to r3 in memory at a2 */
        !           791: void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3)
        !           792: {
        !           793:     int i;
        !           794: 
        !           795:     for (i = r1;; i = (i + 1) % 16) {
        !           796:         stl(a2, env->aregs[i]);
        !           797:         a2 += 4;
        !           798: 
        !           799:         if (i == r3) {
        !           800:             break;
        !           801:         }
        !           802:     }
        !           803: }
        !           804: 
        !           805: /* move long */
        !           806: uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2)
        !           807: {
        !           808:     uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
        !           809:     uint64_t dest = get_address_31fix(r1);
        !           810:     uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
        !           811:     uint64_t src = get_address_31fix(r2);
        !           812:     uint8_t pad = src >> 24;
        !           813:     uint8_t v;
        !           814:     uint32_t cc;
        !           815: 
        !           816:     if (destlen == srclen) {
        !           817:         cc = 0;
        !           818:     } else if (destlen < srclen) {
        !           819:         cc = 1;
        !           820:     } else {
        !           821:         cc = 2;
        !           822:     }
        !           823: 
        !           824:     if (srclen > destlen) {
        !           825:         srclen = destlen;
        !           826:     }
        !           827: 
        !           828:     for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
        !           829:         v = ldub(src);
        !           830:         stb(dest, v);
        !           831:     }
        !           832: 
        !           833:     for (; destlen; dest++, destlen--) {
        !           834:         stb(dest, pad);
        !           835:     }
        !           836: 
        !           837:     env->regs[r1 + 1] = destlen;
        !           838:     /* can't use srclen here, we trunc'ed it */
        !           839:     env->regs[r2 + 1] -= src - env->regs[r2];
        !           840:     env->regs[r1] = dest;
        !           841:     env->regs[r2] = src;
        !           842: 
        !           843:     return cc;
        !           844: }
        !           845: 
        !           846: /* move long extended another memcopy insn with more bells and whistles */
        !           847: uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3)
        !           848: {
        !           849:     uint64_t destlen = env->regs[r1 + 1];
        !           850:     uint64_t dest = env->regs[r1];
        !           851:     uint64_t srclen = env->regs[r3 + 1];
        !           852:     uint64_t src = env->regs[r3];
        !           853:     uint8_t pad = a2 & 0xff;
        !           854:     uint8_t v;
        !           855:     uint32_t cc;
        !           856: 
        !           857:     if (!(env->psw.mask & PSW_MASK_64)) {
        !           858:         destlen = (uint32_t)destlen;
        !           859:         srclen = (uint32_t)srclen;
        !           860:         dest &= 0x7fffffff;
        !           861:         src &= 0x7fffffff;
        !           862:     }
        !           863: 
        !           864:     if (destlen == srclen) {
        !           865:         cc = 0;
        !           866:     } else if (destlen < srclen) {
        !           867:         cc = 1;
        !           868:     } else {
        !           869:         cc = 2;
        !           870:     }
        !           871: 
        !           872:     if (srclen > destlen) {
        !           873:         srclen = destlen;
        !           874:     }
        !           875: 
        !           876:     for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
        !           877:         v = ldub(src);
        !           878:         stb(dest, v);
        !           879:     }
        !           880: 
        !           881:     for (; destlen; dest++, destlen--) {
        !           882:         stb(dest, pad);
        !           883:     }
        !           884: 
        !           885:     env->regs[r1 + 1] = destlen;
        !           886:     /* can't use srclen here, we trunc'ed it */
        !           887:     /* FIXME: 31-bit mode! */
        !           888:     env->regs[r3 + 1] -= src - env->regs[r3];
        !           889:     env->regs[r1] = dest;
        !           890:     env->regs[r3] = src;
        !           891: 
        !           892:     return cc;
        !           893: }
        !           894: 
        !           895: /* compare logical long extended memcompare insn with padding */
        !           896: uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
        !           897: {
        !           898:     uint64_t destlen = env->regs[r1 + 1];
        !           899:     uint64_t dest = get_address_31fix(r1);
        !           900:     uint64_t srclen = env->regs[r3 + 1];
        !           901:     uint64_t src = get_address_31fix(r3);
        !           902:     uint8_t pad = a2 & 0xff;
        !           903:     uint8_t v1 = 0,v2 = 0;
        !           904:     uint32_t cc = 0;
        !           905: 
        !           906:     if (!(destlen || srclen)) {
        !           907:         return cc;
        !           908:     }
        !           909: 
        !           910:     if (srclen > destlen) {
        !           911:         srclen = destlen;
        !           912:     }
        !           913: 
        !           914:     for (; destlen || srclen; src++, dest++, destlen--, srclen--) {
        !           915:         v1 = srclen ? ldub(src) : pad;
        !           916:         v2 = destlen ? ldub(dest) : pad;
        !           917:         if (v1 != v2) {
        !           918:             cc = (v1 < v2) ? 1 : 2;
        !           919:             break;
        !           920:         }
        !           921:     }
        !           922: 
        !           923:     env->regs[r1 + 1] = destlen;
        !           924:     /* can't use srclen here, we trunc'ed it */
        !           925:     env->regs[r3 + 1] -= src - env->regs[r3];
        !           926:     env->regs[r1] = dest;
        !           927:     env->regs[r3] = src;
        !           928: 
        !           929:     return cc;
        !           930: }
        !           931: 
        !           932: /* subtract unsigned v2 from v1 with borrow */
        !           933: uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
        !           934: {
        !           935:     uint32_t v1 = env->regs[r1];
        !           936:     uint32_t res = v1 + (~v2) + (cc >> 1);
        !           937: 
        !           938:     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
        !           939:     if (cc & 2) {
        !           940:         /* borrow */
        !           941:         return v1 ? 1 : 0;
        !           942:     } else {
        !           943:         return v1 ? 3 : 2;
        !           944:     }
        !           945: }
        !           946: 
        !           947: /* subtract unsigned v2 from v1 with borrow */
        !           948: uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
        !           949: {
        !           950:     uint64_t res = v1 + (~v2) + (cc >> 1);
        !           951: 
        !           952:     env->regs[r1] = res;
        !           953:     if (cc & 2) {
        !           954:         /* borrow */
        !           955:         return v1 ? 1 : 0;
        !           956:     } else {
        !           957:         return v1 ? 3 : 2;
        !           958:     }
        !           959: }
        !           960: 
        !           961: static inline int float_comp_to_cc(int float_compare)
        !           962: {
        !           963:     switch (float_compare) {
        !           964:     case float_relation_equal:
        !           965:         return 0;
        !           966:     case float_relation_less:
        !           967:         return 1;
        !           968:     case float_relation_greater:
        !           969:         return 2;
        !           970:     case float_relation_unordered:
        !           971:         return 3;
        !           972:     default:
        !           973:         cpu_abort(env, "unknown return value for float compare\n");
        !           974:     }
        !           975: }
        !           976: 
        !           977: /* condition codes for binary FP ops */
        !           978: static uint32_t set_cc_f32(float32 v1, float32 v2)
        !           979: {
        !           980:     return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status));
        !           981: }
        !           982: 
        !           983: static uint32_t set_cc_f64(float64 v1, float64 v2)
        !           984: {
        !           985:     return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status));
        !           986: }
        !           987: 
        !           988: /* condition codes for unary FP ops */
        !           989: static uint32_t set_cc_nz_f32(float32 v)
        !           990: {
        !           991:     if (float32_is_any_nan(v)) {
        !           992:         return 3;
        !           993:     } else if (float32_is_zero(v)) {
        !           994:         return 0;
        !           995:     } else if (float32_is_neg(v)) {
        !           996:         return 1;
        !           997:     } else {
        !           998:         return 2;
        !           999:     }
        !          1000: }
        !          1001: 
        !          1002: static uint32_t set_cc_nz_f64(float64 v)
        !          1003: {
        !          1004:     if (float64_is_any_nan(v)) {
        !          1005:         return 3;
        !          1006:     } else if (float64_is_zero(v)) {
        !          1007:         return 0;
        !          1008:     } else if (float64_is_neg(v)) {
        !          1009:         return 1;
        !          1010:     } else {
        !          1011:         return 2;
        !          1012:     }
        !          1013: }
        !          1014: 
        !          1015: static uint32_t set_cc_nz_f128(float128 v)
        !          1016: {
        !          1017:     if (float128_is_any_nan(v)) {
        !          1018:         return 3;
        !          1019:     } else if (float128_is_zero(v)) {
        !          1020:         return 0;
        !          1021:     } else if (float128_is_neg(v)) {
        !          1022:         return 1;
        !          1023:     } else {
        !          1024:         return 2;
        !          1025:     }
        !          1026: }
        !          1027: 
        !          1028: /* convert 32-bit int to 64-bit float */
        !          1029: void HELPER(cdfbr)(uint32_t f1, int32_t v2)
        !          1030: {
        !          1031:     HELPER_LOG("%s: converting %d to f%d\n", __FUNCTION__, v2, f1);
        !          1032:     env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
        !          1033: }
        !          1034: 
        !          1035: /* convert 32-bit int to 128-bit float */
        !          1036: void HELPER(cxfbr)(uint32_t f1, int32_t v2)
        !          1037: {
        !          1038:     CPU_QuadU v1;
        !          1039:     v1.q = int32_to_float128(v2, &env->fpu_status);
        !          1040:     env->fregs[f1].ll = v1.ll.upper;
        !          1041:     env->fregs[f1 + 2].ll = v1.ll.lower;
        !          1042: }
        !          1043: 
        !          1044: /* convert 64-bit int to 32-bit float */
        !          1045: void HELPER(cegbr)(uint32_t f1, int64_t v2)
        !          1046: {
        !          1047:     HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1);
        !          1048:     env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
        !          1049: }
        !          1050: 
        !          1051: /* convert 64-bit int to 64-bit float */
        !          1052: void HELPER(cdgbr)(uint32_t f1, int64_t v2)
        !          1053: {
        !          1054:     HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1);
        !          1055:     env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
        !          1056: }
        !          1057: 
        !          1058: /* convert 64-bit int to 128-bit float */
        !          1059: void HELPER(cxgbr)(uint32_t f1, int64_t v2)
        !          1060: {
        !          1061:     CPU_QuadU x1;
        !          1062:     x1.q = int64_to_float128(v2, &env->fpu_status);
        !          1063:     HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __FUNCTION__, v2,
        !          1064:                x1.ll.upper, x1.ll.lower);
        !          1065:     env->fregs[f1].ll = x1.ll.upper;
        !          1066:     env->fregs[f1 + 2].ll = x1.ll.lower;
        !          1067: }
        !          1068: 
        !          1069: /* convert 32-bit int to 32-bit float */
        !          1070: void HELPER(cefbr)(uint32_t f1, int32_t v2)
        !          1071: {
        !          1072:     env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
        !          1073:     HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __FUNCTION__, v2,
        !          1074:                env->fregs[f1].l.upper, f1);
        !          1075: }
        !          1076: 
        !          1077: /* 32-bit FP addition RR */
        !          1078: uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
        !          1079: {
        !          1080:     env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
        !          1081:                                          env->fregs[f2].l.upper,
        !          1082:                                          &env->fpu_status);
        !          1083:     HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
        !          1084:                env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
        !          1085: 
        !          1086:     return set_cc_nz_f32(env->fregs[f1].l.upper);
        !          1087: }
        !          1088: 
        !          1089: /* 64-bit FP addition RR */
        !          1090: uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2)
        !          1091: {
        !          1092:     env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
        !          1093:                                    &env->fpu_status);
        !          1094:     HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __FUNCTION__,
        !          1095:                env->fregs[f2].d, env->fregs[f1].d, f1);
        !          1096: 
        !          1097:     return set_cc_nz_f64(env->fregs[f1].d);
        !          1098: }
        !          1099: 
        !          1100: /* 32-bit FP subtraction RR */
        !          1101: uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
        !          1102: {
        !          1103:     env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
        !          1104:                                          env->fregs[f2].l.upper,
        !          1105:                                          &env->fpu_status);
        !          1106:     HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
        !          1107:                env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
        !          1108: 
        !          1109:     return set_cc_nz_f32(env->fregs[f1].l.upper);
        !          1110: }
        !          1111: 
        !          1112: /* 64-bit FP subtraction RR */
        !          1113: uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
        !          1114: {
        !          1115:     env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
        !          1116:                                    &env->fpu_status);
        !          1117:     HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
        !          1118:                __FUNCTION__, env->fregs[f2].d, env->fregs[f1].d, f1);
        !          1119: 
        !          1120:     return set_cc_nz_f64(env->fregs[f1].d);
        !          1121: }
        !          1122: 
        !          1123: /* 32-bit FP division RR */
        !          1124: void HELPER(debr)(uint32_t f1, uint32_t f2)
        !          1125: {
        !          1126:     env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
        !          1127:                                          env->fregs[f2].l.upper,
        !          1128:                                          &env->fpu_status);
        !          1129: }
        !          1130: 
        !          1131: /* 128-bit FP division RR */
        !          1132: void HELPER(dxbr)(uint32_t f1, uint32_t f2)
        !          1133: {
        !          1134:     CPU_QuadU v1;
        !          1135:     v1.ll.upper = env->fregs[f1].ll;
        !          1136:     v1.ll.lower = env->fregs[f1 + 2].ll;
        !          1137:     CPU_QuadU v2;
        !          1138:     v2.ll.upper = env->fregs[f2].ll;
        !          1139:     v2.ll.lower = env->fregs[f2 + 2].ll;
        !          1140:     CPU_QuadU res;
        !          1141:     res.q = float128_div(v1.q, v2.q, &env->fpu_status);
        !          1142:     env->fregs[f1].ll = res.ll.upper;
        !          1143:     env->fregs[f1 + 2].ll = res.ll.lower;
        !          1144: }
        !          1145: 
        !          1146: /* 64-bit FP multiplication RR */
        !          1147: void HELPER(mdbr)(uint32_t f1, uint32_t f2)
        !          1148: {
        !          1149:     env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
        !          1150:                                    &env->fpu_status);
        !          1151: }
        !          1152: 
        !          1153: /* 128-bit FP multiplication RR */
        !          1154: void HELPER(mxbr)(uint32_t f1, uint32_t f2)
        !          1155: {
        !          1156:     CPU_QuadU v1;
        !          1157:     v1.ll.upper = env->fregs[f1].ll;
        !          1158:     v1.ll.lower = env->fregs[f1 + 2].ll;
        !          1159:     CPU_QuadU v2;
        !          1160:     v2.ll.upper = env->fregs[f2].ll;
        !          1161:     v2.ll.lower = env->fregs[f2 + 2].ll;
        !          1162:     CPU_QuadU res;
        !          1163:     res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
        !          1164:     env->fregs[f1].ll = res.ll.upper;
        !          1165:     env->fregs[f1 + 2].ll = res.ll.lower;
        !          1166: }
        !          1167: 
        !          1168: /* convert 32-bit float to 64-bit float */
        !          1169: void HELPER(ldebr)(uint32_t r1, uint32_t r2)
        !          1170: {
        !          1171:     env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
        !          1172:                                           &env->fpu_status);
        !          1173: }
        !          1174: 
        !          1175: /* convert 128-bit float to 64-bit float */
        !          1176: void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
        !          1177: {
        !          1178:     CPU_QuadU x2;
        !          1179:     x2.ll.upper = env->fregs[f2].ll;
        !          1180:     x2.ll.lower = env->fregs[f2 + 2].ll;
        !          1181:     env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
        !          1182:     HELPER_LOG("%s: to 0x%ld\n", __FUNCTION__, env->fregs[f1].d);
        !          1183: }
        !          1184: 
        !          1185: /* convert 64-bit float to 128-bit float */
        !          1186: void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
        !          1187: {
        !          1188:     CPU_QuadU res;
        !          1189:     res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
        !          1190:     env->fregs[f1].ll = res.ll.upper;
        !          1191:     env->fregs[f1 + 2].ll = res.ll.lower;
        !          1192: }
        !          1193: 
        !          1194: /* convert 64-bit float to 32-bit float */
        !          1195: void HELPER(ledbr)(uint32_t f1, uint32_t f2)
        !          1196: {
        !          1197:     float64 d2 = env->fregs[f2].d;
        !          1198:     env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
        !          1199: }
        !          1200: 
        !          1201: /* convert 128-bit float to 32-bit float */
        !          1202: void HELPER(lexbr)(uint32_t f1, uint32_t f2)
        !          1203: {
        !          1204:     CPU_QuadU x2;
        !          1205:     x2.ll.upper = env->fregs[f2].ll;
        !          1206:     x2.ll.lower = env->fregs[f2 + 2].ll;
        !          1207:     env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
        !          1208:     HELPER_LOG("%s: to 0x%d\n", __FUNCTION__, env->fregs[f1].l.upper);
        !          1209: }
        !          1210: 
        !          1211: /* absolute value of 32-bit float */
        !          1212: uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
        !          1213: {
        !          1214:     float32 v1;
        !          1215:     float32 v2 = env->fregs[f2].d;
        !          1216:     v1 = float32_abs(v2);
        !          1217:     env->fregs[f1].d = v1;
        !          1218:     return set_cc_nz_f32(v1);
        !          1219: }
        !          1220: 
        !          1221: /* absolute value of 64-bit float */
        !          1222: uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
        !          1223: {
        !          1224:     float64 v1;
        !          1225:     float64 v2 = env->fregs[f2].d;
        !          1226:     v1 = float64_abs(v2);
        !          1227:     env->fregs[f1].d = v1;
        !          1228:     return set_cc_nz_f64(v1);
        !          1229: }
        !          1230: 
        !          1231: /* absolute value of 128-bit float */
        !          1232: uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
        !          1233: {
        !          1234:     CPU_QuadU v1;
        !          1235:     CPU_QuadU v2;
        !          1236:     v2.ll.upper = env->fregs[f2].ll;
        !          1237:     v2.ll.lower = env->fregs[f2 + 2].ll;
        !          1238:     v1.q = float128_abs(v2.q);
        !          1239:     env->fregs[f1].ll = v1.ll.upper;
        !          1240:     env->fregs[f1 + 2].ll = v1.ll.lower;
        !          1241:     return set_cc_nz_f128(v1.q);
        !          1242: }
        !          1243: 
        !          1244: /* load and test 64-bit float */
        !          1245: uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2)
        !          1246: {
        !          1247:     env->fregs[f1].d = env->fregs[f2].d;
        !          1248:     return set_cc_nz_f64(env->fregs[f1].d);
        !          1249: }
        !          1250: 
        !          1251: /* load and test 32-bit float */
        !          1252: uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2)
        !          1253: {
        !          1254:     env->fregs[f1].l.upper = env->fregs[f2].l.upper;
        !          1255:     return set_cc_nz_f32(env->fregs[f1].l.upper);
        !          1256: }
        !          1257: 
        !          1258: /* load and test 128-bit float */
        !          1259: uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
        !          1260: {
        !          1261:     CPU_QuadU x;
        !          1262:     x.ll.upper = env->fregs[f2].ll;
        !          1263:     x.ll.lower = env->fregs[f2 + 2].ll;
        !          1264:     env->fregs[f1].ll = x.ll.upper;
        !          1265:     env->fregs[f1 + 2].ll = x.ll.lower;
        !          1266:     return set_cc_nz_f128(x.q);
        !          1267: }
        !          1268: 
        !          1269: /* load complement of 32-bit float */
        !          1270: uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2)
        !          1271: {
        !          1272:     env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
        !          1273: 
        !          1274:     return set_cc_nz_f32(env->fregs[f1].l.upper);
        !          1275: }
        !          1276: 
        !          1277: /* load complement of 64-bit float */
        !          1278: uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
        !          1279: {
        !          1280:     env->fregs[f1].d = float64_chs(env->fregs[f2].d);
        !          1281: 
        !          1282:     return set_cc_nz_f64(env->fregs[f1].d);
        !          1283: }
        !          1284: 
        !          1285: /* load complement of 128-bit float */
        !          1286: uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
        !          1287: {
        !          1288:     CPU_QuadU x1, x2;
        !          1289:     x2.ll.upper = env->fregs[f2].ll;
        !          1290:     x2.ll.lower = env->fregs[f2 + 2].ll;
        !          1291:     x1.q = float128_chs(x2.q);
        !          1292:     env->fregs[f1].ll = x1.ll.upper;
        !          1293:     env->fregs[f1 + 2].ll = x1.ll.lower;
        !          1294:     return set_cc_nz_f128(x1.q);
        !          1295: }
        !          1296: 
        !          1297: /* 32-bit FP addition RM */
        !          1298: void HELPER(aeb)(uint32_t f1, uint32_t val)
        !          1299: {
        !          1300:     float32 v1 = env->fregs[f1].l.upper;
        !          1301:     CPU_FloatU v2;
        !          1302:     v2.l = val;
        !          1303:     HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __FUNCTION__,
        !          1304:                v1, f1, v2.f);
        !          1305:     env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
        !          1306: }
        !          1307: 
        !          1308: /* 32-bit FP division RM */
        !          1309: void HELPER(deb)(uint32_t f1, uint32_t val)
        !          1310: {
        !          1311:     float32 v1 = env->fregs[f1].l.upper;
        !          1312:     CPU_FloatU v2;
        !          1313:     v2.l = val;
        !          1314:     HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __FUNCTION__,
        !          1315:                v1, f1, v2.f);
        !          1316:     env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
        !          1317: }
        !          1318: 
        !          1319: /* 32-bit FP multiplication RM */
        !          1320: void HELPER(meeb)(uint32_t f1, uint32_t val)
        !          1321: {
        !          1322:     float32 v1 = env->fregs[f1].l.upper;
        !          1323:     CPU_FloatU v2;
        !          1324:     v2.l = val;
        !          1325:     HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __FUNCTION__,
        !          1326:                v1, f1, v2.f);
        !          1327:     env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
        !          1328: }
        !          1329: 
        !          1330: /* 32-bit FP compare RR */
        !          1331: uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
        !          1332: {
        !          1333:     float32 v1 = env->fregs[f1].l.upper;
        !          1334:     float32 v2 = env->fregs[f2].l.upper;;
        !          1335:     HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__,
        !          1336:                v1, f1, v2);
        !          1337:     return set_cc_f32(v1, v2);
        !          1338: }
        !          1339: 
        !          1340: /* 64-bit FP compare RR */
        !          1341: uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
        !          1342: {
        !          1343:     float64 v1 = env->fregs[f1].d;
        !          1344:     float64 v2 = env->fregs[f2].d;;
        !          1345:     HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __FUNCTION__,
        !          1346:                v1, f1, v2);
        !          1347:     return set_cc_f64(v1, v2);
        !          1348: }
        !          1349: 
        !          1350: /* 128-bit FP compare RR */
        !          1351: uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
        !          1352: {
        !          1353:     CPU_QuadU v1;
        !          1354:     v1.ll.upper = env->fregs[f1].ll;
        !          1355:     v1.ll.lower = env->fregs[f1 + 2].ll;
        !          1356:     CPU_QuadU v2;
        !          1357:     v2.ll.upper = env->fregs[f2].ll;
        !          1358:     v2.ll.lower = env->fregs[f2 + 2].ll;
        !          1359: 
        !          1360:     return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q,
        !          1361:                             &env->fpu_status));
        !          1362: }
        !          1363: 
        !          1364: /* 64-bit FP compare RM */
        !          1365: uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2)
        !          1366: {
        !          1367:     float64 v1 = env->fregs[f1].d;
        !          1368:     CPU_DoubleU v2;
        !          1369:     v2.ll = ldq(a2);
        !          1370:     HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __FUNCTION__, v1,
        !          1371:                f1, v2.d);
        !          1372:     return set_cc_f64(v1, v2.d);
        !          1373: }
        !          1374: 
        !          1375: /* 64-bit FP addition RM */
        !          1376: uint32_t HELPER(adb)(uint32_t f1, uint64_t a2)
        !          1377: {
        !          1378:     float64 v1 = env->fregs[f1].d;
        !          1379:     CPU_DoubleU v2;
        !          1380:     v2.ll = ldq(a2);
        !          1381:     HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __FUNCTION__,
        !          1382:                v1, f1, v2.d);
        !          1383:     env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
        !          1384:     return set_cc_nz_f64(v1);
        !          1385: }
        !          1386: 
        !          1387: /* 32-bit FP subtraction RM */
        !          1388: void HELPER(seb)(uint32_t f1, uint32_t val)
        !          1389: {
        !          1390:     float32 v1 = env->fregs[f1].l.upper;
        !          1391:     CPU_FloatU v2;
        !          1392:     v2.l = val;
        !          1393:     env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
        !          1394: }
        !          1395: 
        !          1396: /* 64-bit FP subtraction RM */
        !          1397: uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2)
        !          1398: {
        !          1399:     float64 v1 = env->fregs[f1].d;
        !          1400:     CPU_DoubleU v2;
        !          1401:     v2.ll = ldq(a2);
        !          1402:     env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
        !          1403:     return set_cc_nz_f64(v1);
        !          1404: }
        !          1405: 
        !          1406: /* 64-bit FP multiplication RM */
        !          1407: void HELPER(mdb)(uint32_t f1, uint64_t a2)
        !          1408: {
        !          1409:     float64 v1 = env->fregs[f1].d;
        !          1410:     CPU_DoubleU v2;
        !          1411:     v2.ll = ldq(a2);
        !          1412:     HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __FUNCTION__,
        !          1413:                v1, f1, v2.d);
        !          1414:     env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
        !          1415: }
        !          1416: 
        !          1417: /* 64-bit FP division RM */
        !          1418: void HELPER(ddb)(uint32_t f1, uint64_t a2)
        !          1419: {
        !          1420:     float64 v1 = env->fregs[f1].d;
        !          1421:     CPU_DoubleU v2;
        !          1422:     v2.ll = ldq(a2);
        !          1423:     HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __FUNCTION__,
        !          1424:                v1, f1, v2.d);
        !          1425:     env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
        !          1426: }
        !          1427: 
        !          1428: static void set_round_mode(int m3)
        !          1429: {
        !          1430:     switch (m3) {
        !          1431:     case 0:
        !          1432:         /* current mode */
        !          1433:         break;
        !          1434:     case 1:
        !          1435:         /* biased round no nearest */
        !          1436:     case 4:
        !          1437:         /* round to nearest */
        !          1438:         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
        !          1439:         break;
        !          1440:     case 5:
        !          1441:         /* round to zero */
        !          1442:         set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
        !          1443:         break;
        !          1444:     case 6:
        !          1445:         /* round to +inf */
        !          1446:         set_float_rounding_mode(float_round_up, &env->fpu_status);
        !          1447:         break;
        !          1448:     case 7:
        !          1449:         /* round to -inf */
        !          1450:         set_float_rounding_mode(float_round_down, &env->fpu_status);
        !          1451:         break;
        !          1452:     }
        !          1453: }
        !          1454: 
        !          1455: /* convert 32-bit float to 64-bit int */
        !          1456: uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
        !          1457: {
        !          1458:     float32 v2 = env->fregs[f2].l.upper;
        !          1459:     set_round_mode(m3);
        !          1460:     env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
        !          1461:     return set_cc_nz_f32(v2);
        !          1462: }
        !          1463: 
        !          1464: /* convert 64-bit float to 64-bit int */
        !          1465: uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
        !          1466: {
        !          1467:     float64 v2 = env->fregs[f2].d;
        !          1468:     set_round_mode(m3);
        !          1469:     env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
        !          1470:     return set_cc_nz_f64(v2);
        !          1471: }
        !          1472: 
        !          1473: /* convert 128-bit float to 64-bit int */
        !          1474: uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
        !          1475: {
        !          1476:     CPU_QuadU v2;
        !          1477:     v2.ll.upper = env->fregs[f2].ll;
        !          1478:     v2.ll.lower = env->fregs[f2 + 2].ll;
        !          1479:     set_round_mode(m3);
        !          1480:     env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
        !          1481:     if (float128_is_any_nan(v2.q)) {
        !          1482:         return 3;
        !          1483:     } else if (float128_is_zero(v2.q)) {
        !          1484:         return 0;
        !          1485:     } else if (float128_is_neg(v2.q)) {
        !          1486:         return 1;
        !          1487:     } else {
        !          1488:         return 2;
        !          1489:     }
        !          1490: }
        !          1491: 
        !          1492: /* convert 32-bit float to 32-bit int */
        !          1493: uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
        !          1494: {
        !          1495:     float32 v2 = env->fregs[f2].l.upper;
        !          1496:     set_round_mode(m3);
        !          1497:     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
        !          1498:                      float32_to_int32(v2, &env->fpu_status);
        !          1499:     return set_cc_nz_f32(v2);
        !          1500: }
        !          1501: 
        !          1502: /* convert 64-bit float to 32-bit int */
        !          1503: uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
        !          1504: {
        !          1505:     float64 v2 = env->fregs[f2].d;
        !          1506:     set_round_mode(m3);
        !          1507:     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
        !          1508:                      float64_to_int32(v2, &env->fpu_status);
        !          1509:     return set_cc_nz_f64(v2);
        !          1510: }
        !          1511: 
        !          1512: /* convert 128-bit float to 32-bit int */
        !          1513: uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
        !          1514: {
        !          1515:     CPU_QuadU v2;
        !          1516:     v2.ll.upper = env->fregs[f2].ll;
        !          1517:     v2.ll.lower = env->fregs[f2 + 2].ll;
        !          1518:     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
        !          1519:                      float128_to_int32(v2.q, &env->fpu_status);
        !          1520:     return set_cc_nz_f128(v2.q);
        !          1521: }
        !          1522: 
        !          1523: /* load 32-bit FP zero */
        !          1524: void HELPER(lzer)(uint32_t f1)
        !          1525: {
        !          1526:     env->fregs[f1].l.upper = float32_zero;
        !          1527: }
        !          1528: 
        !          1529: /* load 64-bit FP zero */
        !          1530: void HELPER(lzdr)(uint32_t f1)
        !          1531: {
        !          1532:     env->fregs[f1].d = float64_zero;
        !          1533: }
        !          1534: 
        !          1535: /* load 128-bit FP zero */
        !          1536: void HELPER(lzxr)(uint32_t f1)
        !          1537: {
        !          1538:     CPU_QuadU x;
        !          1539:     x.q = float64_to_float128(float64_zero, &env->fpu_status);
        !          1540:     env->fregs[f1].ll = x.ll.upper;
        !          1541:     env->fregs[f1 + 1].ll = x.ll.lower;
        !          1542: }
        !          1543: 
        !          1544: /* 128-bit FP subtraction RR */
        !          1545: uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
        !          1546: {
        !          1547:     CPU_QuadU v1;
        !          1548:     v1.ll.upper = env->fregs[f1].ll;
        !          1549:     v1.ll.lower = env->fregs[f1 + 2].ll;
        !          1550:     CPU_QuadU v2;
        !          1551:     v2.ll.upper = env->fregs[f2].ll;
        !          1552:     v2.ll.lower = env->fregs[f2 + 2].ll;
        !          1553:     CPU_QuadU res;
        !          1554:     res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
        !          1555:     env->fregs[f1].ll = res.ll.upper;
        !          1556:     env->fregs[f1 + 2].ll = res.ll.lower;
        !          1557:     return set_cc_nz_f128(res.q);
        !          1558: }
        !          1559: 
        !          1560: /* 128-bit FP addition RR */
        !          1561: uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
        !          1562: {
        !          1563:     CPU_QuadU v1;
        !          1564:     v1.ll.upper = env->fregs[f1].ll;
        !          1565:     v1.ll.lower = env->fregs[f1 + 2].ll;
        !          1566:     CPU_QuadU v2;
        !          1567:     v2.ll.upper = env->fregs[f2].ll;
        !          1568:     v2.ll.lower = env->fregs[f2 + 2].ll;
        !          1569:     CPU_QuadU res;
        !          1570:     res.q = float128_add(v1.q, v2.q, &env->fpu_status);
        !          1571:     env->fregs[f1].ll = res.ll.upper;
        !          1572:     env->fregs[f1 + 2].ll = res.ll.lower;
        !          1573:     return set_cc_nz_f128(res.q);
        !          1574: }
        !          1575: 
        !          1576: /* 32-bit FP multiplication RR */
        !          1577: void HELPER(meebr)(uint32_t f1, uint32_t f2)
        !          1578: {
        !          1579:     env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
        !          1580:                                          env->fregs[f2].l.upper,
        !          1581:                                          &env->fpu_status);
        !          1582: }
        !          1583: 
        !          1584: /* 64-bit FP division RR */
        !          1585: void HELPER(ddbr)(uint32_t f1, uint32_t f2)
        !          1586: {
        !          1587:     env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
        !          1588:                                    &env->fpu_status);
        !          1589: }
        !          1590: 
        !          1591: /* 64-bit FP multiply and add RM */
        !          1592: void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
        !          1593: {
        !          1594:     HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __FUNCTION__, f1, a2, f3);
        !          1595:     CPU_DoubleU v2;
        !          1596:     v2.ll = ldq(a2);
        !          1597:     env->fregs[f1].d = float64_add(env->fregs[f1].d,
        !          1598:                                    float64_mul(v2.d, env->fregs[f3].d,
        !          1599:                                                &env->fpu_status),
        !          1600:                                    &env->fpu_status);
        !          1601: }
        !          1602: 
        !          1603: /* 64-bit FP multiply and add RR */
        !          1604: void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
        !          1605: {
        !          1606:     HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3);
        !          1607:     env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
        !          1608:                                                env->fregs[f3].d,
        !          1609:                                                &env->fpu_status),
        !          1610:                                    env->fregs[f1].d, &env->fpu_status);
        !          1611: }
        !          1612: 
        !          1613: /* 64-bit FP multiply and subtract RR */
        !          1614: void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2)
        !          1615: {
        !          1616:     HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3);
        !          1617:     env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
        !          1618:                                                env->fregs[f3].d,
        !          1619:                                                &env->fpu_status),
        !          1620:                                    env->fregs[f1].d, &env->fpu_status);
        !          1621: }
        !          1622: 
        !          1623: /* 32-bit FP multiply and add RR */
        !          1624: void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
        !          1625: {
        !          1626:     env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
        !          1627:                                          float32_mul(env->fregs[f2].l.upper,
        !          1628:                                                      env->fregs[f3].l.upper,
        !          1629:                                                      &env->fpu_status),
        !          1630:                                          &env->fpu_status);
        !          1631: }
        !          1632: 
        !          1633: /* convert 64-bit float to 128-bit float */
        !          1634: void HELPER(lxdb)(uint32_t f1, uint64_t a2)
        !          1635: {
        !          1636:     CPU_DoubleU v2;
        !          1637:     v2.ll = ldq(a2);
        !          1638:     CPU_QuadU v1;
        !          1639:     v1.q = float64_to_float128(v2.d, &env->fpu_status);
        !          1640:     env->fregs[f1].ll = v1.ll.upper;
        !          1641:     env->fregs[f1 + 2].ll = v1.ll.lower;
        !          1642: }
        !          1643: 
        !          1644: /* test data class 32-bit */
        !          1645: uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
        !          1646: {
        !          1647:     float32 v1 = env->fregs[f1].l.upper;
        !          1648:     int neg = float32_is_neg(v1);
        !          1649:     uint32_t cc = 0;
        !          1650: 
        !          1651:     HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, (long)v1, m2, neg);
        !          1652:     if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
        !          1653:         (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
        !          1654:         (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
        !          1655:         (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
        !          1656:         cc = 1;
        !          1657:     } else if (m2 & (1 << (9-neg))) {
        !          1658:         /* assume normalized number */
        !          1659:         cc = 1;
        !          1660:     }
        !          1661: 
        !          1662:     /* FIXME: denormalized? */
        !          1663:     return cc;
        !          1664: }
        !          1665: 
        !          1666: /* test data class 64-bit */
        !          1667: uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
        !          1668: {
        !          1669:     float64 v1 = env->fregs[f1].d;
        !          1670:     int neg = float64_is_neg(v1);
        !          1671:     uint32_t cc = 0;
        !          1672: 
        !          1673:     HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, v1, m2, neg);
        !          1674:     if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
        !          1675:         (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
        !          1676:         (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
        !          1677:         (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
        !          1678:         cc = 1;
        !          1679:     } else if (m2 & (1 << (9-neg))) {
        !          1680:         /* assume normalized number */
        !          1681:         cc = 1;
        !          1682:     }
        !          1683:     /* FIXME: denormalized? */
        !          1684:     return cc;
        !          1685: }
        !          1686: 
        !          1687: /* test data class 128-bit */
        !          1688: uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
        !          1689: {
        !          1690:     CPU_QuadU v1;
        !          1691:     uint32_t cc = 0;
        !          1692:     v1.ll.upper = env->fregs[f1].ll;
        !          1693:     v1.ll.lower = env->fregs[f1 + 2].ll;
        !          1694: 
        !          1695:     int neg = float128_is_neg(v1.q);
        !          1696:     if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
        !          1697:         (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
        !          1698:         (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
        !          1699:         (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
        !          1700:         cc = 1;
        !          1701:     } else if (m2 & (1 << (9-neg))) {
        !          1702:         /* assume normalized number */
        !          1703:         cc = 1;
        !          1704:     }
        !          1705:     /* FIXME: denormalized? */
        !          1706:     return cc;
        !          1707: }
        !          1708: 
        !          1709: /* find leftmost one */
        !          1710: uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
        !          1711: {
        !          1712:     uint64_t res = 0;
        !          1713:     uint64_t ov2 = v2;
        !          1714: 
        !          1715:     while (!(v2 & 0x8000000000000000ULL) && v2) {
        !          1716:         v2 <<= 1;
        !          1717:         res++;
        !          1718:     }
        !          1719: 
        !          1720:     if (!v2) {
        !          1721:         env->regs[r1] = 64;
        !          1722:         env->regs[r1 + 1] = 0;
        !          1723:         return 0;
        !          1724:     } else {
        !          1725:         env->regs[r1] = res;
        !          1726:         env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
        !          1727:         return 2;
        !          1728:     }
        !          1729: }
        !          1730: 
        !          1731: /* square root 64-bit RR */
        !          1732: void HELPER(sqdbr)(uint32_t f1, uint32_t f2)
        !          1733: {
        !          1734:     env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
        !          1735: }
        !          1736: 
        !          1737: /* checksum */
        !          1738: void HELPER(cksm)(uint32_t r1, uint32_t r2)
        !          1739: {
        !          1740:     uint64_t src = get_address_31fix(r2);
        !          1741:     uint64_t src_len = env->regs[(r2 + 1) & 15];
        !          1742:     uint64_t cksm = (uint32_t)env->regs[r1];
        !          1743: 
        !          1744:     while (src_len >= 4) {
        !          1745:         cksm += ldl(src);
        !          1746: 
        !          1747:         /* move to next word */
        !          1748:         src_len -= 4;
        !          1749:         src += 4;
        !          1750:     }
        !          1751: 
        !          1752:     switch (src_len) {
        !          1753:     case 0:
        !          1754:         break;
        !          1755:     case 1:
        !          1756:         cksm += ldub(src) << 24;
        !          1757:         break;
        !          1758:     case 2:
        !          1759:         cksm += lduw(src) << 16;
        !          1760:         break;
        !          1761:     case 3:
        !          1762:         cksm += lduw(src) << 16;
        !          1763:         cksm += ldub(src + 2) << 8;
        !          1764:         break;
        !          1765:     }
        !          1766: 
        !          1767:     /* indicate we've processed everything */
        !          1768:     env->regs[r2] = src + src_len;
        !          1769:     env->regs[(r2 + 1) & 15] = 0;
        !          1770: 
        !          1771:     /* store result */
        !          1772:     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
        !          1773:                     ((uint32_t)cksm + (cksm >> 32));
        !          1774: }
        !          1775: 
        !          1776: static inline uint32_t cc_calc_ltgt_32(CPUState *env, int32_t src,
        !          1777:                                        int32_t dst)
        !          1778: {
        !          1779:     if (src == dst) {
        !          1780:         return 0;
        !          1781:     } else if (src < dst) {
        !          1782:         return 1;
        !          1783:     } else {
        !          1784:         return 2;
        !          1785:     }
        !          1786: }
        !          1787: 
        !          1788: static inline uint32_t cc_calc_ltgt0_32(CPUState *env, int32_t dst)
        !          1789: {
        !          1790:     return cc_calc_ltgt_32(env, dst, 0);
        !          1791: }
        !          1792: 
        !          1793: static inline uint32_t cc_calc_ltgt_64(CPUState *env, int64_t src,
        !          1794:                                        int64_t dst)
        !          1795: {
        !          1796:     if (src == dst) {
        !          1797:         return 0;
        !          1798:     } else if (src < dst) {
        !          1799:         return 1;
        !          1800:     } else {
        !          1801:         return 2;
        !          1802:     }
        !          1803: }
        !          1804: 
        !          1805: static inline uint32_t cc_calc_ltgt0_64(CPUState *env, int64_t dst)
        !          1806: {
        !          1807:     return cc_calc_ltgt_64(env, dst, 0);
        !          1808: }
        !          1809: 
        !          1810: static inline uint32_t cc_calc_ltugtu_32(CPUState *env, uint32_t src,
        !          1811:                                          uint32_t dst)
        !          1812: {
        !          1813:     if (src == dst) {
        !          1814:         return 0;
        !          1815:     } else if (src < dst) {
        !          1816:         return 1;
        !          1817:     } else {
        !          1818:         return 2;
        !          1819:     }
        !          1820: }
        !          1821: 
        !          1822: static inline uint32_t cc_calc_ltugtu_64(CPUState *env, uint64_t src,
        !          1823:                                          uint64_t dst)
        !          1824: {
        !          1825:     if (src == dst) {
        !          1826:         return 0;
        !          1827:     } else if (src < dst) {
        !          1828:         return 1;
        !          1829:     } else {
        !          1830:         return 2;
        !          1831:     }
        !          1832: }
        !          1833: 
        !          1834: static inline uint32_t cc_calc_tm_32(CPUState *env, uint32_t val, uint32_t mask)
        !          1835: {
        !          1836:     HELPER_LOG("%s: val 0x%x mask 0x%x\n", __FUNCTION__, val, mask);
        !          1837:     uint16_t r = val & mask;
        !          1838:     if (r == 0 || mask == 0) {
        !          1839:         return 0;
        !          1840:     } else if (r == mask) {
        !          1841:         return 3;
        !          1842:     } else {
        !          1843:         return 1;
        !          1844:     }
        !          1845: }
        !          1846: 
        !          1847: /* set condition code for test under mask */
        !          1848: static inline uint32_t cc_calc_tm_64(CPUState *env, uint64_t val, uint32_t mask)
        !          1849: {
        !          1850:     uint16_t r = val & mask;
        !          1851:     HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __FUNCTION__, val, mask, r);
        !          1852:     if (r == 0 || mask == 0) {
        !          1853:         return 0;
        !          1854:     } else if (r == mask) {
        !          1855:         return 3;
        !          1856:     } else {
        !          1857:         while (!(mask & 0x8000)) {
        !          1858:             mask <<= 1;
        !          1859:             val <<= 1;
        !          1860:         }
        !          1861:         if (val & 0x8000) {
        !          1862:             return 2;
        !          1863:         } else {
        !          1864:             return 1;
        !          1865:         }
        !          1866:     }
        !          1867: }
        !          1868: 
        !          1869: static inline uint32_t cc_calc_nz(CPUState *env, uint64_t dst)
        !          1870: {
        !          1871:     return !!dst;
        !          1872: }
        !          1873: 
        !          1874: static inline uint32_t cc_calc_add_64(CPUState *env, int64_t a1, int64_t a2,
        !          1875:                                       int64_t ar)
        !          1876: {
        !          1877:     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
        !          1878:         return 3; /* overflow */
        !          1879:     } else {
        !          1880:         if (ar < 0) {
        !          1881:             return 1;
        !          1882:         } else if (ar > 0) {
        !          1883:             return 2;
        !          1884:         } else {
        !          1885:             return 0;
        !          1886:         }
        !          1887:     }
        !          1888: }
        !          1889: 
        !          1890: static inline uint32_t cc_calc_addu_64(CPUState *env, uint64_t a1, uint64_t a2,
        !          1891:                                        uint64_t ar)
        !          1892: {
        !          1893:     if (ar == 0) {
        !          1894:         if (a1) {
        !          1895:             return 2;
        !          1896:         } else {
        !          1897:             return 0;
        !          1898:         }
        !          1899:     } else {
        !          1900:         if (ar < a1 || ar < a2) {
        !          1901:           return 3;
        !          1902:         } else {
        !          1903:           return 1;
        !          1904:         }
        !          1905:     }
        !          1906: }
        !          1907: 
        !          1908: static inline uint32_t cc_calc_sub_64(CPUState *env, int64_t a1, int64_t a2,
        !          1909:                                       int64_t ar)
        !          1910: {
        !          1911:     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
        !          1912:         return 3; /* overflow */
        !          1913:     } else {
        !          1914:         if (ar < 0) {
        !          1915:             return 1;
        !          1916:         } else if (ar > 0) {
        !          1917:             return 2;
        !          1918:         } else {
        !          1919:             return 0;
        !          1920:         }
        !          1921:     }
        !          1922: }
        !          1923: 
        !          1924: static inline uint32_t cc_calc_subu_64(CPUState *env, uint64_t a1, uint64_t a2,
        !          1925:                                        uint64_t ar)
        !          1926: {
        !          1927:     if (ar == 0) {
        !          1928:         return 2;
        !          1929:     } else {
        !          1930:         if (a2 > a1) {
        !          1931:             return 1;
        !          1932:         } else {
        !          1933:             return 3;
        !          1934:         }
        !          1935:     }
        !          1936: }
        !          1937: 
        !          1938: static inline uint32_t cc_calc_abs_64(CPUState *env, int64_t dst)
        !          1939: {
        !          1940:     if ((uint64_t)dst == 0x8000000000000000ULL) {
        !          1941:         return 3;
        !          1942:     } else if (dst) {
        !          1943:         return 1;
        !          1944:     } else {
        !          1945:         return 0;
        !          1946:     }
        !          1947: }
        !          1948: 
        !          1949: static inline uint32_t cc_calc_nabs_64(CPUState *env, int64_t dst)
        !          1950: {
        !          1951:     return !!dst;
        !          1952: }
        !          1953: 
        !          1954: static inline uint32_t cc_calc_comp_64(CPUState *env, int64_t dst)
        !          1955: {
        !          1956:     if ((uint64_t)dst == 0x8000000000000000ULL) {
        !          1957:         return 3;
        !          1958:     } else if (dst < 0) {
        !          1959:         return 1;
        !          1960:     } else if (dst > 0) {
        !          1961:         return 2;
        !          1962:     } else {
        !          1963:         return 0;
        !          1964:     }
        !          1965: }
        !          1966: 
        !          1967: 
        !          1968: static inline uint32_t cc_calc_add_32(CPUState *env, int32_t a1, int32_t a2,
        !          1969:                                       int32_t ar)
        !          1970: {
        !          1971:     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
        !          1972:         return 3; /* overflow */
        !          1973:     } else {
        !          1974:         if (ar < 0) {
        !          1975:             return 1;
        !          1976:         } else if (ar > 0) {
        !          1977:             return 2;
        !          1978:         } else {
        !          1979:             return 0;
        !          1980:         }
        !          1981:     }
        !          1982: }
        !          1983: 
        !          1984: static inline uint32_t cc_calc_addu_32(CPUState *env, uint32_t a1, uint32_t a2,
        !          1985:                                        uint32_t ar)
        !          1986: {
        !          1987:     if (ar == 0) {
        !          1988:         if (a1) {
        !          1989:           return 2;
        !          1990:         } else {
        !          1991:           return 0;
        !          1992:         }
        !          1993:     } else {
        !          1994:         if (ar < a1 || ar < a2) {
        !          1995:           return 3;
        !          1996:         } else {
        !          1997:           return 1;
        !          1998:         }
        !          1999:     }
        !          2000: }
        !          2001: 
        !          2002: static inline uint32_t cc_calc_sub_32(CPUState *env, int32_t a1, int32_t a2,
        !          2003:                                       int32_t ar)
        !          2004: {
        !          2005:     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
        !          2006:         return 3; /* overflow */
        !          2007:     } else {
        !          2008:         if (ar < 0) {
        !          2009:             return 1;
        !          2010:         } else if (ar > 0) {
        !          2011:             return 2;
        !          2012:         } else {
        !          2013:             return 0;
        !          2014:         }
        !          2015:     }
        !          2016: }
        !          2017: 
        !          2018: static inline uint32_t cc_calc_subu_32(CPUState *env, uint32_t a1, uint32_t a2,
        !          2019:                                        uint32_t ar)
        !          2020: {
        !          2021:     if (ar == 0) {
        !          2022:         return 2;
        !          2023:     } else {
        !          2024:         if (a2 > a1) {
        !          2025:             return 1;
        !          2026:         } else {
        !          2027:             return 3;
        !          2028:         }
        !          2029:     }
        !          2030: }
        !          2031: 
        !          2032: static inline uint32_t cc_calc_abs_32(CPUState *env, int32_t dst)
        !          2033: {
        !          2034:     if ((uint32_t)dst == 0x80000000UL) {
        !          2035:         return 3;
        !          2036:     } else if (dst) {
        !          2037:         return 1;
        !          2038:     } else {
        !          2039:         return 0;
        !          2040:     }
        !          2041: }
        !          2042: 
        !          2043: static inline uint32_t cc_calc_nabs_32(CPUState *env, int32_t dst)
        !          2044: {
        !          2045:     return !!dst;
        !          2046: }
        !          2047: 
        !          2048: static inline uint32_t cc_calc_comp_32(CPUState *env, int32_t dst)
        !          2049: {
        !          2050:     if ((uint32_t)dst == 0x80000000UL) {
        !          2051:         return 3;
        !          2052:     } else if (dst < 0) {
        !          2053:         return 1;
        !          2054:     } else if (dst > 0) {
        !          2055:         return 2;
        !          2056:     } else {
        !          2057:         return 0;
        !          2058:     }
        !          2059: }
        !          2060: 
        !          2061: /* calculate condition code for insert character under mask insn */
        !          2062: static inline uint32_t cc_calc_icm_32(CPUState *env, uint32_t mask, uint32_t val)
        !          2063: {
        !          2064:     HELPER_LOG("%s: mask 0x%x val %d\n", __FUNCTION__, mask, val);
        !          2065:     uint32_t cc;
        !          2066: 
        !          2067:     if (mask == 0xf) {
        !          2068:         if (!val) {
        !          2069:             return 0;
        !          2070:         } else if (val & 0x80000000) {
        !          2071:             return 1;
        !          2072:         } else {
        !          2073:             return 2;
        !          2074:         }
        !          2075:     }
        !          2076: 
        !          2077:     if (!val || !mask) {
        !          2078:         cc = 0;
        !          2079:     } else {
        !          2080:         while (mask != 1) {
        !          2081:             mask >>= 1;
        !          2082:             val >>= 8;
        !          2083:         }
        !          2084:         if (val & 0x80) {
        !          2085:             cc = 1;
        !          2086:         } else {
        !          2087:             cc = 2;
        !          2088:         }
        !          2089:     }
        !          2090:     return cc;
        !          2091: }
        !          2092: 
        !          2093: static inline uint32_t cc_calc_slag(CPUState *env, uint64_t src, uint64_t shift)
        !          2094: {
        !          2095:     uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
        !          2096:     uint64_t match, r;
        !          2097: 
        !          2098:     /* check if the sign bit stays the same */
        !          2099:     if (src & (1ULL << 63)) {
        !          2100:         match = mask;
        !          2101:     } else {
        !          2102:         match = 0;
        !          2103:     }
        !          2104: 
        !          2105:     if ((src & mask) != match) {
        !          2106:         /* overflow */
        !          2107:         return 3;
        !          2108:     }
        !          2109: 
        !          2110:     r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
        !          2111: 
        !          2112:     if ((int64_t)r == 0) {
        !          2113:         return 0;
        !          2114:     } else if ((int64_t)r < 0) {
        !          2115:         return 1;
        !          2116:     }
        !          2117: 
        !          2118:     return 2;
        !          2119: }
        !          2120: 
        !          2121: 
        !          2122: static inline uint32_t do_calc_cc(CPUState *env, uint32_t cc_op, uint64_t src,
        !          2123:                                   uint64_t dst, uint64_t vr)
        !          2124: {
        !          2125:     uint32_t r = 0;
        !          2126: 
        !          2127:     switch (cc_op) {
        !          2128:     case CC_OP_CONST0:
        !          2129:     case CC_OP_CONST1:
        !          2130:     case CC_OP_CONST2:
        !          2131:     case CC_OP_CONST3:
        !          2132:         /* cc_op value _is_ cc */
        !          2133:         r = cc_op;
        !          2134:         break;
        !          2135:     case CC_OP_LTGT0_32:
        !          2136:         r = cc_calc_ltgt0_32(env, dst);
        !          2137:         break;
        !          2138:     case CC_OP_LTGT0_64:
        !          2139:         r =  cc_calc_ltgt0_64(env, dst);
        !          2140:         break;
        !          2141:     case CC_OP_LTGT_32:
        !          2142:         r =  cc_calc_ltgt_32(env, src, dst);
        !          2143:         break;
        !          2144:     case CC_OP_LTGT_64:
        !          2145:         r =  cc_calc_ltgt_64(env, src, dst);
        !          2146:         break;
        !          2147:     case CC_OP_LTUGTU_32:
        !          2148:         r =  cc_calc_ltugtu_32(env, src, dst);
        !          2149:         break;
        !          2150:     case CC_OP_LTUGTU_64:
        !          2151:         r =  cc_calc_ltugtu_64(env, src, dst);
        !          2152:         break;
        !          2153:     case CC_OP_TM_32:
        !          2154:         r =  cc_calc_tm_32(env, src, dst);
        !          2155:         break;
        !          2156:     case CC_OP_TM_64:
        !          2157:         r =  cc_calc_tm_64(env, src, dst);
        !          2158:         break;
        !          2159:     case CC_OP_NZ:
        !          2160:         r =  cc_calc_nz(env, dst);
        !          2161:         break;
        !          2162:     case CC_OP_ADD_64:
        !          2163:         r =  cc_calc_add_64(env, src, dst, vr);
        !          2164:         break;
        !          2165:     case CC_OP_ADDU_64:
        !          2166:         r =  cc_calc_addu_64(env, src, dst, vr);
        !          2167:         break;
        !          2168:     case CC_OP_SUB_64:
        !          2169:         r =  cc_calc_sub_64(env, src, dst, vr);
        !          2170:         break;
        !          2171:     case CC_OP_SUBU_64:
        !          2172:         r =  cc_calc_subu_64(env, src, dst, vr);
        !          2173:         break;
        !          2174:     case CC_OP_ABS_64:
        !          2175:         r =  cc_calc_abs_64(env, dst);
        !          2176:         break;
        !          2177:     case CC_OP_NABS_64:
        !          2178:         r =  cc_calc_nabs_64(env, dst);
        !          2179:         break;
        !          2180:     case CC_OP_COMP_64:
        !          2181:         r =  cc_calc_comp_64(env, dst);
        !          2182:         break;
        !          2183: 
        !          2184:     case CC_OP_ADD_32:
        !          2185:         r =  cc_calc_add_32(env, src, dst, vr);
        !          2186:         break;
        !          2187:     case CC_OP_ADDU_32:
        !          2188:         r =  cc_calc_addu_32(env, src, dst, vr);
        !          2189:         break;
        !          2190:     case CC_OP_SUB_32:
        !          2191:         r =  cc_calc_sub_32(env, src, dst, vr);
        !          2192:         break;
        !          2193:     case CC_OP_SUBU_32:
        !          2194:         r =  cc_calc_subu_32(env, src, dst, vr);
        !          2195:         break;
        !          2196:     case CC_OP_ABS_32:
        !          2197:         r =  cc_calc_abs_64(env, dst);
        !          2198:         break;
        !          2199:     case CC_OP_NABS_32:
        !          2200:         r =  cc_calc_nabs_64(env, dst);
        !          2201:         break;
        !          2202:     case CC_OP_COMP_32:
        !          2203:         r =  cc_calc_comp_32(env, dst);
        !          2204:         break;
        !          2205: 
        !          2206:     case CC_OP_ICM:
        !          2207:         r =  cc_calc_icm_32(env, src, dst);
        !          2208:         break;
        !          2209:     case CC_OP_SLAG:
        !          2210:         r =  cc_calc_slag(env, src, dst);
        !          2211:         break;
        !          2212: 
        !          2213:     case CC_OP_LTGT_F32:
        !          2214:         r = set_cc_f32(src, dst);
        !          2215:         break;
        !          2216:     case CC_OP_LTGT_F64:
        !          2217:         r = set_cc_f64(src, dst);
        !          2218:         break;
        !          2219:     case CC_OP_NZ_F32:
        !          2220:         r = set_cc_nz_f32(dst);
        !          2221:         break;
        !          2222:     case CC_OP_NZ_F64:
        !          2223:         r = set_cc_nz_f64(dst);
        !          2224:         break;
        !          2225: 
        !          2226:     default:
        !          2227:         cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
        !          2228:     }
        !          2229: 
        !          2230:     HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __FUNCTION__,
        !          2231:                cc_name(cc_op), src, dst, vr, r);
        !          2232:     return r;
        !          2233: }
        !          2234: 
        !          2235: uint32_t calc_cc(CPUState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
        !          2236:                  uint64_t vr)
        !          2237: {
        !          2238:     return do_calc_cc(env, cc_op, src, dst, vr);
        !          2239: }
        !          2240: 
        !          2241: uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst,
        !          2242:                          uint64_t vr)
        !          2243: {
        !          2244:     return do_calc_cc(env, cc_op, src, dst, vr);
        !          2245: }
        !          2246: 
        !          2247: uint64_t HELPER(cvd)(int32_t bin)
        !          2248: {
        !          2249:     /* positive 0 */
        !          2250:     uint64_t dec = 0x0c;
        !          2251:     int shift = 4;
        !          2252: 
        !          2253:     if (bin < 0) {
        !          2254:         bin = -bin;
        !          2255:         dec = 0x0d;
        !          2256:     }
        !          2257: 
        !          2258:     for (shift = 4; (shift < 64) && bin; shift += 4) {
        !          2259:         int current_number = bin % 10;
        !          2260: 
        !          2261:         dec |= (current_number) << shift;
        !          2262:         bin /= 10;
        !          2263:     }
        !          2264: 
        !          2265:     return dec;
        !          2266: }
        !          2267: 
        !          2268: void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
        !          2269: {
        !          2270:     int len_dest = len >> 4;
        !          2271:     int len_src = len & 0xf;
        !          2272:     uint8_t b;
        !          2273:     int second_nibble = 0;
        !          2274: 
        !          2275:     dest += len_dest;
        !          2276:     src += len_src;
        !          2277: 
        !          2278:     /* last byte is special, it only flips the nibbles */
        !          2279:     b = ldub(src);
        !          2280:     stb(dest, (b << 4) | (b >> 4));
        !          2281:     src--;
        !          2282:     len_src--;
        !          2283: 
        !          2284:     /* now pad every nibble with 0xf0 */
        !          2285: 
        !          2286:     while (len_dest > 0) {
        !          2287:         uint8_t cur_byte = 0;
        !          2288: 
        !          2289:         if (len_src > 0) {
        !          2290:             cur_byte = ldub(src);
        !          2291:         }
        !          2292: 
        !          2293:         len_dest--;
        !          2294:         dest--;
        !          2295: 
        !          2296:         /* only advance one nibble at a time */
        !          2297:         if (second_nibble) {
        !          2298:             cur_byte >>= 4;
        !          2299:             len_src--;
        !          2300:             src--;
        !          2301:         }
        !          2302:         second_nibble = !second_nibble;
        !          2303: 
        !          2304:         /* digit */
        !          2305:         cur_byte = (cur_byte & 0xf);
        !          2306:         /* zone bits */
        !          2307:         cur_byte |= 0xf0;
        !          2308: 
        !          2309:         stb(dest, cur_byte);
        !          2310:     }
        !          2311: }
        !          2312: 
        !          2313: void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
        !          2314: {
        !          2315:     int i;
        !          2316: 
        !          2317:     for (i = 0; i <= len; i++) {
        !          2318:         uint8_t byte = ldub(array + i);
        !          2319:         uint8_t new_byte = ldub(trans + byte);
        !          2320:         stb(array + i, new_byte);
        !          2321:     }
        !          2322: }
        !          2323: 
        !          2324: #ifndef CONFIG_USER_ONLY
        !          2325: 
        !          2326: void HELPER(load_psw)(uint64_t mask, uint64_t addr)
        !          2327: {
        !          2328:     load_psw(env, mask, addr);
        !          2329:     cpu_loop_exit(env);
        !          2330: }
        !          2331: 
        !          2332: static void program_interrupt(CPUState *env, uint32_t code, int ilc)
        !          2333: {
        !          2334:     qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
        !          2335: 
        !          2336:     if (kvm_enabled()) {
        !          2337: #ifdef CONFIG_KVM
        !          2338:         kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
        !          2339: #endif
        !          2340:     } else {
        !          2341:         env->int_pgm_code = code;
        !          2342:         env->int_pgm_ilc = ilc;
        !          2343:         env->exception_index = EXCP_PGM;
        !          2344:         cpu_loop_exit(env);
        !          2345:     }
        !          2346: }
        !          2347: 
        !          2348: static void ext_interrupt(CPUState *env, int type, uint32_t param,
        !          2349:                           uint64_t param64)
        !          2350: {
        !          2351:     cpu_inject_ext(env, type, param, param64);
        !          2352: }
        !          2353: 
        !          2354: int sclp_service_call(CPUState *env, uint32_t sccb, uint64_t code)
        !          2355: {
        !          2356:     int r = 0;
        !          2357:     int shift = 0;
        !          2358: 
        !          2359: #ifdef DEBUG_HELPER
        !          2360:     printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
        !          2361: #endif
        !          2362: 
        !          2363:     if (sccb & ~0x7ffffff8ul) {
        !          2364:         fprintf(stderr, "KVM: invalid sccb address 0x%x\n", sccb);
        !          2365:         r = -1;
        !          2366:         goto out;
        !          2367:     }
        !          2368: 
        !          2369:     switch(code) {
        !          2370:         case SCLP_CMDW_READ_SCP_INFO:
        !          2371:         case SCLP_CMDW_READ_SCP_INFO_FORCED:
        !          2372:             while ((ram_size >> (20 + shift)) > 65535) {
        !          2373:                 shift++;
        !          2374:             }
        !          2375:             stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
        !          2376:             stb_phys(sccb + SCP_INCREMENT, 1 << shift);
        !          2377:             stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
        !          2378: 
        !          2379:             if (kvm_enabled()) {
        !          2380: #ifdef CONFIG_KVM
        !          2381:                 kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE,
        !          2382:                                             sccb & ~3, 0, 1);
        !          2383: #endif
        !          2384:             } else {
        !          2385:                 env->psw.addr += 4;
        !          2386:                 ext_interrupt(env, EXT_SERVICE, sccb & ~3, 0);
        !          2387:             }
        !          2388:             break;
        !          2389:         default:
        !          2390: #ifdef DEBUG_HELPER
        !          2391:             printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
        !          2392: #endif
        !          2393:             r = -1;
        !          2394:             break;
        !          2395:     }
        !          2396: 
        !          2397: out:
        !          2398:     return r;
        !          2399: }
        !          2400: 
        !          2401: /* SCLP service call */
        !          2402: uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
        !          2403: {
        !          2404:     if (sclp_service_call(env, r1, r2)) {
        !          2405:         return 3;
        !          2406:     }
        !          2407: 
        !          2408:     return 0;
        !          2409: }
        !          2410: 
        !          2411: /* DIAG */
        !          2412: uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
        !          2413: {
        !          2414:     uint64_t r;
        !          2415: 
        !          2416:     switch (num) {
        !          2417:     case 0x500:
        !          2418:         /* KVM hypercall */
        !          2419:         r = s390_virtio_hypercall(env, mem, code);
        !          2420:         break;
        !          2421:     case 0x44:
        !          2422:         /* yield */
        !          2423:         r = 0;
        !          2424:         break;
        !          2425:     case 0x308:
        !          2426:         /* ipl */
        !          2427:         r = 0;
        !          2428:         break;
        !          2429:     default:
        !          2430:         r = -1;
        !          2431:         break;
        !          2432:     }
        !          2433: 
        !          2434:     if (r) {
        !          2435:         program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
        !          2436:     }
        !          2437: 
        !          2438:     return r;
        !          2439: }
        !          2440: 
        !          2441: /* Store CPU ID */
        !          2442: void HELPER(stidp)(uint64_t a1)
        !          2443: {
        !          2444:     stq(a1, env->cpu_num);
        !          2445: }
        !          2446: 
        !          2447: /* Set Prefix */
        !          2448: void HELPER(spx)(uint64_t a1)
        !          2449: {
        !          2450:     uint32_t prefix;
        !          2451: 
        !          2452:     prefix = ldl(a1);
        !          2453:     env->psa = prefix & 0xfffff000;
        !          2454:     qemu_log("prefix: %#x\n", prefix);
        !          2455:     tlb_flush_page(env, 0);
        !          2456:     tlb_flush_page(env, TARGET_PAGE_SIZE);
        !          2457: }
        !          2458: 
        !          2459: /* Set Clock */
        !          2460: uint32_t HELPER(sck)(uint64_t a1)
        !          2461: {
        !          2462:     /* XXX not implemented - is it necessary? */
        !          2463: 
        !          2464:     return 0;
        !          2465: }
        !          2466: 
        !          2467: static inline uint64_t clock_value(CPUState *env)
        !          2468: {
        !          2469:     uint64_t time;
        !          2470: 
        !          2471:     time = env->tod_offset +
        !          2472:            time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
        !          2473: 
        !          2474:     return time;
        !          2475: }
        !          2476: 
        !          2477: /* Store Clock */
        !          2478: uint32_t HELPER(stck)(uint64_t a1)
        !          2479: {
        !          2480:     stq(a1, clock_value(env));
        !          2481: 
        !          2482:     return 0;
        !          2483: }
        !          2484: 
        !          2485: /* Store Clock Extended */
        !          2486: uint32_t HELPER(stcke)(uint64_t a1)
        !          2487: {
        !          2488:     stb(a1, 0);
        !          2489:     /* basically the same value as stck */
        !          2490:     stq(a1 + 1, clock_value(env) | env->cpu_num);
        !          2491:     /* more fine grained than stck */
        !          2492:     stq(a1 + 9, 0);
        !          2493:     /* XXX programmable fields */
        !          2494:     stw(a1 + 17, 0);
        !          2495: 
        !          2496: 
        !          2497:     return 0;
        !          2498: }
        !          2499: 
        !          2500: /* Set Clock Comparator */
        !          2501: void HELPER(sckc)(uint64_t a1)
        !          2502: {
        !          2503:     uint64_t time = ldq(a1);
        !          2504: 
        !          2505:     if (time == -1ULL) {
        !          2506:         return;
        !          2507:     }
        !          2508: 
        !          2509:     /* difference between now and then */
        !          2510:     time -= clock_value(env);
        !          2511:     /* nanoseconds */
        !          2512:     time = (time * 125) >> 9;
        !          2513: 
        !          2514:     qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
        !          2515: }
        !          2516: 
        !          2517: /* Store Clock Comparator */
        !          2518: void HELPER(stckc)(uint64_t a1)
        !          2519: {
        !          2520:     /* XXX implement */
        !          2521:     stq(a1, 0);
        !          2522: }
        !          2523: 
        !          2524: /* Set CPU Timer */
        !          2525: void HELPER(spt)(uint64_t a1)
        !          2526: {
        !          2527:     uint64_t time = ldq(a1);
        !          2528: 
        !          2529:     if (time == -1ULL) {
        !          2530:         return;
        !          2531:     }
        !          2532: 
        !          2533:     /* nanoseconds */
        !          2534:     time = (time * 125) >> 9;
        !          2535: 
        !          2536:     qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
        !          2537: }
        !          2538: 
        !          2539: /* Store CPU Timer */
        !          2540: void HELPER(stpt)(uint64_t a1)
        !          2541: {
        !          2542:     /* XXX implement */
        !          2543:     stq(a1, 0);
        !          2544: }
        !          2545: 
        !          2546: /* Store System Information */
        !          2547: uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
        !          2548: {
        !          2549:     int cc = 0;
        !          2550:     int sel1, sel2;
        !          2551: 
        !          2552:     if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
        !          2553:         ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
        !          2554:         /* valid function code, invalid reserved bits */
        !          2555:         program_interrupt(env, PGM_SPECIFICATION, 2);
        !          2556:     }
        !          2557: 
        !          2558:     sel1 = r0 & STSI_R0_SEL1_MASK;
        !          2559:     sel2 = r1 & STSI_R1_SEL2_MASK;
        !          2560: 
        !          2561:     /* XXX: spec exception if sysib is not 4k-aligned */
        !          2562: 
        !          2563:     switch (r0 & STSI_LEVEL_MASK) {
        !          2564:     case STSI_LEVEL_1:
        !          2565:         if ((sel1 == 1) && (sel2 == 1)) {
        !          2566:             /* Basic Machine Configuration */
        !          2567:             struct sysib_111 sysib;
        !          2568: 
        !          2569:             memset(&sysib, 0, sizeof(sysib));
        !          2570:             ebcdic_put(sysib.manuf, "QEMU            ", 16);
        !          2571:             /* same as machine type number in STORE CPU ID */
        !          2572:             ebcdic_put(sysib.type, "QEMU", 4);
        !          2573:             /* same as model number in STORE CPU ID */
        !          2574:             ebcdic_put(sysib.model, "QEMU            ", 16);
        !          2575:             ebcdic_put(sysib.sequence, "QEMU            ", 16);
        !          2576:             ebcdic_put(sysib.plant, "QEMU", 4);
        !          2577:             cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
        !          2578:         } else if ((sel1 == 2) && (sel2 == 1)) {
        !          2579:             /* Basic Machine CPU */
        !          2580:             struct sysib_121 sysib;
        !          2581: 
        !          2582:             memset(&sysib, 0, sizeof(sysib));
        !          2583:             /* XXX make different for different CPUs? */
        !          2584:             ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
        !          2585:             ebcdic_put(sysib.plant, "QEMU", 4);
        !          2586:             stw_p(&sysib.cpu_addr, env->cpu_num);
        !          2587:             cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
        !          2588:         } else if ((sel1 == 2) && (sel2 == 2)) {
        !          2589:             /* Basic Machine CPUs */
        !          2590:             struct sysib_122 sysib;
        !          2591: 
        !          2592:             memset(&sysib, 0, sizeof(sysib));
        !          2593:             stl_p(&sysib.capability, 0x443afc29);
        !          2594:             /* XXX change when SMP comes */
        !          2595:             stw_p(&sysib.total_cpus, 1);
        !          2596:             stw_p(&sysib.active_cpus, 1);
        !          2597:             stw_p(&sysib.standby_cpus, 0);
        !          2598:             stw_p(&sysib.reserved_cpus, 0);
        !          2599:             cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
        !          2600:         } else {
        !          2601:             cc = 3;
        !          2602:         }
        !          2603:         break;
        !          2604:     case STSI_LEVEL_2:
        !          2605:     {
        !          2606:         if ((sel1 == 2) && (sel2 == 1)) {
        !          2607:             /* LPAR CPU */
        !          2608:             struct sysib_221 sysib;
        !          2609: 
        !          2610:             memset(&sysib, 0, sizeof(sysib));
        !          2611:             /* XXX make different for different CPUs? */
        !          2612:             ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
        !          2613:             ebcdic_put(sysib.plant, "QEMU", 4);
        !          2614:             stw_p(&sysib.cpu_addr, env->cpu_num);
        !          2615:             stw_p(&sysib.cpu_id, 0);
        !          2616:             cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
        !          2617:         } else if ((sel1 == 2) && (sel2 == 2)) {
        !          2618:             /* LPAR CPUs */
        !          2619:             struct sysib_222 sysib;
        !          2620: 
        !          2621:             memset(&sysib, 0, sizeof(sysib));
        !          2622:             stw_p(&sysib.lpar_num, 0);
        !          2623:             sysib.lcpuc = 0;
        !          2624:             /* XXX change when SMP comes */
        !          2625:             stw_p(&sysib.total_cpus, 1);
        !          2626:             stw_p(&sysib.conf_cpus, 1);
        !          2627:             stw_p(&sysib.standby_cpus, 0);
        !          2628:             stw_p(&sysib.reserved_cpus, 0);
        !          2629:             ebcdic_put(sysib.name, "QEMU    ", 8);
        !          2630:             stl_p(&sysib.caf, 1000);
        !          2631:             stw_p(&sysib.dedicated_cpus, 0);
        !          2632:             stw_p(&sysib.shared_cpus, 0);
        !          2633:             cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
        !          2634:         } else {
        !          2635:             cc = 3;
        !          2636:         }
        !          2637:         break;
        !          2638:     }
        !          2639:     case STSI_LEVEL_3:
        !          2640:     {
        !          2641:         if ((sel1 == 2) && (sel2 == 2)) {
        !          2642:             /* VM CPUs */
        !          2643:             struct sysib_322 sysib;
        !          2644: 
        !          2645:             memset(&sysib, 0, sizeof(sysib));
        !          2646:             sysib.count = 1;
        !          2647:             /* XXX change when SMP comes */
        !          2648:             stw_p(&sysib.vm[0].total_cpus, 1);
        !          2649:             stw_p(&sysib.vm[0].conf_cpus, 1);
        !          2650:             stw_p(&sysib.vm[0].standby_cpus, 0);
        !          2651:             stw_p(&sysib.vm[0].reserved_cpus, 0);
        !          2652:             ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
        !          2653:             stl_p(&sysib.vm[0].caf, 1000);
        !          2654:             ebcdic_put(sysib.vm[0].cpi, "KVM/Linux       ", 16);
        !          2655:             cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
        !          2656:         } else {
        !          2657:             cc = 3;
        !          2658:         }
        !          2659:         break;
        !          2660:     }
        !          2661:     case STSI_LEVEL_CURRENT:
        !          2662:         env->regs[0] = STSI_LEVEL_3;
        !          2663:         break;
        !          2664:     default:
        !          2665:         cc = 3;
        !          2666:         break;
        !          2667:     }
        !          2668: 
        !          2669:     return cc;
        !          2670: }
        !          2671: 
        !          2672: void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3)
        !          2673: {
        !          2674:     int i;
        !          2675:     uint64_t src = a2;
        !          2676: 
        !          2677:     for (i = r1;; i = (i + 1) % 16) {
        !          2678:         env->cregs[i] = ldq(src);
        !          2679:         HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
        !          2680:                    i, src, env->cregs[i]);
        !          2681:         src += sizeof(uint64_t);
        !          2682: 
        !          2683:         if (i == r3) {
        !          2684:             break;
        !          2685:         }
        !          2686:     }
        !          2687: 
        !          2688:     tlb_flush(env, 1);
        !          2689: }
        !          2690: 
        !          2691: void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3)
        !          2692: {
        !          2693:     int i;
        !          2694:     uint64_t src = a2;
        !          2695: 
        !          2696:     for (i = r1;; i = (i + 1) % 16) {
        !          2697:         env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src);
        !          2698:         src += sizeof(uint32_t);
        !          2699: 
        !          2700:         if (i == r3) {
        !          2701:             break;
        !          2702:         }
        !          2703:     }
        !          2704: 
        !          2705:     tlb_flush(env, 1);
        !          2706: }
        !          2707: 
        !          2708: void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3)
        !          2709: {
        !          2710:     int i;
        !          2711:     uint64_t dest = a2;
        !          2712: 
        !          2713:     for (i = r1;; i = (i + 1) % 16) {
        !          2714:         stq(dest, env->cregs[i]);
        !          2715:         dest += sizeof(uint64_t);
        !          2716: 
        !          2717:         if (i == r3) {
        !          2718:             break;
        !          2719:         }
        !          2720:     }
        !          2721: }
        !          2722: 
        !          2723: void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3)
        !          2724: {
        !          2725:     int i;
        !          2726:     uint64_t dest = a2;
        !          2727: 
        !          2728:     for (i = r1;; i = (i + 1) % 16) {
        !          2729:         stl(dest, env->cregs[i]);
        !          2730:         dest += sizeof(uint32_t);
        !          2731: 
        !          2732:         if (i == r3) {
        !          2733:             break;
        !          2734:         }
        !          2735:     }
        !          2736: }
        !          2737: 
        !          2738: uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
        !          2739: {
        !          2740:     /* XXX implement */
        !          2741: 
        !          2742:     return 0;
        !          2743: }
        !          2744: 
        !          2745: /* insert storage key extended */
        !          2746: uint64_t HELPER(iske)(uint64_t r2)
        !          2747: {
        !          2748:     uint64_t addr = get_address(0, 0, r2);
        !          2749: 
        !          2750:     if (addr > ram_size) {
        !          2751:         return 0;
        !          2752:     }
        !          2753: 
        !          2754:     /* XXX maybe use qemu's internal keys? */
        !          2755:     return env->storage_keys[addr / TARGET_PAGE_SIZE];
        !          2756: }
        !          2757: 
        !          2758: /* set storage key extended */
        !          2759: void HELPER(sske)(uint32_t r1, uint64_t r2)
        !          2760: {
        !          2761:     uint64_t addr = get_address(0, 0, r2);
        !          2762: 
        !          2763:     if (addr > ram_size) {
        !          2764:         return;
        !          2765:     }
        !          2766: 
        !          2767:     env->storage_keys[addr / TARGET_PAGE_SIZE] = r1;
        !          2768: }
        !          2769: 
        !          2770: /* reset reference bit extended */
        !          2771: uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
        !          2772: {
        !          2773:     if (r2 > ram_size) {
        !          2774:         return 0;
        !          2775:     }
        !          2776: 
        !          2777:     /* XXX implement */
        !          2778: #if 0
        !          2779:     env->storage_keys[r2 / TARGET_PAGE_SIZE] &= ~SK_REFERENCED;
        !          2780: #endif
        !          2781: 
        !          2782:     /*
        !          2783:      * cc
        !          2784:      *
        !          2785:      * 0  Reference bit zero; change bit zero
        !          2786:      * 1  Reference bit zero; change bit one
        !          2787:      * 2  Reference bit one; change bit zero
        !          2788:      * 3  Reference bit one; change bit one
        !          2789:      */
        !          2790:     return 0;
        !          2791: }
        !          2792: 
        !          2793: /* compare and swap and purge */
        !          2794: uint32_t HELPER(csp)(uint32_t r1, uint32_t r2)
        !          2795: {
        !          2796:     uint32_t cc;
        !          2797:     uint32_t o1 = env->regs[r1];
        !          2798:     uint64_t a2 = get_address_31fix(r2) & ~3ULL;
        !          2799:     uint32_t o2 = ldl(a2);
        !          2800: 
        !          2801:     if (o1 == o2) {
        !          2802:         stl(a2, env->regs[(r1 + 1) & 15]);
        !          2803:         if (env->regs[r2] & 0x3) {
        !          2804:             /* flush TLB / ALB */
        !          2805:             tlb_flush(env, 1);
        !          2806:         }
        !          2807:         cc = 0;
        !          2808:     } else {
        !          2809:         env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | o2;
        !          2810:         cc = 1;
        !          2811:     }
        !          2812: 
        !          2813:     return cc;
        !          2814: }
        !          2815: 
        !          2816: static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
        !          2817:                         uint64_t mode2)
        !          2818: {
        !          2819:     target_ulong src, dest;
        !          2820:     int flags, cc = 0, i;
        !          2821: 
        !          2822:     if (!l) {
        !          2823:         return 0;
        !          2824:     } else if (l > 256) {
        !          2825:         /* max 256 */
        !          2826:         l = 256;
        !          2827:         cc = 3;
        !          2828:     }
        !          2829: 
        !          2830:     if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) {
        !          2831:         cpu_loop_exit(env);
        !          2832:     }
        !          2833:     dest |= a1 & ~TARGET_PAGE_MASK;
        !          2834: 
        !          2835:     if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) {
        !          2836:         cpu_loop_exit(env);
        !          2837:     }
        !          2838:     src |= a2 & ~TARGET_PAGE_MASK;
        !          2839: 
        !          2840:     /* XXX replace w/ memcpy */
        !          2841:     for (i = 0; i < l; i++) {
        !          2842:         /* XXX be more clever */
        !          2843:         if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) ||
        !          2844:             (((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) {
        !          2845:             mvc_asc(l - i, a1 + i, mode1, a2 + i, mode2);
        !          2846:             break;
        !          2847:         }
        !          2848:         stb_phys(dest + i, ldub_phys(src + i));
        !          2849:     }
        !          2850: 
        !          2851:     return cc;
        !          2852: }
        !          2853: 
        !          2854: uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
        !          2855: {
        !          2856:     HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
        !          2857:                __FUNCTION__, l, a1, a2);
        !          2858: 
        !          2859:     return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
        !          2860: }
        !          2861: 
        !          2862: uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2)
        !          2863: {
        !          2864:     HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
        !          2865:                __FUNCTION__, l, a1, a2);
        !          2866: 
        !          2867:     return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
        !          2868: }
        !          2869: 
        !          2870: uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
        !          2871: {
        !          2872:     int cc = 0;
        !          2873: 
        !          2874:     HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
        !          2875:                __FUNCTION__, order_code, r1, cpu_addr);
        !          2876: 
        !          2877:     /* Remember: Use "R1 or R1+1, whichever is the odd-numbered register"
        !          2878:        as parameter (input). Status (output) is always R1. */
        !          2879: 
        !          2880:     switch (order_code) {
        !          2881:     case SIGP_SET_ARCH:
        !          2882:         /* switch arch */
        !          2883:         break;
        !          2884:     case SIGP_SENSE:
        !          2885:         /* enumerate CPU status */
        !          2886:         if (cpu_addr) {
        !          2887:             /* XXX implement when SMP comes */
        !          2888:             return 3;
        !          2889:         }
        !          2890:         env->regs[r1] &= 0xffffffff00000000ULL;
        !          2891:         cc = 1;
        !          2892:         break;
        !          2893:     default:
        !          2894:         /* unknown sigp */
        !          2895:         fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
        !          2896:         cc = 3;
        !          2897:     }
        !          2898: 
        !          2899:     return cc;
        !          2900: }
        !          2901: 
        !          2902: void HELPER(sacf)(uint64_t a1)
        !          2903: {
        !          2904:     HELPER_LOG("%s: %16" PRIx64 "\n", __FUNCTION__, a1);
        !          2905: 
        !          2906:     switch (a1 & 0xf00) {
        !          2907:     case 0x000:
        !          2908:         env->psw.mask &= ~PSW_MASK_ASC;
        !          2909:         env->psw.mask |= PSW_ASC_PRIMARY;
        !          2910:         break;
        !          2911:     case 0x100:
        !          2912:         env->psw.mask &= ~PSW_MASK_ASC;
        !          2913:         env->psw.mask |= PSW_ASC_SECONDARY;
        !          2914:         break;
        !          2915:     case 0x300:
        !          2916:         env->psw.mask &= ~PSW_MASK_ASC;
        !          2917:         env->psw.mask |= PSW_ASC_HOME;
        !          2918:         break;
        !          2919:     default:
        !          2920:         qemu_log("unknown sacf mode: %" PRIx64 "\n", a1);
        !          2921:         program_interrupt(env, PGM_SPECIFICATION, 2);
        !          2922:         break;
        !          2923:     }
        !          2924: }
        !          2925: 
        !          2926: /* invalidate pte */
        !          2927: void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
        !          2928: {
        !          2929:     uint64_t page = vaddr & TARGET_PAGE_MASK;
        !          2930:     uint64_t pte = 0;
        !          2931: 
        !          2932:     /* XXX broadcast to other CPUs */
        !          2933: 
        !          2934:     /* XXX Linux is nice enough to give us the exact pte address.
        !          2935:            According to spec we'd have to find it out ourselves */
        !          2936:     /* XXX Linux is fine with overwriting the pte, the spec requires
        !          2937:            us to only set the invalid bit */
        !          2938:     stq_phys(pte_addr, pte | _PAGE_INVALID);
        !          2939: 
        !          2940:     /* XXX we exploit the fact that Linux passes the exact virtual
        !          2941:            address here - it's not obliged to! */
        !          2942:     tlb_flush_page(env, page);
        !          2943: }
        !          2944: 
        !          2945: /* flush local tlb */
        !          2946: void HELPER(ptlb)(void)
        !          2947: {
        !          2948:     tlb_flush(env, 1);
        !          2949: }
        !          2950: 
        !          2951: /* store using real address */
        !          2952: void HELPER(stura)(uint64_t addr, uint32_t v1)
        !          2953: {
        !          2954:     stw_phys(get_address(0, 0, addr), v1);
        !          2955: }
        !          2956: 
        !          2957: /* load real address */
        !          2958: uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
        !          2959: {
        !          2960:     uint32_t cc = 0;
        !          2961:     int old_exc = env->exception_index;
        !          2962:     uint64_t asc = env->psw.mask & PSW_MASK_ASC;
        !          2963:     uint64_t ret;
        !          2964:     int flags;
        !          2965: 
        !          2966:     /* XXX incomplete - has more corner cases */
        !          2967:     if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
        !          2968:         program_interrupt(env, PGM_SPECIAL_OP, 2);
        !          2969:     }
        !          2970: 
        !          2971:     env->exception_index = old_exc;
        !          2972:     if (mmu_translate(env, addr, 0, asc, &ret, &flags)) {
        !          2973:         cc = 3;
        !          2974:     }
        !          2975:     if (env->exception_index == EXCP_PGM) {
        !          2976:         ret = env->int_pgm_code | 0x80000000;
        !          2977:     } else {
        !          2978:         ret |= addr & ~TARGET_PAGE_MASK;
        !          2979:     }
        !          2980:     env->exception_index = old_exc;
        !          2981: 
        !          2982:     if (!(env->psw.mask & PSW_MASK_64)) {
        !          2983:         env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (ret & 0xffffffffULL);
        !          2984:     } else {
        !          2985:         env->regs[r1] = ret;
        !          2986:     }
        !          2987: 
        !          2988:     return cc;
        !          2989: }
        !          2990: 
        !          2991: #endif

unix.superglobalmegacorp.com

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