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