qemu/target/s390x/mem_helper.c
<<
>>
Prefs
   1/*
   2 *  S/390 memory access 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 "qemu/osdep.h"
  22#include "cpu.h"
  23#include "internal.h"
  24#include "exec/helper-proto.h"
  25#include "exec/exec-all.h"
  26#include "exec/cpu_ldst.h"
  27#include "qemu/int128.h"
  28
  29#if !defined(CONFIG_USER_ONLY)
  30#include "hw/s390x/storage-keys.h"
  31#endif
  32
  33/*****************************************************************************/
  34/* Softmmu support */
  35#if !defined(CONFIG_USER_ONLY)
  36
  37/* try to fill the TLB and return an exception if error. If retaddr is
  38   NULL, it means that the function was called in C code (i.e. not
  39   from generated code or from helper.c) */
  40/* XXX: fix it to restore all registers */
  41void tlb_fill(CPUState *cs, target_ulong addr, int size,
  42              MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
  43{
  44    int ret = s390_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
  45    if (unlikely(ret != 0)) {
  46        cpu_loop_exit_restore(cs, retaddr);
  47    }
  48}
  49
  50#endif
  51
  52/* #define DEBUG_HELPER */
  53#ifdef DEBUG_HELPER
  54#define HELPER_LOG(x...) qemu_log(x)
  55#else
  56#define HELPER_LOG(x...)
  57#endif
  58
  59static inline bool psw_key_valid(CPUS390XState *env, uint8_t psw_key)
  60{
  61    uint16_t pkm = env->cregs[3] >> 16;
  62
  63    if (env->psw.mask & PSW_MASK_PSTATE) {
  64        /* PSW key has range 0..15, it is valid if the bit is 1 in the PKM */
  65        return pkm & (0x80 >> psw_key);
  66    }
  67    return true;
  68}
  69
  70/* Reduce the length so that addr + len doesn't cross a page boundary.  */
  71static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr)
  72{
  73#ifndef CONFIG_USER_ONLY
  74    if ((addr & ~TARGET_PAGE_MASK) + len - 1 >= TARGET_PAGE_SIZE) {
  75        return -(addr | TARGET_PAGE_MASK);
  76    }
  77#endif
  78    return len;
  79}
  80
  81/* Trigger a SPECIFICATION exception if an address or a length is not
  82   naturally aligned.  */
  83static inline void check_alignment(CPUS390XState *env, uint64_t v,
  84                                   int wordsize, uintptr_t ra)
  85{
  86    if (v % wordsize) {
  87        s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
  88    }
  89}
  90
  91/* Load a value from memory according to its size.  */
  92static inline uint64_t cpu_ldusize_data_ra(CPUS390XState *env, uint64_t addr,
  93                                           int wordsize, uintptr_t ra)
  94{
  95    switch (wordsize) {
  96    case 1:
  97        return cpu_ldub_data_ra(env, addr, ra);
  98    case 2:
  99        return cpu_lduw_data_ra(env, addr, ra);
 100    default:
 101        abort();
 102    }
 103}
 104
 105/* Store a to memory according to its size.  */
 106static inline void cpu_stsize_data_ra(CPUS390XState *env, uint64_t addr,
 107                                      uint64_t value, int wordsize,
 108                                      uintptr_t ra)
 109{
 110    switch (wordsize) {
 111    case 1:
 112        cpu_stb_data_ra(env, addr, value, ra);
 113        break;
 114    case 2:
 115        cpu_stw_data_ra(env, addr, value, ra);
 116        break;
 117    default:
 118        abort();
 119    }
 120}
 121
 122static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte,
 123                        uint32_t l, uintptr_t ra)
 124{
 125    int mmu_idx = cpu_mmu_index(env, false);
 126
 127    while (l > 0) {
 128        void *p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx);
 129        if (p) {
 130            /* Access to the whole page in write mode granted.  */
 131            uint32_t l_adj = adj_len_to_page(l, dest);
 132            memset(p, byte, l_adj);
 133            dest += l_adj;
 134            l -= l_adj;
 135        } else {
 136            /* We failed to get access to the whole page. The next write
 137               access will likely fill the QEMU TLB for the next iteration.  */
 138            cpu_stb_data_ra(env, dest, byte, ra);
 139            dest++;
 140            l--;
 141        }
 142    }
 143}
 144
 145#ifndef CONFIG_USER_ONLY
 146static void fast_memmove_idx(CPUS390XState *env, uint64_t dest, uint64_t src,
 147                             uint32_t len, int dest_idx, int src_idx,
 148                             uintptr_t ra)
 149{
 150    TCGMemOpIdx oi_dest = make_memop_idx(MO_UB, dest_idx);
 151    TCGMemOpIdx oi_src = make_memop_idx(MO_UB, src_idx);
 152    uint32_t len_adj;
 153    void *src_p;
 154    void *dest_p;
 155    uint8_t x;
 156
 157    while (len > 0) {
 158        src = wrap_address(env, src);
 159        dest = wrap_address(env, dest);
 160        src_p = tlb_vaddr_to_host(env, src, MMU_DATA_LOAD, src_idx);
 161        dest_p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, dest_idx);
 162
 163        if (src_p && dest_p) {
 164            /* Access to both whole pages granted.  */
 165            len_adj = adj_len_to_page(adj_len_to_page(len, src), dest);
 166            memmove(dest_p, src_p, len_adj);
 167        } else {
 168            /* We failed to get access to one or both whole pages. The next
 169               read or write access will likely fill the QEMU TLB for the
 170               next iteration.  */
 171            len_adj = 1;
 172            x = helper_ret_ldub_mmu(env, src, oi_src, ra);
 173            helper_ret_stb_mmu(env, dest, x, oi_dest, ra);
 174        }
 175        src += len_adj;
 176        dest += len_adj;
 177        len -= len_adj;
 178    }
 179}
 180
 181static int mmu_idx_from_as(uint8_t as)
 182{
 183    switch (as) {
 184    case AS_PRIMARY:
 185        return MMU_PRIMARY_IDX;
 186    case AS_SECONDARY:
 187        return MMU_SECONDARY_IDX;
 188    case AS_HOME:
 189        return MMU_HOME_IDX;
 190    default:
 191        /* FIXME AS_ACCREG */
 192        g_assert_not_reached();
 193    }
 194}
 195
 196static void fast_memmove_as(CPUS390XState *env, uint64_t dest, uint64_t src,
 197                            uint32_t len, uint8_t dest_as, uint8_t src_as,
 198                            uintptr_t ra)
 199{
 200    int src_idx = mmu_idx_from_as(src_as);
 201    int dest_idx = mmu_idx_from_as(dest_as);
 202
 203    fast_memmove_idx(env, dest, src, len, dest_idx, src_idx, ra);
 204}
 205#endif
 206
 207static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src,
 208                         uint32_t l, uintptr_t ra)
 209{
 210    int mmu_idx = cpu_mmu_index(env, false);
 211
 212    while (l > 0) {
 213        void *src_p = tlb_vaddr_to_host(env, src, MMU_DATA_LOAD, mmu_idx);
 214        void *dest_p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx);
 215        if (src_p && dest_p) {
 216            /* Access to both whole pages granted.  */
 217            uint32_t l_adj = adj_len_to_page(l, src);
 218            l_adj = adj_len_to_page(l_adj, dest);
 219            memmove(dest_p, src_p, l_adj);
 220            src += l_adj;
 221            dest += l_adj;
 222            l -= l_adj;
 223        } else {
 224            /* We failed to get access to one or both whole pages. The next
 225               read or write access will likely fill the QEMU TLB for the
 226               next iteration.  */
 227            cpu_stb_data_ra(env, dest, cpu_ldub_data_ra(env, src, ra), ra);
 228            src++;
 229            dest++;
 230            l--;
 231        }
 232    }
 233}
 234
 235/* and on array */
 236static uint32_t do_helper_nc(CPUS390XState *env, uint32_t l, uint64_t dest,
 237                             uint64_t src, uintptr_t ra)
 238{
 239    uint32_t i;
 240    uint8_t c = 0;
 241
 242    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
 243               __func__, l, dest, src);
 244
 245    for (i = 0; i <= l; i++) {
 246        uint8_t x = cpu_ldub_data_ra(env, src + i, ra);
 247        x &= cpu_ldub_data_ra(env, dest + i, ra);
 248        c |= x;
 249        cpu_stb_data_ra(env, dest + i, x, ra);
 250    }
 251    return c != 0;
 252}
 253
 254uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest,
 255                    uint64_t src)
 256{
 257    return do_helper_nc(env, l, dest, src, GETPC());
 258}
 259
 260/* xor on array */
 261static uint32_t do_helper_xc(CPUS390XState *env, uint32_t l, uint64_t dest,
 262                             uint64_t src, uintptr_t ra)
 263{
 264    uint32_t i;
 265    uint8_t c = 0;
 266
 267    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
 268               __func__, l, dest, src);
 269
 270    /* xor with itself is the same as memset(0) */
 271    if (src == dest) {
 272        fast_memset(env, dest, 0, l + 1, ra);
 273        return 0;
 274    }
 275
 276    for (i = 0; i <= l; i++) {
 277        uint8_t x = cpu_ldub_data_ra(env, src + i, ra);
 278        x ^= cpu_ldub_data_ra(env, dest + i, ra);
 279        c |= x;
 280        cpu_stb_data_ra(env, dest + i, x, ra);
 281    }
 282    return c != 0;
 283}
 284
 285uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest,
 286                    uint64_t src)
 287{
 288    return do_helper_xc(env, l, dest, src, GETPC());
 289}
 290
 291/* or on array */
 292static uint32_t do_helper_oc(CPUS390XState *env, uint32_t l, uint64_t dest,
 293                             uint64_t src, uintptr_t ra)
 294{
 295    uint32_t i;
 296    uint8_t c = 0;
 297
 298    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
 299               __func__, l, dest, src);
 300
 301    for (i = 0; i <= l; i++) {
 302        uint8_t x = cpu_ldub_data_ra(env, src + i, ra);
 303        x |= cpu_ldub_data_ra(env, dest + i, ra);
 304        c |= x;
 305        cpu_stb_data_ra(env, dest + i, x, ra);
 306    }
 307    return c != 0;
 308}
 309
 310uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest,
 311                    uint64_t src)
 312{
 313    return do_helper_oc(env, l, dest, src, GETPC());
 314}
 315
 316/* memmove */
 317static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest,
 318                              uint64_t src, uintptr_t ra)
 319{
 320    uint32_t i;
 321
 322    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
 323               __func__, l, dest, src);
 324
 325    /* mvc and memmove do not behave the same when areas overlap! */
 326    /* mvc with source pointing to the byte after the destination is the
 327       same as memset with the first source byte */
 328    if (dest == src + 1) {
 329        fast_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l + 1, ra);
 330    } else if (dest < src || src + l < dest) {
 331        fast_memmove(env, dest, src, l + 1, ra);
 332    } else {
 333        /* slow version with byte accesses which always work */
 334        for (i = 0; i <= l; i++) {
 335            uint8_t x = cpu_ldub_data_ra(env, src + i, ra);
 336            cpu_stb_data_ra(env, dest + i, x, ra);
 337        }
 338    }
 339
 340    return env->cc_op;
 341}
 342
 343void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 344{
 345    do_helper_mvc(env, l, dest, src, GETPC());
 346}
 347
 348/* move inverse  */
 349void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 350{
 351    uintptr_t ra = GETPC();
 352    int i;
 353
 354    for (i = 0; i <= l; i++) {
 355        uint8_t v = cpu_ldub_data_ra(env, src - i, ra);
 356        cpu_stb_data_ra(env, dest + i, v, ra);
 357    }
 358}
 359
 360/* move numerics  */
 361void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 362{
 363    uintptr_t ra = GETPC();
 364    int i;
 365
 366    for (i = 0; i <= l; i++) {
 367        uint8_t v = cpu_ldub_data_ra(env, dest + i, ra) & 0xf0;
 368        v |= cpu_ldub_data_ra(env, src + i, ra) & 0x0f;
 369        cpu_stb_data_ra(env, dest + i, v, ra);
 370    }
 371}
 372
 373/* move with offset  */
 374void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 375{
 376    uintptr_t ra = GETPC();
 377    int len_dest = l >> 4;
 378    int len_src = l & 0xf;
 379    uint8_t byte_dest, byte_src;
 380    int i;
 381
 382    src += len_src;
 383    dest += len_dest;
 384
 385    /* Handle rightmost byte */
 386    byte_src = cpu_ldub_data_ra(env, src, ra);
 387    byte_dest = cpu_ldub_data_ra(env, dest, ra);
 388    byte_dest = (byte_dest & 0x0f) | (byte_src << 4);
 389    cpu_stb_data_ra(env, dest, byte_dest, ra);
 390
 391    /* Process remaining bytes from right to left */
 392    for (i = 1; i <= len_dest; i++) {
 393        byte_dest = byte_src >> 4;
 394        if (len_src - i >= 0) {
 395            byte_src = cpu_ldub_data_ra(env, src - i, ra);
 396        } else {
 397            byte_src = 0;
 398        }
 399        byte_dest |= byte_src << 4;
 400        cpu_stb_data_ra(env, dest - i, byte_dest, ra);
 401    }
 402}
 403
 404/* move zones  */
 405void HELPER(mvz)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 406{
 407    uintptr_t ra = GETPC();
 408    int i;
 409
 410    for (i = 0; i <= l; i++) {
 411        uint8_t b = cpu_ldub_data_ra(env, dest + i, ra) & 0x0f;
 412        b |= cpu_ldub_data_ra(env, src + i, ra) & 0xf0;
 413        cpu_stb_data_ra(env, dest + i, b, ra);
 414    }
 415}
 416
 417/* compare unsigned byte arrays */
 418static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1,
 419                              uint64_t s2, uintptr_t ra)
 420{
 421    uint32_t i;
 422    uint32_t cc = 0;
 423
 424    HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
 425               __func__, l, s1, s2);
 426
 427    for (i = 0; i <= l; i++) {
 428        uint8_t x = cpu_ldub_data_ra(env, s1 + i, ra);
 429        uint8_t y = cpu_ldub_data_ra(env, s2 + i, ra);
 430        HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
 431        if (x < y) {
 432            cc = 1;
 433            break;
 434        } else if (x > y) {
 435            cc = 2;
 436            break;
 437        }
 438    }
 439
 440    HELPER_LOG("\n");
 441    return cc;
 442}
 443
 444uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2)
 445{
 446    return do_helper_clc(env, l, s1, s2, GETPC());
 447}
 448
 449/* compare logical under mask */
 450uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
 451                     uint64_t addr)
 452{
 453    uintptr_t ra = GETPC();
 454    uint32_t cc = 0;
 455
 456    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1,
 457               mask, addr);
 458
 459    while (mask) {
 460        if (mask & 8) {
 461            uint8_t d = cpu_ldub_data_ra(env, addr, ra);
 462            uint8_t r = extract32(r1, 24, 8);
 463            HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
 464                       addr);
 465            if (r < d) {
 466                cc = 1;
 467                break;
 468            } else if (r > d) {
 469                cc = 2;
 470                break;
 471            }
 472            addr++;
 473        }
 474        mask = (mask << 1) & 0xf;
 475        r1 <<= 8;
 476    }
 477
 478    HELPER_LOG("\n");
 479    return cc;
 480}
 481
 482static inline uint64_t get_address(CPUS390XState *env, int reg)
 483{
 484    return wrap_address(env, env->regs[reg]);
 485}
 486
 487static inline void set_address(CPUS390XState *env, int reg, uint64_t address)
 488{
 489    if (env->psw.mask & PSW_MASK_64) {
 490        /* 64-Bit mode */
 491        env->regs[reg] = address;
 492    } else {
 493        if (!(env->psw.mask & PSW_MASK_32)) {
 494            /* 24-Bit mode. According to the PoO it is implementation
 495            dependent if bits 32-39 remain unchanged or are set to
 496            zeros.  Choose the former so that the function can also be
 497            used for TRT.  */
 498            env->regs[reg] = deposit64(env->regs[reg], 0, 24, address);
 499        } else {
 500            /* 31-Bit mode. According to the PoO it is implementation
 501            dependent if bit 32 remains unchanged or is set to zero.
 502            Choose the latter so that the function can also be used for
 503            TRT.  */
 504            address &= 0x7fffffff;
 505            env->regs[reg] = deposit64(env->regs[reg], 0, 32, address);
 506        }
 507    }
 508}
 509
 510static inline uint64_t wrap_length(CPUS390XState *env, uint64_t length)
 511{
 512    if (!(env->psw.mask & PSW_MASK_64)) {
 513        /* 24-Bit and 31-Bit mode */
 514        length &= 0x7fffffff;
 515    }
 516    return length;
 517}
 518
 519static inline uint64_t get_length(CPUS390XState *env, int reg)
 520{
 521    return wrap_length(env, env->regs[reg]);
 522}
 523
 524static inline void set_length(CPUS390XState *env, int reg, uint64_t length)
 525{
 526    if (env->psw.mask & PSW_MASK_64) {
 527        /* 64-Bit mode */
 528        env->regs[reg] = length;
 529    } else {
 530        /* 24-Bit and 31-Bit mode */
 531        env->regs[reg] = deposit64(env->regs[reg], 0, 32, length);
 532    }
 533}
 534
 535/* search string (c is byte to search, r2 is string, r1 end of string) */
 536void HELPER(srst)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 537{
 538    uintptr_t ra = GETPC();
 539    uint64_t end, str;
 540    uint32_t len;
 541    uint8_t v, c = env->regs[0];
 542
 543    /* Bits 32-55 must contain all 0.  */
 544    if (env->regs[0] & 0xffffff00u) {
 545        s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
 546    }
 547
 548    str = get_address(env, r2);
 549    end = get_address(env, r1);
 550
 551    /* Lest we fail to service interrupts in a timely manner, limit the
 552       amount of work we're willing to do.  For now, let's cap at 8k.  */
 553    for (len = 0; len < 0x2000; ++len) {
 554        if (str + len == end) {
 555            /* Character not found.  R1 & R2 are unmodified.  */
 556            env->cc_op = 2;
 557            return;
 558        }
 559        v = cpu_ldub_data_ra(env, str + len, ra);
 560        if (v == c) {
 561            /* Character found.  Set R1 to the location; R2 is unmodified.  */
 562            env->cc_op = 1;
 563            set_address(env, r1, str + len);
 564            return;
 565        }
 566    }
 567
 568    /* CPU-determined bytes processed.  Advance R2 to next byte to process.  */
 569    env->cc_op = 3;
 570    set_address(env, r2, str + len);
 571}
 572
 573void HELPER(srstu)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 574{
 575    uintptr_t ra = GETPC();
 576    uint32_t len;
 577    uint16_t v, c = env->regs[0];
 578    uint64_t end, str, adj_end;
 579
 580    /* Bits 32-47 of R0 must be zero.  */
 581    if (env->regs[0] & 0xffff0000u) {
 582        s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
 583    }
 584
 585    str = get_address(env, r2);
 586    end = get_address(env, r1);
 587
 588    /* If the LSB of the two addresses differ, use one extra byte.  */
 589    adj_end = end + ((str ^ end) & 1);
 590
 591    /* Lest we fail to service interrupts in a timely manner, limit the
 592       amount of work we're willing to do.  For now, let's cap at 8k.  */
 593    for (len = 0; len < 0x2000; len += 2) {
 594        if (str + len == adj_end) {
 595            /* End of input found.  */
 596            env->cc_op = 2;
 597            return;
 598        }
 599        v = cpu_lduw_data_ra(env, str + len, ra);
 600        if (v == c) {
 601            /* Character found.  Set R1 to the location; R2 is unmodified.  */
 602            env->cc_op = 1;
 603            set_address(env, r1, str + len);
 604            return;
 605        }
 606    }
 607
 608    /* CPU-determined bytes processed.  Advance R2 to next byte to process.  */
 609    env->cc_op = 3;
 610    set_address(env, r2, str + len);
 611}
 612
 613/* unsigned string compare (c is string terminator) */
 614uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2)
 615{
 616    uintptr_t ra = GETPC();
 617    uint32_t len;
 618
 619    c = c & 0xff;
 620    s1 = wrap_address(env, s1);
 621    s2 = wrap_address(env, s2);
 622
 623    /* Lest we fail to service interrupts in a timely manner, limit the
 624       amount of work we're willing to do.  For now, let's cap at 8k.  */
 625    for (len = 0; len < 0x2000; ++len) {
 626        uint8_t v1 = cpu_ldub_data_ra(env, s1 + len, ra);
 627        uint8_t v2 = cpu_ldub_data_ra(env, s2 + len, ra);
 628        if (v1 == v2) {
 629            if (v1 == c) {
 630                /* Equal.  CC=0, and don't advance the registers.  */
 631                env->cc_op = 0;
 632                env->retxl = s2;
 633                return s1;
 634            }
 635        } else {
 636            /* Unequal.  CC={1,2}, and advance the registers.  Note that
 637               the terminator need not be zero, but the string that contains
 638               the terminator is by definition "low".  */
 639            env->cc_op = (v1 == c ? 1 : v2 == c ? 2 : v1 < v2 ? 1 : 2);
 640            env->retxl = s2 + len;
 641            return s1 + len;
 642        }
 643    }
 644
 645    /* CPU-determined bytes equal; advance the registers.  */
 646    env->cc_op = 3;
 647    env->retxl = s2 + len;
 648    return s1 + len;
 649}
 650
 651/* move page */
 652uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2)
 653{
 654    /* ??? missing r0 handling, which includes access keys, but more
 655       importantly optional suppression of the exception!  */
 656    fast_memmove(env, r1, r2, TARGET_PAGE_SIZE, GETPC());
 657    return 0; /* data moved */
 658}
 659
 660/* string copy (c is string terminator) */
 661uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s)
 662{
 663    uintptr_t ra = GETPC();
 664    uint32_t len;
 665
 666    c = c & 0xff;
 667    d = wrap_address(env, d);
 668    s = wrap_address(env, s);
 669
 670    /* Lest we fail to service interrupts in a timely manner, limit the
 671       amount of work we're willing to do.  For now, let's cap at 8k.  */
 672    for (len = 0; len < 0x2000; ++len) {
 673        uint8_t v = cpu_ldub_data_ra(env, s + len, ra);
 674        cpu_stb_data_ra(env, d + len, v, ra);
 675        if (v == c) {
 676            /* Complete.  Set CC=1 and advance R1.  */
 677            env->cc_op = 1;
 678            env->retxl = s;
 679            return d + len;
 680        }
 681    }
 682
 683    /* Incomplete.  Set CC=3 and signal to advance R1 and R2.  */
 684    env->cc_op = 3;
 685    env->retxl = s + len;
 686    return d + len;
 687}
 688
 689/* load access registers r1 to r3 from memory at a2 */
 690void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 691{
 692    uintptr_t ra = GETPC();
 693    int i;
 694
 695    if (a2 & 0x3) {
 696        /* we either came here by lam or lamy, which have different lengths */
 697        s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, ra);
 698    }
 699
 700    for (i = r1;; i = (i + 1) % 16) {
 701        env->aregs[i] = cpu_ldl_data_ra(env, a2, ra);
 702        a2 += 4;
 703
 704        if (i == r3) {
 705            break;
 706        }
 707    }
 708}
 709
 710/* store access registers r1 to r3 in memory at a2 */
 711void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 712{
 713    uintptr_t ra = GETPC();
 714    int i;
 715
 716    if (a2 & 0x3) {
 717        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
 718    }
 719
 720    for (i = r1;; i = (i + 1) % 16) {
 721        cpu_stl_data_ra(env, a2, env->aregs[i], ra);
 722        a2 += 4;
 723
 724        if (i == r3) {
 725            break;
 726        }
 727    }
 728}
 729
 730/* move long helper */
 731static inline uint32_t do_mvcl(CPUS390XState *env,
 732                               uint64_t *dest, uint64_t *destlen,
 733                               uint64_t *src, uint64_t *srclen,
 734                               uint16_t pad, int wordsize, uintptr_t ra)
 735{
 736    uint64_t len = MIN(*srclen, *destlen);
 737    uint32_t cc;
 738
 739    if (*destlen == *srclen) {
 740        cc = 0;
 741    } else if (*destlen < *srclen) {
 742        cc = 1;
 743    } else {
 744        cc = 2;
 745    }
 746
 747    /* Copy the src array */
 748    fast_memmove(env, *dest, *src, len, ra);
 749    *src += len;
 750    *srclen -= len;
 751    *dest += len;
 752    *destlen -= len;
 753
 754    /* Pad the remaining area */
 755    if (wordsize == 1) {
 756        fast_memset(env, *dest, pad, *destlen, ra);
 757        *dest += *destlen;
 758        *destlen = 0;
 759    } else {
 760        /* If remaining length is odd, pad with odd byte first.  */
 761        if (*destlen & 1) {
 762            cpu_stb_data_ra(env, *dest, pad & 0xff, ra);
 763            *dest += 1;
 764            *destlen -= 1;
 765        }
 766        /* The remaining length is even, pad using words.  */
 767        for (; *destlen; *dest += 2, *destlen -= 2) {
 768            cpu_stw_data_ra(env, *dest, pad, ra);
 769        }
 770    }
 771
 772    return cc;
 773}
 774
 775/* move long */
 776uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 777{
 778    uintptr_t ra = GETPC();
 779    uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
 780    uint64_t dest = get_address(env, r1);
 781    uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
 782    uint64_t src = get_address(env, r2);
 783    uint8_t pad = env->regs[r2 + 1] >> 24;
 784    uint32_t cc;
 785
 786    cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, 1, ra);
 787
 788    env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen);
 789    env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen);
 790    set_address(env, r1, dest);
 791    set_address(env, r2, src);
 792
 793    return cc;
 794}
 795
 796/* move long extended */
 797uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
 798                       uint32_t r3)
 799{
 800    uintptr_t ra = GETPC();
 801    uint64_t destlen = get_length(env, r1 + 1);
 802    uint64_t dest = get_address(env, r1);
 803    uint64_t srclen = get_length(env, r3 + 1);
 804    uint64_t src = get_address(env, r3);
 805    uint8_t pad = a2;
 806    uint32_t cc;
 807
 808    cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, 1, ra);
 809
 810    set_length(env, r1 + 1, destlen);
 811    set_length(env, r3 + 1, srclen);
 812    set_address(env, r1, dest);
 813    set_address(env, r3, src);
 814
 815    return cc;
 816}
 817
 818/* move long unicode */
 819uint32_t HELPER(mvclu)(CPUS390XState *env, uint32_t r1, uint64_t a2,
 820                       uint32_t r3)
 821{
 822    uintptr_t ra = GETPC();
 823    uint64_t destlen = get_length(env, r1 + 1);
 824    uint64_t dest = get_address(env, r1);
 825    uint64_t srclen = get_length(env, r3 + 1);
 826    uint64_t src = get_address(env, r3);
 827    uint16_t pad = a2;
 828    uint32_t cc;
 829
 830    cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, 2, ra);
 831
 832    set_length(env, r1 + 1, destlen);
 833    set_length(env, r3 + 1, srclen);
 834    set_address(env, r1, dest);
 835    set_address(env, r3, src);
 836
 837    return cc;
 838}
 839
 840/* compare logical long helper */
 841static inline uint32_t do_clcl(CPUS390XState *env,
 842                               uint64_t *src1, uint64_t *src1len,
 843                               uint64_t *src3, uint64_t *src3len,
 844                               uint16_t pad, uint64_t limit,
 845                               int wordsize, uintptr_t ra)
 846{
 847    uint64_t len = MAX(*src1len, *src3len);
 848    uint32_t cc = 0;
 849
 850    check_alignment(env, *src1len | *src3len, wordsize, ra);
 851
 852    if (!len) {
 853        return cc;
 854    }
 855
 856    /* Lest we fail to service interrupts in a timely manner, limit the
 857       amount of work we're willing to do.  */
 858    if (len > limit) {
 859        len = limit;
 860        cc = 3;
 861    }
 862
 863    for (; len; len -= wordsize) {
 864        uint16_t v1 = pad;
 865        uint16_t v3 = pad;
 866
 867        if (*src1len) {
 868            v1 = cpu_ldusize_data_ra(env, *src1, wordsize, ra);
 869        }
 870        if (*src3len) {
 871            v3 = cpu_ldusize_data_ra(env, *src3, wordsize, ra);
 872        }
 873
 874        if (v1 != v3) {
 875            cc = (v1 < v3) ? 1 : 2;
 876            break;
 877        }
 878
 879        if (*src1len) {
 880            *src1 += wordsize;
 881            *src1len -= wordsize;
 882        }
 883        if (*src3len) {
 884            *src3 += wordsize;
 885            *src3len -= wordsize;
 886        }
 887    }
 888
 889    return cc;
 890}
 891
 892
 893/* compare logical long */
 894uint32_t HELPER(clcl)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 895{
 896    uintptr_t ra = GETPC();
 897    uint64_t src1len = extract64(env->regs[r1 + 1], 0, 24);
 898    uint64_t src1 = get_address(env, r1);
 899    uint64_t src3len = extract64(env->regs[r2 + 1], 0, 24);
 900    uint64_t src3 = get_address(env, r2);
 901    uint8_t pad = env->regs[r2 + 1] >> 24;
 902    uint32_t cc;
 903
 904    cc = do_clcl(env, &src1, &src1len, &src3, &src3len, pad, -1, 1, ra);
 905
 906    env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, src1len);
 907    env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, src3len);
 908    set_address(env, r1, src1);
 909    set_address(env, r2, src3);
 910
 911    return cc;
 912}
 913
 914/* compare logical long extended memcompare insn with padding */
 915uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
 916                       uint32_t r3)
 917{
 918    uintptr_t ra = GETPC();
 919    uint64_t src1len = get_length(env, r1 + 1);
 920    uint64_t src1 = get_address(env, r1);
 921    uint64_t src3len = get_length(env, r3 + 1);
 922    uint64_t src3 = get_address(env, r3);
 923    uint8_t pad = a2;
 924    uint32_t cc;
 925
 926    cc = do_clcl(env, &src1, &src1len, &src3, &src3len, pad, 0x2000, 1, ra);
 927
 928    set_length(env, r1 + 1, src1len);
 929    set_length(env, r3 + 1, src3len);
 930    set_address(env, r1, src1);
 931    set_address(env, r3, src3);
 932
 933    return cc;
 934}
 935
 936/* compare logical long unicode memcompare insn with padding */
 937uint32_t HELPER(clclu)(CPUS390XState *env, uint32_t r1, uint64_t a2,
 938                       uint32_t r3)
 939{
 940    uintptr_t ra = GETPC();
 941    uint64_t src1len = get_length(env, r1 + 1);
 942    uint64_t src1 = get_address(env, r1);
 943    uint64_t src3len = get_length(env, r3 + 1);
 944    uint64_t src3 = get_address(env, r3);
 945    uint16_t pad = a2;
 946    uint32_t cc = 0;
 947
 948    cc = do_clcl(env, &src1, &src1len, &src3, &src3len, pad, 0x1000, 2, ra);
 949
 950    set_length(env, r1 + 1, src1len);
 951    set_length(env, r3 + 1, src3len);
 952    set_address(env, r1, src1);
 953    set_address(env, r3, src3);
 954
 955    return cc;
 956}
 957
 958/* checksum */
 959uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1,
 960                      uint64_t src, uint64_t src_len)
 961{
 962    uintptr_t ra = GETPC();
 963    uint64_t max_len, len;
 964    uint64_t cksm = (uint32_t)r1;
 965
 966    /* Lest we fail to service interrupts in a timely manner, limit the
 967       amount of work we're willing to do.  For now, let's cap at 8k.  */
 968    max_len = (src_len > 0x2000 ? 0x2000 : src_len);
 969
 970    /* Process full words as available.  */
 971    for (len = 0; len + 4 <= max_len; len += 4, src += 4) {
 972        cksm += (uint32_t)cpu_ldl_data_ra(env, src, ra);
 973    }
 974
 975    switch (max_len - len) {
 976    case 1:
 977        cksm += cpu_ldub_data_ra(env, src, ra) << 24;
 978        len += 1;
 979        break;
 980    case 2:
 981        cksm += cpu_lduw_data_ra(env, src, ra) << 16;
 982        len += 2;
 983        break;
 984    case 3:
 985        cksm += cpu_lduw_data_ra(env, src, ra) << 16;
 986        cksm += cpu_ldub_data_ra(env, src + 2, ra) << 8;
 987        len += 3;
 988        break;
 989    }
 990
 991    /* Fold the carry from the checksum.  Note that we can see carry-out
 992       during folding more than once (but probably not more than twice).  */
 993    while (cksm > 0xffffffffull) {
 994        cksm = (uint32_t)cksm + (cksm >> 32);
 995    }
 996
 997    /* Indicate whether or not we've processed everything.  */
 998    env->cc_op = (len == src_len ? 0 : 3);
 999
1000    /* Return both cksm and processed length.  */
1001    env->retxl = cksm;
1002    return len;
1003}
1004
1005void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src)
1006{
1007    uintptr_t ra = GETPC();
1008    int len_dest = len >> 4;
1009    int len_src = len & 0xf;
1010    uint8_t b;
1011
1012    dest += len_dest;
1013    src += len_src;
1014
1015    /* last byte is special, it only flips the nibbles */
1016    b = cpu_ldub_data_ra(env, src, ra);
1017    cpu_stb_data_ra(env, dest, (b << 4) | (b >> 4), ra);
1018    src--;
1019    len_src--;
1020
1021    /* now pack every value */
1022    while (len_dest >= 0) {
1023        b = 0;
1024
1025        if (len_src > 0) {
1026            b = cpu_ldub_data_ra(env, src, ra) & 0x0f;
1027            src--;
1028            len_src--;
1029        }
1030        if (len_src > 0) {
1031            b |= cpu_ldub_data_ra(env, src, ra) << 4;
1032            src--;
1033            len_src--;
1034        }
1035
1036        len_dest--;
1037        dest--;
1038        cpu_stb_data_ra(env, dest, b, ra);
1039    }
1040}
1041
1042static inline void do_pkau(CPUS390XState *env, uint64_t dest, uint64_t src,
1043                           uint32_t srclen, int ssize, uintptr_t ra)
1044{
1045    int i;
1046    /* The destination operand is always 16 bytes long.  */
1047    const int destlen = 16;
1048
1049    /* The operands are processed from right to left.  */
1050    src += srclen - 1;
1051    dest += destlen - 1;
1052
1053    for (i = 0; i < destlen; i++) {
1054        uint8_t b = 0;
1055
1056        /* Start with a positive sign */
1057        if (i == 0) {
1058            b = 0xc;
1059        } else if (srclen > ssize) {
1060            b = cpu_ldub_data_ra(env, src, ra) & 0x0f;
1061            src -= ssize;
1062            srclen -= ssize;
1063        }
1064
1065        if (srclen > ssize) {
1066            b |= cpu_ldub_data_ra(env, src, ra) << 4;
1067            src -= ssize;
1068            srclen -= ssize;
1069        }
1070
1071        cpu_stb_data_ra(env, dest, b, ra);
1072        dest--;
1073    }
1074}
1075
1076
1077void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src,
1078                 uint32_t srclen)
1079{
1080    do_pkau(env, dest, src, srclen, 1, GETPC());
1081}
1082
1083void HELPER(pku)(CPUS390XState *env, uint64_t dest, uint64_t src,
1084                 uint32_t srclen)
1085{
1086    do_pkau(env, dest, src, srclen, 2, GETPC());
1087}
1088
1089void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest,
1090                  uint64_t src)
1091{
1092    uintptr_t ra = GETPC();
1093    int len_dest = len >> 4;
1094    int len_src = len & 0xf;
1095    uint8_t b;
1096    int second_nibble = 0;
1097
1098    dest += len_dest;
1099    src += len_src;
1100
1101    /* last byte is special, it only flips the nibbles */
1102    b = cpu_ldub_data_ra(env, src, ra);
1103    cpu_stb_data_ra(env, dest, (b << 4) | (b >> 4), ra);
1104    src--;
1105    len_src--;
1106
1107    /* now pad every nibble with 0xf0 */
1108
1109    while (len_dest > 0) {
1110        uint8_t cur_byte = 0;
1111
1112        if (len_src > 0) {
1113            cur_byte = cpu_ldub_data_ra(env, src, ra);
1114        }
1115
1116        len_dest--;
1117        dest--;
1118
1119        /* only advance one nibble at a time */
1120        if (second_nibble) {
1121            cur_byte >>= 4;
1122            len_src--;
1123            src--;
1124        }
1125        second_nibble = !second_nibble;
1126
1127        /* digit */
1128        cur_byte = (cur_byte & 0xf);
1129        /* zone bits */
1130        cur_byte |= 0xf0;
1131
1132        cpu_stb_data_ra(env, dest, cur_byte, ra);
1133    }
1134}
1135
1136static inline uint32_t do_unpkau(CPUS390XState *env, uint64_t dest,
1137                                 uint32_t destlen, int dsize, uint64_t src,
1138                                 uintptr_t ra)
1139{
1140    int i;
1141    uint32_t cc;
1142    uint8_t b;
1143    /* The source operand is always 16 bytes long.  */
1144    const int srclen = 16;
1145
1146    /* The operands are processed from right to left.  */
1147    src += srclen - 1;
1148    dest += destlen - dsize;
1149
1150    /* Check for the sign.  */
1151    b = cpu_ldub_data_ra(env, src, ra);
1152    src--;
1153    switch (b & 0xf) {
1154    case 0xa:
1155    case 0xc:
1156    case 0xe ... 0xf:
1157        cc = 0;  /* plus */
1158        break;
1159    case 0xb:
1160    case 0xd:
1161        cc = 1;  /* minus */
1162        break;
1163    default:
1164    case 0x0 ... 0x9:
1165        cc = 3;  /* invalid */
1166        break;
1167    }
1168
1169    /* Now pad every nibble with 0x30, advancing one nibble at a time. */
1170    for (i = 0; i < destlen; i += dsize) {
1171        if (i == (31 * dsize)) {
1172            /* If length is 32/64 bytes, the leftmost byte is 0. */
1173            b = 0;
1174        } else if (i % (2 * dsize)) {
1175            b = cpu_ldub_data_ra(env, src, ra);
1176            src--;
1177        } else {
1178            b >>= 4;
1179        }
1180        cpu_stsize_data_ra(env, dest, 0x30 + (b & 0xf), dsize, ra);
1181        dest -= dsize;
1182    }
1183
1184    return cc;
1185}
1186
1187uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen,
1188                       uint64_t src)
1189{
1190    return do_unpkau(env, dest, destlen, 1, src, GETPC());
1191}
1192
1193uint32_t HELPER(unpku)(CPUS390XState *env, uint64_t dest, uint32_t destlen,
1194                       uint64_t src)
1195{
1196    return do_unpkau(env, dest, destlen, 2, src, GETPC());
1197}
1198
1199uint32_t HELPER(tp)(CPUS390XState *env, uint64_t dest, uint32_t destlen)
1200{
1201    uintptr_t ra = GETPC();
1202    uint32_t cc = 0;
1203    int i;
1204
1205    for (i = 0; i < destlen; i++) {
1206        uint8_t b = cpu_ldub_data_ra(env, dest + i, ra);
1207        /* digit */
1208        cc |= (b & 0xf0) > 0x90 ? 2 : 0;
1209
1210        if (i == (destlen - 1)) {
1211            /* sign */
1212            cc |= (b & 0xf) < 0xa ? 1 : 0;
1213        } else {
1214            /* digit */
1215            cc |= (b & 0xf) > 0x9 ? 2 : 0;
1216        }
1217    }
1218
1219    return cc;
1220}
1221
1222static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array,
1223                             uint64_t trans, uintptr_t ra)
1224{
1225    uint32_t i;
1226
1227    for (i = 0; i <= len; i++) {
1228        uint8_t byte = cpu_ldub_data_ra(env, array + i, ra);
1229        uint8_t new_byte = cpu_ldub_data_ra(env, trans + byte, ra);
1230        cpu_stb_data_ra(env, array + i, new_byte, ra);
1231    }
1232
1233    return env->cc_op;
1234}
1235
1236void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array,
1237                uint64_t trans)
1238{
1239    do_helper_tr(env, len, array, trans, GETPC());
1240}
1241
1242uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array,
1243                     uint64_t len, uint64_t trans)
1244{
1245    uintptr_t ra = GETPC();
1246    uint8_t end = env->regs[0] & 0xff;
1247    uint64_t l = len;
1248    uint64_t i;
1249    uint32_t cc = 0;
1250
1251    if (!(env->psw.mask & PSW_MASK_64)) {
1252        array &= 0x7fffffff;
1253        l = (uint32_t)l;
1254    }
1255
1256    /* Lest we fail to service interrupts in a timely manner, limit the
1257       amount of work we're willing to do.  For now, let's cap at 8k.  */
1258    if (l > 0x2000) {
1259        l = 0x2000;
1260        cc = 3;
1261    }
1262
1263    for (i = 0; i < l; i++) {
1264        uint8_t byte, new_byte;
1265
1266        byte = cpu_ldub_data_ra(env, array + i, ra);
1267
1268        if (byte == end) {
1269            cc = 1;
1270            break;
1271        }
1272
1273        new_byte = cpu_ldub_data_ra(env, trans + byte, ra);
1274        cpu_stb_data_ra(env, array + i, new_byte, ra);
1275    }
1276
1277    env->cc_op = cc;
1278    env->retxl = len - i;
1279    return array + i;
1280}
1281
1282static inline uint32_t do_helper_trt(CPUS390XState *env, int len,
1283                                     uint64_t array, uint64_t trans,
1284                                     int inc, uintptr_t ra)
1285{
1286    int i;
1287
1288    for (i = 0; i <= len; i++) {
1289        uint8_t byte = cpu_ldub_data_ra(env, array + i * inc, ra);
1290        uint8_t sbyte = cpu_ldub_data_ra(env, trans + byte, ra);
1291
1292        if (sbyte != 0) {
1293            set_address(env, 1, array + i * inc);
1294            env->regs[2] = deposit64(env->regs[2], 0, 8, sbyte);
1295            return (i == len) ? 2 : 1;
1296        }
1297    }
1298
1299    return 0;
1300}
1301
1302uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array,
1303                     uint64_t trans)
1304{
1305    return do_helper_trt(env, len, array, trans, 1, GETPC());
1306}
1307
1308uint32_t HELPER(trtr)(CPUS390XState *env, uint32_t len, uint64_t array,
1309                      uint64_t trans)
1310{
1311    return do_helper_trt(env, len, array, trans, -1, GETPC());
1312}
1313
1314/* Translate one/two to one/two */
1315uint32_t HELPER(trXX)(CPUS390XState *env, uint32_t r1, uint32_t r2,
1316                      uint32_t tst, uint32_t sizes)
1317{
1318    uintptr_t ra = GETPC();
1319    int dsize = (sizes & 1) ? 1 : 2;
1320    int ssize = (sizes & 2) ? 1 : 2;
1321    uint64_t tbl = get_address(env, 1);
1322    uint64_t dst = get_address(env, r1);
1323    uint64_t len = get_length(env, r1 + 1);
1324    uint64_t src = get_address(env, r2);
1325    uint32_t cc = 3;
1326    int i;
1327
1328    /* The lower address bits of TBL are ignored.  For TROO, TROT, it's
1329       the low 3 bits (double-word aligned).  For TRTO, TRTT, it's either
1330       the low 12 bits (4K, without ETF2-ENH) or 3 bits (with ETF2-ENH).  */
1331    if (ssize == 2 && !s390_has_feat(S390_FEAT_ETF2_ENH)) {
1332        tbl &= -4096;
1333    } else {
1334        tbl &= -8;
1335    }
1336
1337    check_alignment(env, len, ssize, ra);
1338
1339    /* Lest we fail to service interrupts in a timely manner, */
1340    /* limit the amount of work we're willing to do.   */
1341    for (i = 0; i < 0x2000; i++) {
1342        uint16_t sval = cpu_ldusize_data_ra(env, src, ssize, ra);
1343        uint64_t tble = tbl + (sval * dsize);
1344        uint16_t dval = cpu_ldusize_data_ra(env, tble, dsize, ra);
1345        if (dval == tst) {
1346            cc = 1;
1347            break;
1348        }
1349        cpu_stsize_data_ra(env, dst, dval, dsize, ra);
1350
1351        len -= ssize;
1352        src += ssize;
1353        dst += dsize;
1354
1355        if (len == 0) {
1356            cc = 0;
1357            break;
1358        }
1359    }
1360
1361    set_address(env, r1, dst);
1362    set_length(env, r1 + 1, len);
1363    set_address(env, r2, src);
1364
1365    return cc;
1366}
1367
1368static void do_cdsg(CPUS390XState *env, uint64_t addr,
1369                    uint32_t r1, uint32_t r3, bool parallel)
1370{
1371    uintptr_t ra = GETPC();
1372    Int128 cmpv = int128_make128(env->regs[r1 + 1], env->regs[r1]);
1373    Int128 newv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
1374    Int128 oldv;
1375    bool fail;
1376
1377    if (parallel) {
1378#ifndef CONFIG_ATOMIC128
1379        cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
1380#else
1381        int mem_idx = cpu_mmu_index(env, false);
1382        TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
1383        oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
1384        fail = !int128_eq(oldv, cmpv);
1385#endif
1386    } else {
1387        uint64_t oldh, oldl;
1388
1389        check_alignment(env, addr, 16, ra);
1390
1391        oldh = cpu_ldq_data_ra(env, addr + 0, ra);
1392        oldl = cpu_ldq_data_ra(env, addr + 8, ra);
1393
1394        oldv = int128_make128(oldl, oldh);
1395        fail = !int128_eq(oldv, cmpv);
1396        if (fail) {
1397            newv = oldv;
1398        }
1399
1400        cpu_stq_data_ra(env, addr + 0, int128_gethi(newv), ra);
1401        cpu_stq_data_ra(env, addr + 8, int128_getlo(newv), ra);
1402    }
1403
1404    env->cc_op = fail;
1405    env->regs[r1] = int128_gethi(oldv);
1406    env->regs[r1 + 1] = int128_getlo(oldv);
1407}
1408
1409void HELPER(cdsg)(CPUS390XState *env, uint64_t addr,
1410                  uint32_t r1, uint32_t r3)
1411{
1412    do_cdsg(env, addr, r1, r3, false);
1413}
1414
1415void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
1416                           uint32_t r1, uint32_t r3)
1417{
1418    do_cdsg(env, addr, r1, r3, true);
1419}
1420
1421static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
1422                        uint64_t a2, bool parallel)
1423{
1424#if !defined(CONFIG_USER_ONLY) || defined(CONFIG_ATOMIC128)
1425    uint32_t mem_idx = cpu_mmu_index(env, false);
1426#endif
1427    uintptr_t ra = GETPC();
1428    uint32_t fc = extract32(env->regs[0], 0, 8);
1429    uint32_t sc = extract32(env->regs[0], 8, 8);
1430    uint64_t pl = get_address(env, 1) & -16;
1431    uint64_t svh, svl;
1432    uint32_t cc;
1433
1434    /* Sanity check the function code and storage characteristic.  */
1435    if (fc > 1 || sc > 3) {
1436        if (!s390_has_feat(S390_FEAT_COMPARE_AND_SWAP_AND_STORE_2)) {
1437            goto spec_exception;
1438        }
1439        if (fc > 2 || sc > 4 || (fc == 2 && (r3 & 1))) {
1440            goto spec_exception;
1441        }
1442    }
1443
1444    /* Sanity check the alignments.  */
1445    if (extract32(a1, 0, 4 << fc) || extract32(a2, 0, 1 << sc)) {
1446        goto spec_exception;
1447    }
1448
1449    /* Sanity check writability of the store address.  */
1450#ifndef CONFIG_USER_ONLY
1451    probe_write(env, a2, 0, mem_idx, ra);
1452#endif
1453
1454    /* Note that the compare-and-swap is atomic, and the store is atomic, but
1455       the complete operation is not.  Therefore we do not need to assert serial
1456       context in order to implement this.  That said, restart early if we can't
1457       support either operation that is supposed to be atomic.  */
1458    if (parallel) {
1459        int mask = 0;
1460#if !defined(CONFIG_ATOMIC64)
1461        mask = -8;
1462#elif !defined(CONFIG_ATOMIC128)
1463        mask = -16;
1464#endif
1465        if (((4 << fc) | (1 << sc)) & mask) {
1466            cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
1467        }
1468    }
1469
1470    /* All loads happen before all stores.  For simplicity, load the entire
1471       store value area from the parameter list.  */
1472    svh = cpu_ldq_data_ra(env, pl + 16, ra);
1473    svl = cpu_ldq_data_ra(env, pl + 24, ra);
1474
1475    switch (fc) {
1476    case 0:
1477        {
1478            uint32_t nv = cpu_ldl_data_ra(env, pl, ra);
1479            uint32_t cv = env->regs[r3];
1480            uint32_t ov;
1481
1482            if (parallel) {
1483#ifdef CONFIG_USER_ONLY
1484                uint32_t *haddr = g2h(a1);
1485                ov = atomic_cmpxchg__nocheck(haddr, cv, nv);
1486#else
1487                TCGMemOpIdx oi = make_memop_idx(MO_TEUL | MO_ALIGN, mem_idx);
1488                ov = helper_atomic_cmpxchgl_be_mmu(env, a1, cv, nv, oi, ra);
1489#endif
1490            } else {
1491                ov = cpu_ldl_data_ra(env, a1, ra);
1492                cpu_stl_data_ra(env, a1, (ov == cv ? nv : ov), ra);
1493            }
1494            cc = (ov != cv);
1495            env->regs[r3] = deposit64(env->regs[r3], 32, 32, ov);
1496        }
1497        break;
1498
1499    case 1:
1500        {
1501            uint64_t nv = cpu_ldq_data_ra(env, pl, ra);
1502            uint64_t cv = env->regs[r3];
1503            uint64_t ov;
1504
1505            if (parallel) {
1506#ifdef CONFIG_ATOMIC64
1507# ifdef CONFIG_USER_ONLY
1508                uint64_t *haddr = g2h(a1);
1509                ov = atomic_cmpxchg__nocheck(haddr, cv, nv);
1510# else
1511                TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN, mem_idx);
1512                ov = helper_atomic_cmpxchgq_be_mmu(env, a1, cv, nv, oi, ra);
1513# endif
1514#else
1515                /* Note that we asserted !parallel above.  */
1516                g_assert_not_reached();
1517#endif
1518            } else {
1519                ov = cpu_ldq_data_ra(env, a1, ra);
1520                cpu_stq_data_ra(env, a1, (ov == cv ? nv : ov), ra);
1521            }
1522            cc = (ov != cv);
1523            env->regs[r3] = ov;
1524        }
1525        break;
1526
1527    case 2:
1528        {
1529            uint64_t nvh = cpu_ldq_data_ra(env, pl, ra);
1530            uint64_t nvl = cpu_ldq_data_ra(env, pl + 8, ra);
1531            Int128 nv = int128_make128(nvl, nvh);
1532            Int128 cv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
1533            Int128 ov;
1534
1535            if (parallel) {
1536#ifdef CONFIG_ATOMIC128
1537                TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
1538                ov = helper_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi, ra);
1539                cc = !int128_eq(ov, cv);
1540#else
1541                /* Note that we asserted !parallel above.  */
1542                g_assert_not_reached();
1543#endif
1544            } else {
1545                uint64_t oh = cpu_ldq_data_ra(env, a1 + 0, ra);
1546                uint64_t ol = cpu_ldq_data_ra(env, a1 + 8, ra);
1547
1548                ov = int128_make128(ol, oh);
1549                cc = !int128_eq(ov, cv);
1550                if (cc) {
1551                    nv = ov;
1552                }
1553
1554                cpu_stq_data_ra(env, a1 + 0, int128_gethi(nv), ra);
1555                cpu_stq_data_ra(env, a1 + 8, int128_getlo(nv), ra);
1556            }
1557
1558            env->regs[r3 + 0] = int128_gethi(ov);
1559            env->regs[r3 + 1] = int128_getlo(ov);
1560        }
1561        break;
1562
1563    default:
1564        g_assert_not_reached();
1565    }
1566
1567    /* Store only if the comparison succeeded.  Note that above we use a pair
1568       of 64-bit big-endian loads, so for sc < 3 we must extract the value
1569       from the most-significant bits of svh.  */
1570    if (cc == 0) {
1571        switch (sc) {
1572        case 0:
1573            cpu_stb_data_ra(env, a2, svh >> 56, ra);
1574            break;
1575        case 1:
1576            cpu_stw_data_ra(env, a2, svh >> 48, ra);
1577            break;
1578        case 2:
1579            cpu_stl_data_ra(env, a2, svh >> 32, ra);
1580            break;
1581        case 3:
1582            cpu_stq_data_ra(env, a2, svh, ra);
1583            break;
1584        case 4:
1585            if (parallel) {
1586#ifdef CONFIG_ATOMIC128
1587                TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
1588                Int128 sv = int128_make128(svl, svh);
1589                helper_atomic_sto_be_mmu(env, a2, sv, oi, ra);
1590#else
1591                /* Note that we asserted !parallel above.  */
1592                g_assert_not_reached();
1593#endif
1594            } else {
1595                cpu_stq_data_ra(env, a2 + 0, svh, ra);
1596                cpu_stq_data_ra(env, a2 + 8, svl, ra);
1597            }
1598            break;
1599        default:
1600            g_assert_not_reached();
1601        }
1602    }
1603
1604    return cc;
1605
1606 spec_exception:
1607    s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
1608    g_assert_not_reached();
1609}
1610
1611uint32_t HELPER(csst)(CPUS390XState *env, uint32_t r3, uint64_t a1, uint64_t a2)
1612{
1613    return do_csst(env, r3, a1, a2, false);
1614}
1615
1616uint32_t HELPER(csst_parallel)(CPUS390XState *env, uint32_t r3, uint64_t a1,
1617                               uint64_t a2)
1618{
1619    return do_csst(env, r3, a1, a2, true);
1620}
1621
1622#if !defined(CONFIG_USER_ONLY)
1623void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
1624{
1625    uintptr_t ra = GETPC();
1626    S390CPU *cpu = s390_env_get_cpu(env);
1627    bool PERchanged = false;
1628    uint64_t src = a2;
1629    uint32_t i;
1630
1631    if (src & 0x7) {
1632        s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
1633    }
1634
1635    for (i = r1;; i = (i + 1) % 16) {
1636        uint64_t val = cpu_ldq_data_ra(env, src, ra);
1637        if (env->cregs[i] != val && i >= 9 && i <= 11) {
1638            PERchanged = true;
1639        }
1640        env->cregs[i] = val;
1641        HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
1642                   i, src, val);
1643        src += sizeof(uint64_t);
1644
1645        if (i == r3) {
1646            break;
1647        }
1648    }
1649
1650    if (PERchanged && env->psw.mask & PSW_MASK_PER) {
1651        s390_cpu_recompute_watchpoints(CPU(cpu));
1652    }
1653
1654    tlb_flush(CPU(cpu));
1655}
1656
1657void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
1658{
1659    uintptr_t ra = GETPC();
1660    S390CPU *cpu = s390_env_get_cpu(env);
1661    bool PERchanged = false;
1662    uint64_t src = a2;
1663    uint32_t i;
1664
1665    if (src & 0x3) {
1666        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
1667    }
1668
1669    for (i = r1;; i = (i + 1) % 16) {
1670        uint32_t val = cpu_ldl_data_ra(env, src, ra);
1671        if ((uint32_t)env->cregs[i] != val && i >= 9 && i <= 11) {
1672            PERchanged = true;
1673        }
1674        env->cregs[i] = deposit64(env->cregs[i], 0, 32, val);
1675        HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%x\n", i, src, val);
1676        src += sizeof(uint32_t);
1677
1678        if (i == r3) {
1679            break;
1680        }
1681    }
1682
1683    if (PERchanged && env->psw.mask & PSW_MASK_PER) {
1684        s390_cpu_recompute_watchpoints(CPU(cpu));
1685    }
1686
1687    tlb_flush(CPU(cpu));
1688}
1689
1690void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
1691{
1692    uintptr_t ra = GETPC();
1693    uint64_t dest = a2;
1694    uint32_t i;
1695
1696    if (dest & 0x7) {
1697        s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
1698    }
1699
1700    for (i = r1;; i = (i + 1) % 16) {
1701        cpu_stq_data_ra(env, dest, env->cregs[i], ra);
1702        dest += sizeof(uint64_t);
1703
1704        if (i == r3) {
1705            break;
1706        }
1707    }
1708}
1709
1710void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
1711{
1712    uintptr_t ra = GETPC();
1713    uint64_t dest = a2;
1714    uint32_t i;
1715
1716    if (dest & 0x3) {
1717        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
1718    }
1719
1720    for (i = r1;; i = (i + 1) % 16) {
1721        cpu_stl_data_ra(env, dest, env->cregs[i], ra);
1722        dest += sizeof(uint32_t);
1723
1724        if (i == r3) {
1725            break;
1726        }
1727    }
1728}
1729
1730uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr)
1731{
1732    uintptr_t ra = GETPC();
1733    int i;
1734
1735    real_addr = wrap_address(env, real_addr) & TARGET_PAGE_MASK;
1736
1737    for (i = 0; i < TARGET_PAGE_SIZE; i += 8) {
1738        cpu_stq_real_ra(env, real_addr + i, 0, ra);
1739    }
1740
1741    return 0;
1742}
1743
1744uint32_t HELPER(tprot)(CPUS390XState *env, uint64_t a1, uint64_t a2)
1745{
1746    S390CPU *cpu = s390_env_get_cpu(env);
1747    CPUState *cs = CPU(cpu);
1748
1749    /*
1750     * TODO: we currently don't handle all access protection types
1751     * (including access-list and key-controlled) as well as AR mode.
1752     */
1753    if (!s390_cpu_virt_mem_check_write(cpu, a1, 0, 1)) {
1754        /* Fetching permitted; storing permitted */
1755        return 0;
1756    }
1757
1758    if (env->int_pgm_code == PGM_PROTECTION) {
1759        /* retry if reading is possible */
1760        cs->exception_index = 0;
1761        if (!s390_cpu_virt_mem_check_read(cpu, a1, 0, 1)) {
1762            /* Fetching permitted; storing not permitted */
1763            return 1;
1764        }
1765    }
1766
1767    switch (env->int_pgm_code) {
1768    case PGM_PROTECTION:
1769        /* Fetching not permitted; storing not permitted */
1770        cs->exception_index = 0;
1771        return 2;
1772    case PGM_ADDRESSING:
1773    case PGM_TRANS_SPEC:
1774        /* exceptions forwarded to the guest */
1775        s390_cpu_virt_mem_handle_exc(cpu, GETPC());
1776        return 0;
1777    }
1778
1779    /* Translation not available */
1780    cs->exception_index = 0;
1781    return 3;
1782}
1783
1784/* insert storage key extended */
1785uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
1786{
1787    static S390SKeysState *ss;
1788    static S390SKeysClass *skeyclass;
1789    uint64_t addr = wrap_address(env, r2);
1790    uint8_t key;
1791
1792    if (addr > ram_size) {
1793        return 0;
1794    }
1795
1796    if (unlikely(!ss)) {
1797        ss = s390_get_skeys_device();
1798        skeyclass = S390_SKEYS_GET_CLASS(ss);
1799    }
1800
1801    if (skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key)) {
1802        return 0;
1803    }
1804    return key;
1805}
1806
1807/* set storage key extended */
1808void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
1809{
1810    static S390SKeysState *ss;
1811    static S390SKeysClass *skeyclass;
1812    uint64_t addr = wrap_address(env, r2);
1813    uint8_t key;
1814
1815    if (addr > ram_size) {
1816        return;
1817    }
1818
1819    if (unlikely(!ss)) {
1820        ss = s390_get_skeys_device();
1821        skeyclass = S390_SKEYS_GET_CLASS(ss);
1822    }
1823
1824    key = (uint8_t) r1;
1825    skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
1826}
1827
1828/* reset reference bit extended */
1829uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
1830{
1831    static S390SKeysState *ss;
1832    static S390SKeysClass *skeyclass;
1833    uint8_t re, key;
1834
1835    if (r2 > ram_size) {
1836        return 0;
1837    }
1838
1839    if (unlikely(!ss)) {
1840        ss = s390_get_skeys_device();
1841        skeyclass = S390_SKEYS_GET_CLASS(ss);
1842    }
1843
1844    if (skeyclass->get_skeys(ss, r2 / TARGET_PAGE_SIZE, 1, &key)) {
1845        return 0;
1846    }
1847
1848    re = key & (SK_R | SK_C);
1849    key &= ~SK_R;
1850
1851    if (skeyclass->set_skeys(ss, r2 / TARGET_PAGE_SIZE, 1, &key)) {
1852        return 0;
1853    }
1854
1855    /*
1856     * cc
1857     *
1858     * 0  Reference bit zero; change bit zero
1859     * 1  Reference bit zero; change bit one
1860     * 2  Reference bit one; change bit zero
1861     * 3  Reference bit one; change bit one
1862     */
1863
1864    return re >> 1;
1865}
1866
1867uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
1868{
1869    uintptr_t ra = GETPC();
1870    int cc = 0, i;
1871
1872    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
1873               __func__, l, a1, a2);
1874
1875    if (l > 256) {
1876        /* max 256 */
1877        l = 256;
1878        cc = 3;
1879    }
1880
1881    /* XXX replace w/ memcpy */
1882    for (i = 0; i < l; i++) {
1883        uint8_t x = cpu_ldub_primary_ra(env, a2 + i, ra);
1884        cpu_stb_secondary_ra(env, a1 + i, x, ra);
1885    }
1886
1887    return cc;
1888}
1889
1890uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
1891{
1892    uintptr_t ra = GETPC();
1893    int cc = 0, i;
1894
1895    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
1896               __func__, l, a1, a2);
1897
1898    if (l > 256) {
1899        /* max 256 */
1900        l = 256;
1901        cc = 3;
1902    }
1903
1904    /* XXX replace w/ memcpy */
1905    for (i = 0; i < l; i++) {
1906        uint8_t x = cpu_ldub_secondary_ra(env, a2 + i, ra);
1907        cpu_stb_primary_ra(env, a1 + i, x, ra);
1908    }
1909
1910    return cc;
1911}
1912
1913void HELPER(idte)(CPUS390XState *env, uint64_t r1, uint64_t r2, uint32_t m4)
1914{
1915    CPUState *cs = CPU(s390_env_get_cpu(env));
1916    const uintptr_t ra = GETPC();
1917    uint64_t table, entry, raddr;
1918    uint16_t entries, i, index = 0;
1919
1920    if (r2 & 0xff000) {
1921        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
1922    }
1923
1924    if (!(r2 & 0x800)) {
1925        /* invalidation-and-clearing operation */
1926        table = r1 & ASCE_ORIGIN;
1927        entries = (r2 & 0x7ff) + 1;
1928
1929        switch (r1 & ASCE_TYPE_MASK) {
1930        case ASCE_TYPE_REGION1:
1931            index = (r2 >> 53) & 0x7ff;
1932            break;
1933        case ASCE_TYPE_REGION2:
1934            index = (r2 >> 42) & 0x7ff;
1935            break;
1936        case ASCE_TYPE_REGION3:
1937            index = (r2 >> 31) & 0x7ff;
1938            break;
1939        case ASCE_TYPE_SEGMENT:
1940            index = (r2 >> 20) & 0x7ff;
1941            break;
1942        }
1943        for (i = 0; i < entries; i++) {
1944            /* addresses are not wrapped in 24/31bit mode but table index is */
1945            raddr = table + ((index + i) & 0x7ff) * sizeof(entry);
1946            entry = cpu_ldq_real_ra(env, raddr, ra);
1947            if (!(entry & REGION_ENTRY_INV)) {
1948                /* we are allowed to not store if already invalid */
1949                entry |= REGION_ENTRY_INV;
1950                cpu_stq_real_ra(env, raddr, entry, ra);
1951            }
1952        }
1953    }
1954
1955    /* We simply flush the complete tlb, therefore we can ignore r3. */
1956    if (m4 & 1) {
1957        tlb_flush(cs);
1958    } else {
1959        tlb_flush_all_cpus_synced(cs);
1960    }
1961}
1962
1963/* invalidate pte */
1964void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr,
1965                  uint32_t m4)
1966{
1967    CPUState *cs = CPU(s390_env_get_cpu(env));
1968    const uintptr_t ra = GETPC();
1969    uint64_t page = vaddr & TARGET_PAGE_MASK;
1970    uint64_t pte_addr, pte;
1971
1972    /* Compute the page table entry address */
1973    pte_addr = (pto & SEGMENT_ENTRY_ORIGIN);
1974    pte_addr += (vaddr & VADDR_PX) >> 9;
1975
1976    /* Mark the page table entry as invalid */
1977    pte = cpu_ldq_real_ra(env, pte_addr, ra);
1978    pte |= PAGE_INVALID;
1979    cpu_stq_real_ra(env, pte_addr, pte, ra);
1980
1981    /* XXX we exploit the fact that Linux passes the exact virtual
1982       address here - it's not obliged to! */
1983    if (m4 & 1) {
1984        if (vaddr & ~VADDR_PX) {
1985            tlb_flush_page(cs, page);
1986            /* XXX 31-bit hack */
1987            tlb_flush_page(cs, page ^ 0x80000000);
1988        } else {
1989            /* looks like we don't have a valid virtual address */
1990            tlb_flush(cs);
1991        }
1992    } else {
1993        if (vaddr & ~VADDR_PX) {
1994            tlb_flush_page_all_cpus_synced(cs, page);
1995            /* XXX 31-bit hack */
1996            tlb_flush_page_all_cpus_synced(cs, page ^ 0x80000000);
1997        } else {
1998            /* looks like we don't have a valid virtual address */
1999            tlb_flush_all_cpus_synced(cs);
2000        }
2001    }
2002}
2003
2004/* flush local tlb */
2005void HELPER(ptlb)(CPUS390XState *env)
2006{
2007    S390CPU *cpu = s390_env_get_cpu(env);
2008
2009    tlb_flush(CPU(cpu));
2010}
2011
2012/* flush global tlb */
2013void HELPER(purge)(CPUS390XState *env)
2014{
2015    S390CPU *cpu = s390_env_get_cpu(env);
2016
2017    tlb_flush_all_cpus_synced(CPU(cpu));
2018}
2019
2020/* load using real address */
2021uint64_t HELPER(lura)(CPUS390XState *env, uint64_t addr)
2022{
2023    return cpu_ldl_real_ra(env, wrap_address(env, addr), GETPC());
2024}
2025
2026uint64_t HELPER(lurag)(CPUS390XState *env, uint64_t addr)
2027{
2028    return cpu_ldq_real_ra(env, wrap_address(env, addr), GETPC());
2029}
2030
2031/* store using real address */
2032void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint64_t v1)
2033{
2034    cpu_stl_real_ra(env, wrap_address(env, addr), (uint32_t)v1, GETPC());
2035
2036    if ((env->psw.mask & PSW_MASK_PER) &&
2037        (env->cregs[9] & PER_CR9_EVENT_STORE) &&
2038        (env->cregs[9] & PER_CR9_EVENT_STORE_REAL)) {
2039        /* PSW is saved just before calling the helper.  */
2040        env->per_address = env->psw.addr;
2041        env->per_perc_atmid = PER_CODE_EVENT_STORE_REAL | get_per_atmid(env);
2042    }
2043}
2044
2045void HELPER(sturg)(CPUS390XState *env, uint64_t addr, uint64_t v1)
2046{
2047    cpu_stq_real_ra(env, wrap_address(env, addr), v1, GETPC());
2048
2049    if ((env->psw.mask & PSW_MASK_PER) &&
2050        (env->cregs[9] & PER_CR9_EVENT_STORE) &&
2051        (env->cregs[9] & PER_CR9_EVENT_STORE_REAL)) {
2052        /* PSW is saved just before calling the helper.  */
2053        env->per_address = env->psw.addr;
2054        env->per_perc_atmid = PER_CODE_EVENT_STORE_REAL | get_per_atmid(env);
2055    }
2056}
2057
2058/* load real address */
2059uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
2060{
2061    CPUState *cs = CPU(s390_env_get_cpu(env));
2062    uint32_t cc = 0;
2063    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
2064    uint64_t ret;
2065    int old_exc, flags;
2066
2067    /* XXX incomplete - has more corner cases */
2068    if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
2069        s390_program_interrupt(env, PGM_SPECIAL_OP, 2, GETPC());
2070    }
2071
2072    old_exc = cs->exception_index;
2073    if (mmu_translate(env, addr, 0, asc, &ret, &flags, true)) {
2074        cc = 3;
2075    }
2076    if (cs->exception_index == EXCP_PGM) {
2077        ret = env->int_pgm_code | 0x80000000;
2078    } else {
2079        ret |= addr & ~TARGET_PAGE_MASK;
2080    }
2081    cs->exception_index = old_exc;
2082
2083    env->cc_op = cc;
2084    return ret;
2085}
2086#endif
2087
2088/* load pair from quadword */
2089static uint64_t do_lpq(CPUS390XState *env, uint64_t addr, bool parallel)
2090{
2091    uintptr_t ra = GETPC();
2092    uint64_t hi, lo;
2093
2094    if (parallel) {
2095#ifndef CONFIG_ATOMIC128
2096        cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
2097#else
2098        int mem_idx = cpu_mmu_index(env, false);
2099        TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
2100        Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
2101        hi = int128_gethi(v);
2102        lo = int128_getlo(v);
2103#endif
2104    } else {
2105        check_alignment(env, addr, 16, ra);
2106
2107        hi = cpu_ldq_data_ra(env, addr + 0, ra);
2108        lo = cpu_ldq_data_ra(env, addr + 8, ra);
2109    }
2110
2111    env->retxl = lo;
2112    return hi;
2113}
2114
2115uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr)
2116{
2117    return do_lpq(env, addr, false);
2118}
2119
2120uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
2121{
2122    return do_lpq(env, addr, true);
2123}
2124
2125/* store pair to quadword */
2126static void do_stpq(CPUS390XState *env, uint64_t addr,
2127                    uint64_t low, uint64_t high, bool parallel)
2128{
2129    uintptr_t ra = GETPC();
2130
2131    if (parallel) {
2132#ifndef CONFIG_ATOMIC128
2133        cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
2134#else
2135        int mem_idx = cpu_mmu_index(env, false);
2136        TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
2137
2138        Int128 v = int128_make128(low, high);
2139        helper_atomic_sto_be_mmu(env, addr, v, oi, ra);
2140#endif
2141    } else {
2142        check_alignment(env, addr, 16, ra);
2143
2144        cpu_stq_data_ra(env, addr + 0, high, ra);
2145        cpu_stq_data_ra(env, addr + 8, low, ra);
2146    }
2147}
2148
2149void HELPER(stpq)(CPUS390XState *env, uint64_t addr,
2150                  uint64_t low, uint64_t high)
2151{
2152    do_stpq(env, addr, low, high, false);
2153}
2154
2155void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
2156                           uint64_t low, uint64_t high)
2157{
2158    do_stpq(env, addr, low, high, true);
2159}
2160
2161/* Execute instruction.  This instruction executes an insn modified with
2162   the contents of r1.  It does not change the executed instruction in memory;
2163   it does not change the program counter.
2164
2165   Perform this by recording the modified instruction in env->ex_value.
2166   This will be noticed by cpu_get_tb_cpu_state and thus tb translation.
2167*/
2168void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr)
2169{
2170    uint64_t insn = cpu_lduw_code(env, addr);
2171    uint8_t opc = insn >> 8;
2172
2173    /* Or in the contents of R1[56:63].  */
2174    insn |= r1 & 0xff;
2175
2176    /* Load the rest of the instruction.  */
2177    insn <<= 48;
2178    switch (get_ilen(opc)) {
2179    case 2:
2180        break;
2181    case 4:
2182        insn |= (uint64_t)cpu_lduw_code(env, addr + 2) << 32;
2183        break;
2184    case 6:
2185        insn |= (uint64_t)(uint32_t)cpu_ldl_code(env, addr + 2) << 16;
2186        break;
2187    default:
2188        g_assert_not_reached();
2189    }
2190
2191    /* The very most common cases can be sped up by avoiding a new TB.  */
2192    if ((opc & 0xf0) == 0xd0) {
2193        typedef uint32_t (*dx_helper)(CPUS390XState *, uint32_t, uint64_t,
2194                                      uint64_t, uintptr_t);
2195        static const dx_helper dx[16] = {
2196            [0x2] = do_helper_mvc,
2197            [0x4] = do_helper_nc,
2198            [0x5] = do_helper_clc,
2199            [0x6] = do_helper_oc,
2200            [0x7] = do_helper_xc,
2201            [0xc] = do_helper_tr,
2202        };
2203        dx_helper helper = dx[opc & 0xf];
2204
2205        if (helper) {
2206            uint32_t l = extract64(insn, 48, 8);
2207            uint32_t b1 = extract64(insn, 44, 4);
2208            uint32_t d1 = extract64(insn, 32, 12);
2209            uint32_t b2 = extract64(insn, 28, 4);
2210            uint32_t d2 = extract64(insn, 16, 12);
2211            uint64_t a1 = wrap_address(env, env->regs[b1] + d1);
2212            uint64_t a2 = wrap_address(env, env->regs[b2] + d2);
2213
2214            env->cc_op = helper(env, l, a1, a2, 0);
2215            env->psw.addr += ilen;
2216            return;
2217        }
2218    } else if (opc == 0x0a) {
2219        env->int_svc_code = extract64(insn, 48, 8);
2220        env->int_svc_ilen = ilen;
2221        helper_exception(env, EXCP_SVC);
2222        g_assert_not_reached();
2223    }
2224
2225    /* Record the insn we want to execute as well as the ilen to use
2226       during the execution of the target insn.  This will also ensure
2227       that ex_value is non-zero, which flags that we are in a state
2228       that requires such execution.  */
2229    env->ex_value = insn | ilen;
2230}
2231
2232uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src,
2233                       uint64_t len)
2234{
2235    const uint8_t psw_key = (env->psw.mask & PSW_MASK_KEY) >> PSW_SHIFT_KEY;
2236    const uint8_t psw_as = (env->psw.mask & PSW_MASK_ASC) >> PSW_SHIFT_ASC;
2237    const uint64_t r0 = env->regs[0];
2238    const uintptr_t ra = GETPC();
2239    uint8_t dest_key, dest_as, dest_k, dest_a;
2240    uint8_t src_key, src_as, src_k, src_a;
2241    uint64_t val;
2242    int cc = 0;
2243
2244    HELPER_LOG("%s dest %" PRIx64 ", src %" PRIx64 ", len %" PRIx64 "\n",
2245               __func__, dest, src, len);
2246
2247    if (!(env->psw.mask & PSW_MASK_DAT)) {
2248        s390_program_interrupt(env, PGM_SPECIAL_OP, 6, ra);
2249    }
2250
2251    /* OAC (operand access control) for the first operand -> dest */
2252    val = (r0 & 0xffff0000ULL) >> 16;
2253    dest_key = (val >> 12) & 0xf;
2254    dest_as = (val >> 6) & 0x3;
2255    dest_k = (val >> 1) & 0x1;
2256    dest_a = val & 0x1;
2257
2258    /* OAC (operand access control) for the second operand -> src */
2259    val = (r0 & 0x0000ffffULL);
2260    src_key = (val >> 12) & 0xf;
2261    src_as = (val >> 6) & 0x3;
2262    src_k = (val >> 1) & 0x1;
2263    src_a = val & 0x1;
2264
2265    if (!dest_k) {
2266        dest_key = psw_key;
2267    }
2268    if (!src_k) {
2269        src_key = psw_key;
2270    }
2271    if (!dest_a) {
2272        dest_as = psw_as;
2273    }
2274    if (!src_a) {
2275        src_as = psw_as;
2276    }
2277
2278    if (dest_a && dest_as == AS_HOME && (env->psw.mask & PSW_MASK_PSTATE)) {
2279        s390_program_interrupt(env, PGM_SPECIAL_OP, 6, ra);
2280    }
2281    if (!(env->cregs[0] & CR0_SECONDARY) &&
2282        (dest_as == AS_SECONDARY || src_as == AS_SECONDARY)) {
2283        s390_program_interrupt(env, PGM_SPECIAL_OP, 6, ra);
2284    }
2285    if (!psw_key_valid(env, dest_key) || !psw_key_valid(env, src_key)) {
2286        s390_program_interrupt(env, PGM_PRIVILEGED, 6, ra);
2287    }
2288
2289    len = wrap_length(env, len);
2290    if (len > 4096) {
2291        cc = 3;
2292        len = 4096;
2293    }
2294
2295    /* FIXME: AR-mode and proper problem state mode (using PSW keys) missing */
2296    if (src_as == AS_ACCREG || dest_as == AS_ACCREG ||
2297        (env->psw.mask & PSW_MASK_PSTATE)) {
2298        qemu_log_mask(LOG_UNIMP, "%s: AR-mode and PSTATE support missing\n",
2299                      __func__);
2300        s390_program_interrupt(env, PGM_ADDRESSING, 6, ra);
2301    }
2302
2303    /* FIXME: a) LAP
2304     *        b) Access using correct keys
2305     *        c) AR-mode
2306     */
2307#ifdef CONFIG_USER_ONLY
2308    /* psw keys are never valid in user mode, we will never reach this */
2309    g_assert_not_reached();
2310#else
2311    fast_memmove_as(env, dest, src, len, dest_as, src_as, ra);
2312#endif
2313
2314    return cc;
2315}
2316
2317/* Decode a Unicode character.  A return value < 0 indicates success, storing
2318   the UTF-32 result into OCHAR and the input length into OLEN.  A return
2319   value >= 0 indicates failure, and the CC value to be returned.  */
2320typedef int (*decode_unicode_fn)(CPUS390XState *env, uint64_t addr,
2321                                 uint64_t ilen, bool enh_check, uintptr_t ra,
2322                                 uint32_t *ochar, uint32_t *olen);
2323
2324/* Encode a Unicode character.  A return value < 0 indicates success, storing
2325   the bytes into ADDR and the output length into OLEN.  A return value >= 0
2326   indicates failure, and the CC value to be returned.  */
2327typedef int (*encode_unicode_fn)(CPUS390XState *env, uint64_t addr,
2328                                 uint64_t ilen, uintptr_t ra, uint32_t c,
2329                                 uint32_t *olen);
2330
2331static int decode_utf8(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2332                       bool enh_check, uintptr_t ra,
2333                       uint32_t *ochar, uint32_t *olen)
2334{
2335    uint8_t s0, s1, s2, s3;
2336    uint32_t c, l;
2337
2338    if (ilen < 1) {
2339        return 0;
2340    }
2341    s0 = cpu_ldub_data_ra(env, addr, ra);
2342    if (s0 <= 0x7f) {
2343        /* one byte character */
2344        l = 1;
2345        c = s0;
2346    } else if (s0 <= (enh_check ? 0xc1 : 0xbf)) {
2347        /* invalid character */
2348        return 2;
2349    } else if (s0 <= 0xdf) {
2350        /* two byte character */
2351        l = 2;
2352        if (ilen < 2) {
2353            return 0;
2354        }
2355        s1 = cpu_ldub_data_ra(env, addr + 1, ra);
2356        c = s0 & 0x1f;
2357        c = (c << 6) | (s1 & 0x3f);
2358        if (enh_check && (s1 & 0xc0) != 0x80) {
2359            return 2;
2360        }
2361    } else if (s0 <= 0xef) {
2362        /* three byte character */
2363        l = 3;
2364        if (ilen < 3) {
2365            return 0;
2366        }
2367        s1 = cpu_ldub_data_ra(env, addr + 1, ra);
2368        s2 = cpu_ldub_data_ra(env, addr + 2, ra);
2369        c = s0 & 0x0f;
2370        c = (c << 6) | (s1 & 0x3f);
2371        c = (c << 6) | (s2 & 0x3f);
2372        /* Fold the byte-by-byte range descriptions in the PoO into
2373           tests against the complete value.  It disallows encodings
2374           that could be smaller, and the UTF-16 surrogates.  */
2375        if (enh_check
2376            && ((s1 & 0xc0) != 0x80
2377                || (s2 & 0xc0) != 0x80
2378                || c < 0x1000
2379                || (c >= 0xd800 && c <= 0xdfff))) {
2380            return 2;
2381        }
2382    } else if (s0 <= (enh_check ? 0xf4 : 0xf7)) {
2383        /* four byte character */
2384        l = 4;
2385        if (ilen < 4) {
2386            return 0;
2387        }
2388        s1 = cpu_ldub_data_ra(env, addr + 1, ra);
2389        s2 = cpu_ldub_data_ra(env, addr + 2, ra);
2390        s3 = cpu_ldub_data_ra(env, addr + 3, ra);
2391        c = s0 & 0x07;
2392        c = (c << 6) | (s1 & 0x3f);
2393        c = (c << 6) | (s2 & 0x3f);
2394        c = (c << 6) | (s3 & 0x3f);
2395        /* See above.  */
2396        if (enh_check
2397            && ((s1 & 0xc0) != 0x80
2398                || (s2 & 0xc0) != 0x80
2399                || (s3 & 0xc0) != 0x80
2400                || c < 0x010000
2401                || c > 0x10ffff)) {
2402            return 2;
2403        }
2404    } else {
2405        /* invalid character */
2406        return 2;
2407    }
2408
2409    *ochar = c;
2410    *olen = l;
2411    return -1;
2412}
2413
2414static int decode_utf16(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2415                        bool enh_check, uintptr_t ra,
2416                        uint32_t *ochar, uint32_t *olen)
2417{
2418    uint16_t s0, s1;
2419    uint32_t c, l;
2420
2421    if (ilen < 2) {
2422        return 0;
2423    }
2424    s0 = cpu_lduw_data_ra(env, addr, ra);
2425    if ((s0 & 0xfc00) != 0xd800) {
2426        /* one word character */
2427        l = 2;
2428        c = s0;
2429    } else {
2430        /* two word character */
2431        l = 4;
2432        if (ilen < 4) {
2433            return 0;
2434        }
2435        s1 = cpu_lduw_data_ra(env, addr + 2, ra);
2436        c = extract32(s0, 6, 4) + 1;
2437        c = (c << 6) | (s0 & 0x3f);
2438        c = (c << 10) | (s1 & 0x3ff);
2439        if (enh_check && (s1 & 0xfc00) != 0xdc00) {
2440            /* invalid surrogate character */
2441            return 2;
2442        }
2443    }
2444
2445    *ochar = c;
2446    *olen = l;
2447    return -1;
2448}
2449
2450static int decode_utf32(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2451                        bool enh_check, uintptr_t ra,
2452                        uint32_t *ochar, uint32_t *olen)
2453{
2454    uint32_t c;
2455
2456    if (ilen < 4) {
2457        return 0;
2458    }
2459    c = cpu_ldl_data_ra(env, addr, ra);
2460    if ((c >= 0xd800 && c <= 0xdbff) || c > 0x10ffff) {
2461        /* invalid unicode character */
2462        return 2;
2463    }
2464
2465    *ochar = c;
2466    *olen = 4;
2467    return -1;
2468}
2469
2470static int encode_utf8(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2471                       uintptr_t ra, uint32_t c, uint32_t *olen)
2472{
2473    uint8_t d[4];
2474    uint32_t l, i;
2475
2476    if (c <= 0x7f) {
2477        /* one byte character */
2478        l = 1;
2479        d[0] = c;
2480    } else if (c <= 0x7ff) {
2481        /* two byte character */
2482        l = 2;
2483        d[1] = 0x80 | extract32(c, 0, 6);
2484        d[0] = 0xc0 | extract32(c, 6, 5);
2485    } else if (c <= 0xffff) {
2486        /* three byte character */
2487        l = 3;
2488        d[2] = 0x80 | extract32(c, 0, 6);
2489        d[1] = 0x80 | extract32(c, 6, 6);
2490        d[0] = 0xe0 | extract32(c, 12, 4);
2491    } else {
2492        /* four byte character */
2493        l = 4;
2494        d[3] = 0x80 | extract32(c, 0, 6);
2495        d[2] = 0x80 | extract32(c, 6, 6);
2496        d[1] = 0x80 | extract32(c, 12, 6);
2497        d[0] = 0xf0 | extract32(c, 18, 3);
2498    }
2499
2500    if (ilen < l) {
2501        return 1;
2502    }
2503    for (i = 0; i < l; ++i) {
2504        cpu_stb_data_ra(env, addr + i, d[i], ra);
2505    }
2506
2507    *olen = l;
2508    return -1;
2509}
2510
2511static int encode_utf16(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2512                        uintptr_t ra, uint32_t c, uint32_t *olen)
2513{
2514    uint16_t d0, d1;
2515
2516    if (c <= 0xffff) {
2517        /* one word character */
2518        if (ilen < 2) {
2519            return 1;
2520        }
2521        cpu_stw_data_ra(env, addr, c, ra);
2522        *olen = 2;
2523    } else {
2524        /* two word character */
2525        if (ilen < 4) {
2526            return 1;
2527        }
2528        d1 = 0xdc00 | extract32(c, 0, 10);
2529        d0 = 0xd800 | extract32(c, 10, 6);
2530        d0 = deposit32(d0, 6, 4, extract32(c, 16, 5) - 1);
2531        cpu_stw_data_ra(env, addr + 0, d0, ra);
2532        cpu_stw_data_ra(env, addr + 2, d1, ra);
2533        *olen = 4;
2534    }
2535
2536    return -1;
2537}
2538
2539static int encode_utf32(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2540                        uintptr_t ra, uint32_t c, uint32_t *olen)
2541{
2542    if (ilen < 4) {
2543        return 1;
2544    }
2545    cpu_stl_data_ra(env, addr, c, ra);
2546    *olen = 4;
2547    return -1;
2548}
2549
2550static inline uint32_t convert_unicode(CPUS390XState *env, uint32_t r1,
2551                                       uint32_t r2, uint32_t m3, uintptr_t ra,
2552                                       decode_unicode_fn decode,
2553                                       encode_unicode_fn encode)
2554{
2555    uint64_t dst = get_address(env, r1);
2556    uint64_t dlen = get_length(env, r1 + 1);
2557    uint64_t src = get_address(env, r2);
2558    uint64_t slen = get_length(env, r2 + 1);
2559    bool enh_check = m3 & 1;
2560    int cc, i;
2561
2562    /* Lest we fail to service interrupts in a timely manner, limit the
2563       amount of work we're willing to do.  For now, let's cap at 256.  */
2564    for (i = 0; i < 256; ++i) {
2565        uint32_t c, ilen, olen;
2566
2567        cc = decode(env, src, slen, enh_check, ra, &c, &ilen);
2568        if (unlikely(cc >= 0)) {
2569            break;
2570        }
2571        cc = encode(env, dst, dlen, ra, c, &olen);
2572        if (unlikely(cc >= 0)) {
2573            break;
2574        }
2575
2576        src += ilen;
2577        slen -= ilen;
2578        dst += olen;
2579        dlen -= olen;
2580        cc = 3;
2581    }
2582
2583    set_address(env, r1, dst);
2584    set_length(env, r1 + 1, dlen);
2585    set_address(env, r2, src);
2586    set_length(env, r2 + 1, slen);
2587
2588    return cc;
2589}
2590
2591uint32_t HELPER(cu12)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2592{
2593    return convert_unicode(env, r1, r2, m3, GETPC(),
2594                           decode_utf8, encode_utf16);
2595}
2596
2597uint32_t HELPER(cu14)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2598{
2599    return convert_unicode(env, r1, r2, m3, GETPC(),
2600                           decode_utf8, encode_utf32);
2601}
2602
2603uint32_t HELPER(cu21)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2604{
2605    return convert_unicode(env, r1, r2, m3, GETPC(),
2606                           decode_utf16, encode_utf8);
2607}
2608
2609uint32_t HELPER(cu24)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2610{
2611    return convert_unicode(env, r1, r2, m3, GETPC(),
2612                           decode_utf16, encode_utf32);
2613}
2614
2615uint32_t HELPER(cu41)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2616{
2617    return convert_unicode(env, r1, r2, m3, GETPC(),
2618                           decode_utf32, encode_utf8);
2619}
2620
2621uint32_t HELPER(cu42)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2622{
2623    return convert_unicode(env, r1, r2, m3, GETPC(),
2624                           decode_utf32, encode_utf16);
2625}
2626