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

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

unix.superglobalmegacorp.com

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