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