target/m68k: fix V flag for CC_OP_SUBx

V flag for subtraction is:

v = (res ^ src1) & (src1 ^ src2)

(see COMPUTE_CCR() in target/m68k/helper.c)

But gen_flush_flags() uses:

v = (res ^ src2) & (src1 ^ src2)

The problem has been found with the following program:

.global _start
_start:
move.l #-2147483648,%d0
subq.l #1,%d0
jvc 1f
move.l #1,%d1
move.l #1,%d0
trap #0
1:
move.l #0,%d1
move.l #1,%d0
trap #0

It works fine (exit(1)) on real hardware, and with "-singlestep".

"-singlestep" uses gen_helper_flush_flags(), whereas
without "-singlestep", V flag is computed directly in
gen_flush_flags().

This patch updates gen_flush_flags() to have the same result
as with gen_helper_flush_flags().

Backports commit 043b936ef6fe53396b3c6b8f5562ea3e238a071d from qemu
This commit is contained in:
Laurent Vivier 2018-03-03 14:59:12 -05:00 committed by Lioncash
parent e1c2fac129
commit 68c9ab9b77
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -555,7 +555,7 @@ static void gen_flush_flags(DisasContext *s)
t1 = tcg_temp_new(tcg_ctx); t1 = tcg_temp_new(tcg_ctx);
tcg_gen_add_i32(tcg_ctx, t0, tcg_ctx->QREG_CC_N, tcg_ctx->QREG_CC_V); tcg_gen_add_i32(tcg_ctx, t0, tcg_ctx->QREG_CC_N, tcg_ctx->QREG_CC_V);
gen_ext(s, t0, t0, s->cc_op - CC_OP_SUBB, 1); gen_ext(s, t0, t0, s->cc_op - CC_OP_SUBB, 1);
tcg_gen_xor_i32(tcg_ctx, t1, tcg_ctx->QREG_CC_N, tcg_ctx->QREG_CC_V); tcg_gen_xor_i32(tcg_ctx, t1, tcg_ctx->QREG_CC_N, t0);
tcg_gen_xor_i32(tcg_ctx, tcg_ctx->QREG_CC_V, tcg_ctx->QREG_CC_V, t0); tcg_gen_xor_i32(tcg_ctx, tcg_ctx->QREG_CC_V, tcg_ctx->QREG_CC_V, t0);
tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, t0);
tcg_gen_and_i32(tcg_ctx, tcg_ctx->QREG_CC_V, tcg_ctx->QREG_CC_V, t1); tcg_gen_and_i32(tcg_ctx, tcg_ctx->QREG_CC_V, tcg_ctx->QREG_CC_V, t1);