Revision 374724f9

b/target-s390x/helper.h
75 75
DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
76 76
DEF_HELPER_4(unpk, void, env, i32, i64, i64)
77 77
DEF_HELPER_4(tr, void, env, i32, i64, i64)
78
DEF_HELPER_3(cksm, void, env, i32, i32)
78
DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
79 79
DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
80 80
DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
81 81

  
b/target-s390x/insn-data.def
91 91
    C(0xa706, BRCT,    RI_b,  Z,   0, 0, 0, 0, bct32, 0)
92 92
    C(0xa707, BRCTG,   RI_b,  Z,   0, 0, 0, 0, bct64, 0)
93 93

  
94
/* CHECKSUM */
95
    C(0xb241, CKSM,    RRE,   Z,   r1_o, ra2, new, r1_32, cksm, 0)
96

  
94 97
/* COMPARE */
95 98
    C(0x1900, CR,      RR_a,  Z,   r1_o, r2_o, 0, 0, 0, cmps32)
96 99
    C(0x5900, C,       RX_a,  Z,   r1_o, m2_32s, 0, 0, 0, cmps32)
b/target-s390x/mem_helper.c
747 747
}
748 748

  
749 749
/* checksum */
750
void HELPER(cksm)(CPUS390XState *env, uint32_t r1, uint32_t r2)
750
uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1,
751
                      uint64_t src, uint64_t src_len)
751 752
{
752
    uint64_t src = get_address_31fix(env, r2);
753
    uint64_t src_len = env->regs[(r2 + 1) & 15];
754
    uint64_t cksm = (uint32_t)env->regs[r1];
753
    uint64_t max_len, len;
754
    uint64_t cksm = (uint32_t)r1;
755 755

  
756
    while (src_len >= 4) {
757
        cksm += cpu_ldl_data(env, src);
756
    /* Lest we fail to service interrupts in a timely manner, limit the
757
       amount of work we're willing to do.  For now, lets cap at 8k.  */
758
    max_len = (src_len > 0x2000 ? 0x2000 : src_len);
758 759

  
759
        /* move to next word */
760
        src_len -= 4;
761
        src += 4;
760
    /* Process full words as available.  */
761
    for (len = 0; len + 4 <= max_len; len += 4, src += 4) {
762
        cksm += (uint32_t)cpu_ldl_data(env, src);
762 763
    }
763 764

  
764
    switch (src_len) {
765
    case 0:
766
        break;
765
    switch (max_len - len) {
767 766
    case 1:
768 767
        cksm += cpu_ldub_data(env, src) << 24;
768
        len += 1;
769 769
        break;
770 770
    case 2:
771 771
        cksm += cpu_lduw_data(env, src) << 16;
772
        len += 2;
772 773
        break;
773 774
    case 3:
774 775
        cksm += cpu_lduw_data(env, src) << 16;
775 776
        cksm += cpu_ldub_data(env, src + 2) << 8;
777
        len += 3;
776 778
        break;
777 779
    }
778 780

  
779
    /* indicate we've processed everything */
780
    env->regs[r2] = src + src_len;
781
    env->regs[(r2 + 1) & 15] = 0;
781
    /* Fold the carry from the checksum.  Note that we can see carry-out
782
       during folding more than once (but probably not more than twice).  */
783
    while (cksm > 0xffffffffull) {
784
        cksm = (uint32_t)cksm + (cksm >> 32);
785
    }
786

  
787
    /* Indicate whether or not we've processed everything.  */
788
    env->cc_op = (len == src_len ? 0 : 3);
782 789

  
783
    /* store result */
784
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
785
        ((uint32_t)cksm + (cksm >> 32));
790
    /* Return both cksm and processed length.  */
791
    env->retxl = cksm;
792
    return len;
786 793
}
787 794

  
788 795
void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest,
b/target-s390x/translate.c
1034 1034
    LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
1035 1035

  
1036 1036
    switch (op) {
1037
    case 0x41: /* CKSM    R1,R2     [RRE] */
1038
        tmp32_1 = tcg_const_i32(r1);
1039
        tmp32_2 = tcg_const_i32(r2);
1040
        potential_page_fault(s);
1041
        gen_helper_cksm(cpu_env, tmp32_1, tmp32_2);
1042
        tcg_temp_free_i32(tmp32_1);
1043
        tcg_temp_free_i32(tmp32_2);
1044
        gen_op_movi_cc(s, 0);
1045
        break;
1046 1037
    case 0x4e: /* SAR     R1,R2     [RRE] */
1047 1038
        tmp32_1 = load_reg32(r2);
1048 1039
        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
......
2047 2038
    return NO_EXIT;
2048 2039
}
2049 2040

  
2041
static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
2042
{
2043
    int r2 = get_field(s->fields, r2);
2044
    TCGv_i64 len = tcg_temp_new_i64();
2045

  
2046
    potential_page_fault(s);
2047
    gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]);
2048
    set_cc_static(s);
2049
    return_low128(o->out);
2050

  
2051
    tcg_gen_add_i64(regs[r2], regs[r2], len);
2052
    tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len);
2053
    tcg_temp_free_i64(len);
2054

  
2055
    return NO_EXIT;
2056
}
2057

  
2050 2058
static ExitStatus op_clc(DisasContext *s, DisasOps *o)
2051 2059
{
2052 2060
    int l = get_field(s->fields, l1);
......
3847 3855
    o->g_in1 = o->g_in2 = true;
3848 3856
}
3849 3857

  
3858
static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
3859
{
3860
    o->in2 = get_address(s, 0, get_field(f, r2), 0);
3861
}
3862

  
3850 3863
static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
3851 3864
{
3852 3865
    int x2 = have_field(f, x2) ? get_field(f, x2) : 0;

Also available in: Unified diff