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

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

unix.superglobalmegacorp.com

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