[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 12/13] s390x: fix cksm instruction
From: |
Alexander Graf |
Subject: |
[Qemu-devel] [PATCH 12/13] s390x: fix cksm instruction |
Date: |
Thu, 2 Jun 2011 08:51:42 +0200 |
The cksm instruction was implemented incorrectly, rendering UDP and TCP
checksum calculation wrong, making an emulated s390x Linux guest break
in most networking operations.
This patch fixes odd end checksum calculation, takes the input register
as input for the checksum and optimizes the overflow pieces by a bit.
Signed-off-by: Alexander Graf <address@hidden>
---
target-s390x/op_helper.c | 28 ++++++++--------------------
1 files changed, 8 insertions(+), 20 deletions(-)
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 49760a4..db03a79 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -1731,25 +1731,15 @@ void HELPER(sqdbr)(uint32_t f1, uint32_t f2)
env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
}
-static inline uint64_t cksm_overflow(uint64_t cksm)
-{
- if (cksm > 0xffffffffULL) {
- cksm &= 0xffffffffULL;
- cksm++;
- }
- return cksm;
-}
-
/* checksum */
void HELPER(cksm)(uint32_t r1, uint32_t r2)
{
uint64_t src = get_address_31fix(r2);
uint64_t src_len = env->regs[(r2 + 1) & 15];
- uint64_t cksm = 0;
+ uint64_t cksm = (uint32_t)env->regs[r1];
while (src_len >= 4) {
cksm += ldl(src);
- cksm = cksm_overflow(cksm);
/* move to next word */
src_len -= 4;
@@ -1760,26 +1750,24 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2)
case 0:
break;
case 1:
- cksm += ldub(src);
- cksm = cksm_overflow(cksm);
+ cksm += ldub(src) << 24;
break;
case 2:
- cksm += lduw(src);
- cksm = cksm_overflow(cksm);
+ cksm += lduw(src) << 16;
break;
case 3:
- /* XXX check if this really is correct */
- cksm += lduw(src) << 8;
- cksm += ldub(src + 2);
- cksm = cksm_overflow(cksm);
+ cksm += lduw(src) << 16;
+ cksm += ldub(src + 2) << 8;
break;
}
/* indicate we've processed everything */
+ env->regs[r2] = src + src_len;
env->regs[(r2 + 1) & 15] = 0;
/* store result */
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (uint32_t)cksm;
+ env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
+ ((uint32_t)cksm + (cksm >> 32));
}
static inline uint32_t cc_calc_ltgt_32(CPUState *env, int32_t src,
--
1.6.0.2
- [Qemu-devel] [PULL 00/13] s390x patch queue June 03 2011, Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 09/13] target-s390x: Add missing tcg_temp_free_i64() in disas_s390_insn(), opc == 0x90, Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 03/13] target-s390x: Fix wrong argument in call of tcg_gen_shl_i64(), Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 04/13] target-s390x: Fix duplicate call of tcg_temp_new_i64, Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 02/13] target-s390x: Fix build for non-linux hosts, Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 08/13] target-s390x: Add missing tcg_temp_free_i64() in disas_s390_insn(), opc == 0x8e, Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 10/13] target-s390x: Add missing tcg_temp_free_i32(), Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 12/13] s390x: fix cksm instruction,
Alexander Graf <=
- [Qemu-devel] [PATCH 06/13] target-s390x: Add missing tcg_temp_free_i64() in do_mh(), Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 11/13] s390x: free tmp explicitly in every opcode for disas_a5(), Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 01/13] s390x: update zipl rom, Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 07/13] target-s390x: Add missing tcg_temp_free_i64() in disas_b2(), Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 13/13] s390x: implement lrvgr, Alexander Graf, 2011/06/03
- [Qemu-devel] [PATCH 05/13] target-s390x: Add missing tcg_temp_free_i64() in gen_jcc(), Alexander Graf, 2011/06/03
- Re: [Qemu-devel] [PULL 00/13] s390x patch queue June 03 2011, Aurelien Jarno, 2011/06/03