Revision 58a9e35b

b/target-s390x/cc_helper.c
331 331
}
332 332

  
333 333
/* calculate condition code for insert character under mask insn */
334
static uint32_t cc_calc_icm_32(uint32_t mask, uint32_t val)
334
static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
335 335
{
336
    uint32_t cc;
337

  
338
    HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val);
339
    if (mask == 0xf) {
340
        if (!val) {
341
            return 0;
342
        } else if (val & 0x80000000) {
336
    if ((val & mask) == 0) {
337
        return 0;
338
    } else {
339
        int top = clz64(mask);
340
        if ((int64_t)(val << top) < 0) {
343 341
            return 1;
344 342
        } else {
345 343
            return 2;
346 344
        }
347 345
    }
348

  
349
    if (!val || !mask) {
350
        cc = 0;
351
    } else {
352
        while (mask != 1) {
353
            mask >>= 1;
354
            val >>= 8;
355
        }
356
        if (val & 0x80) {
357
            cc = 1;
358
        } else {
359
            cc = 2;
360
        }
361
    }
362
    return cc;
363 346
}
364 347

  
365 348
static uint32_t cc_calc_slag(uint64_t src, uint64_t shift)
......
488 471
        break;
489 472

  
490 473
    case CC_OP_ICM:
491
        r =  cc_calc_icm_32(src, dst);
474
        r =  cc_calc_icm(src, dst);
492 475
        break;
493 476
    case CC_OP_SLAG:
494 477
        r =  cc_calc_slag(src, dst);
b/target-s390x/helper.h
27 27
DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_NO_RWG_SE, i64, s64)
28 28
DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_NO_RWG_SE, s64, s64)
29 29
DEF_HELPER_4(stcmh, void, env, i32, i64, i32)
30
DEF_HELPER_4(icmh, i32, env, i32, i64, i32)
31 30
DEF_HELPER_3(ipm, void, env, i32, i32)
32 31
DEF_HELPER_4(stam, void, env, i32, i64, i32)
33 32
DEF_HELPER_4(lam, void, env, i32, i64, i32)
b/target-s390x/insn-data.def
160 160
/* INSERT CHARACTER */
161 161
    C(0x4300, IC,      RX_a,  Z,   0, m2_8u, 0, r1_8, mov2, 0)
162 162
    C(0xe373, ICY,     RXY_a, LD,  0, m2_8u, 0, r1_8, mov2, 0)
163
/* INSERT CHARACTERS UNDER MASK */
164
    D(0xbf00, ICM,     RS_b,  Z,   0, a2, r1, 0, icm, 0, 0)
165
    D(0xeb81, ICMY,    RSY_b, LD,  0, a2, r1, 0, icm, 0, 0)
166
    D(0xeb80, ICMH,    RSY_b, Z,   0, a2, r1, 0, icm, 0, 32)
163 167
/* INSERT IMMEDIATE */
164 168
    D(0xc008, IIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, insi, 0, 0x2020)
165 169
    D(0xc009, IILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, insi, 0, 0x2000)
b/target-s390x/mem_helper.c
629 629
    }
630 630
}
631 631

  
632
/* insert character under mask high; same as icm, but operates on the
633
   upper half of r1 */
634
uint32_t HELPER(icmh)(CPUS390XState *env, uint32_t r1, uint64_t address,
635
                      uint32_t mask)
