mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 19:33:39 +08:00
target-s390: Convert CKSM
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
6e2704e74d
commit
374724f91a
@ -75,7 +75,7 @@ DEF_HELPER_3(sqxb, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
|
||||
DEF_HELPER_4(unpk, void, env, i32, i64, i64)
|
||||
DEF_HELPER_4(tr, void, env, i32, i64, i64)
|
||||
DEF_HELPER_3(cksm, void, env, i32, i32)
|
||||
DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
|
||||
|
||||
|
@ -91,6 +91,9 @@
|
||||
C(0xa706, BRCT, RI_b, Z, 0, 0, 0, 0, bct32, 0)
|
||||
C(0xa707, BRCTG, RI_b, Z, 0, 0, 0, 0, bct64, 0)
|
||||
|
||||
/* CHECKSUM */
|
||||
C(0xb241, CKSM, RRE, Z, r1_o, ra2, new, r1_32, cksm, 0)
|
||||
|
||||
/* COMPARE */
|
||||
C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
|
||||
C(0x5900, C, RX_a, Z, r1_o, m2_32s, 0, 0, 0, cmps32)
|
||||
|
@ -747,42 +747,49 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
|
||||
}
|
||||
|
||||
/* checksum */
|
||||
void HELPER(cksm)(CPUS390XState *env, uint32_t r1, uint32_t r2)
|
||||
uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1,
|
||||
uint64_t src, uint64_t src_len)
|
||||
{
|
||||
uint64_t src = get_address_31fix(env, r2);
|
||||
uint64_t src_len = env->regs[(r2 + 1) & 15];
|
||||
uint64_t cksm = (uint32_t)env->regs[r1];
|
||||
uint64_t max_len, len;
|
||||
uint64_t cksm = (uint32_t)r1;
|
||||
|
||||
while (src_len >= 4) {
|
||||
cksm += cpu_ldl_data(env, src);
|
||||
/* Lest we fail to service interrupts in a timely manner, limit the
|
||||
amount of work we're willing to do. For now, lets cap at 8k. */
|
||||
max_len = (src_len > 0x2000 ? 0x2000 : src_len);
|
||||
|
||||
/* move to next word */
|
||||
src_len -= 4;
|
||||
src += 4;
|
||||
/* Process full words as available. */
|
||||
for (len = 0; len + 4 <= max_len; len += 4, src += 4) {
|
||||
cksm += (uint32_t)cpu_ldl_data(env, src);
|
||||
}
|
||||
|
||||
switch (src_len) {
|
||||
case 0:
|
||||
break;
|
||||
switch (max_len - len) {
|
||||
case 1:
|
||||
cksm += cpu_ldub_data(env, src) << 24;
|
||||
len += 1;
|
||||
break;
|
||||
case 2:
|
||||
cksm += cpu_lduw_data(env, src) << 16;
|
||||
len += 2;
|
||||
break;
|
||||
case 3:
|
||||
cksm += cpu_lduw_data(env, src) << 16;
|
||||
cksm += cpu_ldub_data(env, src + 2) << 8;
|
||||
len += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
/* indicate we've processed everything */
|
||||
env->regs[r2] = src + src_len;
|
||||
env->regs[(r2 + 1) & 15] = 0;
|
||||
/* Fold the carry from the checksum. Note that we can see carry-out
|
||||
during folding more than once (but probably not more than twice). */
|
||||
while (cksm > 0xffffffffull) {
|
||||
cksm = (uint32_t)cksm + (cksm >> 32);
|
||||
}
|
||||
|
||||
/* store result */
|
||||
env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
|
||||
((uint32_t)cksm + (cksm >> 32));
|
||||
/* Indicate whether or not we've processed everything. */
|
||||
env->cc_op = (len == src_len ? 0 : 3);
|
||||
|
||||
/* Return both cksm and processed length. */
|
||||
env->retxl = cksm;
|
||||
return len;
|
||||
}
|
||||
|
||||
void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest,
|
||||
|
@ -1034,15 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
|
||||
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
|
||||
|
||||
switch (op) {
|
||||
case 0x41: /* CKSM R1,R2 [RRE] */
|
||||
tmp32_1 = tcg_const_i32(r1);
|
||||
tmp32_2 = tcg_const_i32(r2);
|
||||
potential_page_fault(s);
|
||||
gen_helper_cksm(cpu_env, tmp32_1, tmp32_2);
|
||||
tcg_temp_free_i32(tmp32_1);
|
||||
tcg_temp_free_i32(tmp32_2);
|
||||
gen_op_movi_cc(s, 0);
|
||||
break;
|
||||
case 0x4e: /* SAR R1,R2 [RRE] */
|
||||
tmp32_1 = load_reg32(r2);
|
||||
tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
|
||||
@ -2047,6 +2038,23 @@ static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r2 = get_field(s->fields, r2);
|
||||
TCGv_i64 len = tcg_temp_new_i64();
|
||||
|
||||
potential_page_fault(s);
|
||||
gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]);
|
||||
set_cc_static(s);
|
||||
return_low128(o->out);
|
||||
|
||||
tcg_gen_add_i64(regs[r2], regs[r2], len);
|
||||
tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len);
|
||||
tcg_temp_free_i64(len);
|
||||
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_clc(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int l = get_field(s->fields, l1);
|
||||
@ -3847,6 +3855,11 @@ static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
|
||||
o->g_in1 = o->g_in2 = true;
|
||||
}
|
||||
|
||||
static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
|
||||
{
|
||||
o->in2 = get_address(s, 0, get_field(f, r2), 0);
|
||||
}
|
||||
|
||||
static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
|
||||
{
|
||||
int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
|
||||
|
Loading…
Reference in New Issue
Block a user