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