636
{
637
    int pos = 56; /* top of the upper half of r1 */
638
    uint64_t rmask = 0xff00000000000000ULL;
639
    uint8_t val = 0;
640
    int ccd = 0;
641
    uint32_t cc = 0;
642

  
643
    while (mask) {
644
        if (mask & 8) {
645
            env->regs[r1] &= ~rmask;
646
            val = cpu_ldub_data(env, address);
647
            if ((val & 0x80) && !ccd) {
648
                cc = 1;
649
            }
650
            ccd = 1;
651
            if (val && cc == 0) {
652
                cc = 2;
653
            }
654
            env->regs[r1] |= (uint64_t)val << pos;
655
            address++;
656
        }
657
        mask = (mask << 1) & 0xf;
658
        pos -= 8;
659
        rmask >>= 8;
660
    }
661

  
662
    return cc;
663
}
664

  
665 632
/* load access registers r1 to r3 from memory at a2 */
666 633
void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
667 634
{
b/target-s390x/translate.c
32 32
#include "disas/disas.h"
33 33
#include "tcg-op.h"
34 34
#include "qemu/log.h"
35
#include "qemu/host-utils.h"
35 36

  
36 37
/* global register indexes */
37 38
static TCGv_ptr cpu_env;
......
561 562
    gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
562 563
}
563 564

  
564
static void set_cc_icm(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
565
{
566
    gen_op_update2_cc_i32(s, CC_OP_ICM, v1, v2);
567
}
568

  
569 565
static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
570 566
{
571 567
    tcg_gen_extu_i32_i64(cc_src, v1);
......
896 892

  
897 893
    case CC_OP_LTGT0_64:
898 894
    case CC_OP_NZ:
899
    case CC_OP_ICM:
900 895
        c->u.s64.a = cc_dst;
901 896
        c->u.s64.b = tcg_const_i64(0);
902 897
        c->g1 = true;
......
910 905

  
911 906
    case CC_OP_TM_32:
912 907
    case CC_OP_TM_64:
908
    case CC_OP_ICM:
913 909
        c->u.s64.a = tcg_temp_new_i64();
914 910
        c->u.s64.b = tcg_const_i64(0);
915 911
        tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
......
1521 1517
        tcg_temp_free_i64(tmp);
1522 1518
        tcg_temp_free_i64(tmp2);
1523 1519
        break;
1524
    case 0x80: /* ICMH      R1,M3,D2(B2)     [RSY] */
1525
        tmp = get_address(s, 0, b2, d2);
1526
        tmp32_1 = tcg_const_i32(r1);
1527
        tmp32_2 = tcg_const_i32(r3);
1528
        potential_page_fault(s);
1529
        /* XXX split CC calculation out */
1530
        gen_helper_icmh(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
1531
        set_cc_static(s);
1532
        tcg_temp_free_i64(tmp);
1533
        tcg_temp_free_i32(tmp32_1);
1534
        tcg_temp_free_i32(tmp32_2);
1535
        break;
1536 1520
    default:
1537 1521
        LOG_DISAS("illegal eb operation 0x%x\n", op);
1538 1522
        gen_illegal_opcode(s);
......
2361 2345
static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
2362 2346
{
2363 2347
    TCGv_i64 tmp, tmp2, tmp3, tmp4;
2364
    TCGv_i32 tmp32_1, tmp32_2, tmp32_3, tmp32_4;
2348
    TCGv_i32 tmp32_1, tmp32_2;
2365 2349
    unsigned char opc;
2366 2350
    uint64_t insn;
2367 2351
    int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
......
2786 2770
        tcg_temp_free_i32(tmp32_1);
2787 2771
        tcg_temp_free_i32(tmp32_2);
2788 2772
        break;
2789
    case 0xbf: /* ICM    R1,M3,D2(B2)     [RS] */
2790
        insn = ld_code4(env, s->pc);
2791
        decode_rs(s, insn, &r1, &r3, &b2, &d2);
2792
        if (r3 == 15) {
2793
            /* effectively a 32-bit load */
2794
            tmp = get_address(s, 0, b2, d2);
2795
            tmp32_1 = tcg_temp_new_i32();
2796
            tmp32_2 = tcg_const_i32(r3);
2797
            tcg_gen_qemu_ld32u(tmp, tmp, get_mem_index(s));
2798
            store_reg32_i64(r1, tmp);
2799
            tcg_gen_trunc_i64_i32(tmp32_1, tmp);
2800
            set_cc_icm(s, tmp32_2, tmp32_1);
2801
            tcg_temp_free_i64(tmp);
2802
            tcg_temp_free_i32(tmp32_1);
2803
            tcg_temp_free_i32(tmp32_2);
2804
        } else if (r3) {
2805
            uint32_t mask = 0x00ffffffUL;
2806
            uint32_t shift = 24;
2807
            int m3 = r3;
2808
            tmp = get_address(s, 0, b2, d2);
2809
            tmp2 = tcg_temp_new_i64();
2810
            tmp32_1 = load_reg32(r1);
2811
            tmp32_2 = tcg_temp_new_i32();
2812
            tmp32_3 = tcg_const_i32(r3);
2813
            tmp32_4 = tcg_const_i32(0);
2814
            while (m3) {
2815
                if (m3 & 8) {
2816
                    tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
2817
                    tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
2818
                    if (shift) {
2819
                        tcg_gen_shli_i32(tmp32_2, tmp32_2, shift);
2820
                    }
2821
                    tcg_gen_andi_i32(tmp32_1, tmp32_1, mask);
2822
                    tcg_gen_or_i32(tmp32_1, tmp32_1, tmp32_2);
2823
                    tcg_gen_or_i32(tmp32_4, tmp32_4, tmp32_2);
2824
                    tcg_gen_addi_i64(tmp, tmp, 1);
2825
                }
2826
                m3 = (m3 << 1) & 0xf;
2827
                mask = (mask >> 8) | 0xff000000UL;
2828
                shift -= 8;
2829
            }
2830
            store_reg32(r1, tmp32_1);
2831
            set_cc_icm(s, tmp32_3, tmp32_4);
2832
            tcg_temp_free_i64(tmp);
2833
            tcg_temp_free_i64(tmp2);
2834
            tcg_temp_free_i32(tmp32_1);
2835
            tcg_temp_free_i32(tmp32_2);
2836
            tcg_temp_free_i32(tmp32_3);
2837
            tcg_temp_free_i32(tmp32_4);
2838
        } else {
2839
            /* i.e. env->cc = 0 */
2840
            gen_op_movi_cc(s, 0);
2841
        }
2842
        break;
2843 2773
    case 0xd2: /* MVC    D1(L,B1),D2(B2)         [SS] */
2844 2774
    case 0xd4: /* NC     D1(L,B1),D2(B2)         [SS] */
2845 2775
    case 0xd5: /* CLC    D1(L,B1),D2(B2)         [SS] */
......
3493 3423
    return NO_EXIT;
3494 3424
}
3495 3425

  
3426
static ExitStatus op_icm(DisasContext *s, DisasOps *o)
3427
{
3428
    int m3 = get_field(s->fields, m3);
3429
    int pos, len, base = s->insn->data;
3430
    TCGv_i64 tmp = tcg_temp_new_i64();
3431
    uint64_t ccm;
3432

  
3433
    switch (m3) {
3434
    case 0xf:
3435
        /* Effectively a 32-bit load.  */
3436
        tcg_gen_qemu_ld32u(tmp, o->in2, get_mem_index(s));
3437
        len = 32;
3438
        goto one_insert;
3439

  
3440
    case 0xc:
3441
    case 0x6:
3442
    case 0x3:
3443
        /* Effectively a 16-bit load.  */
3444
        tcg_gen_qemu_ld16u(tmp, o->in2, get_mem_index(s));
3445
        len = 16;
3446
        goto one_insert;
3447

  
3448
    case 0x8:
3449
    case 0x4:
3450
    case 0x2:
3451
    case 0x1:
3452
        /* Effectively an 8-bit load.  */
3453
        tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
3454
        len = 8;
3455
        goto one_insert;
3456

  
3457
    one_insert:
3458
        pos = base + ctz32(m3) * 8;
3459
        tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len);
3460
        ccm = ((1ull << len) - 1) << pos;
3461
        break;
3462

  
3463
    default:
3464
        /* This is going to be a sequence of loads and inserts.  */
3465
        pos = base + 32 - 8;
3466
        ccm = 0;
3467
        while (m3) {
3468
            if (m3 & 0x8) {
3469
                tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
3470
                tcg_gen_addi_i64(o->in2, o->in2, 1);
3471
                tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8);
3472
                ccm |= 0xff << pos;
3473
            }
3474
            m3 = (m3 << 1) & 0xf;
3475
            pos -= 8;
3476
        }
3477
        break;
3478
    }
3479

  
3480
    tcg_gen_movi_i64(tmp, ccm);
3481
    gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out);
3482
    tcg_temp_free_i64(tmp);
3483
    return NO_EXIT;
3484
}
3485

  
3496 3486
static ExitStatus op_insi(DisasContext *s, DisasOps *o)
3497 3487
{
3498 3488
    int shift = s->insn->data & 0xff;

Also available in: Unified diff