diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2024-05-31 11:00:33 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2024-10-31 18:28:33 +0100 |
commit | 134ffcb276be569fcb7531b2266b0df0d2a1db81 (patch) | |
tree | d33c278e3deb08f457eb297806de5e91e220516b | |
parent | 24899cdcd238f885e9b7c0c708f624aa29090c21 (diff) | |
download | qemu-134ffcb276be569fcb7531b2266b0df0d2a1db81.zip qemu-134ffcb276be569fcb7531b2266b0df0d2a1db81.tar.gz qemu-134ffcb276be569fcb7531b2266b0df0d2a1db81.tar.bz2 |
target/i386: use higher-precision arithmetic to compute CF
If the operands of the arithmetic instruction fit within a half-register,
it's easiest to use a comparison instruction to compute the carry.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | target/i386/tcg/cc_helper_template.h.inc | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/target/i386/tcg/cc_helper_template.h.inc b/target/i386/tcg/cc_helper_template.h.inc index 8af8b85..628d942 100644 --- a/target/i386/tcg/cc_helper_template.h.inc +++ b/target/i386/tcg/cc_helper_template.h.inc @@ -22,12 +22,17 @@ #if DATA_BITS == 8 #define SUFFIX b #define DATA_TYPE uint8_t +#define WIDER_TYPE uint32_t #elif DATA_BITS == 16 #define SUFFIX w #define DATA_TYPE uint16_t +#define WIDER_TYPE uint32_t #elif DATA_BITS == 32 #define SUFFIX l #define DATA_TYPE uint32_t +#if HOST_LONG_BITS >= 64 +#define WIDER_TYPE uint64_t +#endif #elif DATA_BITS == 64 #define SUFFIX q #define DATA_TYPE uint64_t @@ -62,9 +67,18 @@ static uint32_t glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, DATA_TYPE src3) { uint32_t cf, pf, af, zf, sf, of; + +#ifdef WIDER_TYPE + WIDER_TYPE src13 = (WIDER_TYPE) src1 + (WIDER_TYPE) src3; + DATA_TYPE src2 = dst - src13; + + cf = dst < src13; +#else DATA_TYPE src2 = dst - src1 - src3; cf = (src3 ? dst <= src1 : dst < src1); +#endif + pf = compute_pf(dst); af = (dst ^ src1 ^ src2) & 0x10; zf = (dst == 0) << 6; @@ -76,7 +90,13 @@ static uint32_t glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, DATA_TYPE src3) { +#ifdef WIDER_TYPE + WIDER_TYPE src13 = (WIDER_TYPE) src1 + (WIDER_TYPE) src3; + + return dst < src13; +#else return src3 ? dst <= src1 : dst < src1; +#endif } static uint32_t glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) @@ -104,9 +124,18 @@ static uint32_t glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, DATA_TYPE src3) { uint32_t cf, pf, af, zf, sf, of; + +#ifdef WIDER_TYPE + WIDER_TYPE src23 = (WIDER_TYPE) src2 + (WIDER_TYPE) src3; + DATA_TYPE src1 = dst + src23; + + cf = src1 < src23; +#else DATA_TYPE src1 = dst + src2 + src3; cf = (src3 ? src1 <= src2 : src1 < src2); +#endif + pf = compute_pf(dst); af = (dst ^ src1 ^ src2) & 0x10; zf = (dst == 0) << 6; @@ -118,9 +147,16 @@ static uint32_t glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, DATA_TYPE src3) { +#ifdef WIDER_TYPE + WIDER_TYPE src23 = (WIDER_TYPE) src2 + (WIDER_TYPE) src3; + DATA_TYPE src1 = dst + src23; + + return src1 < src23; +#else DATA_TYPE src1 = dst + src2 + src3; return (src3 ? src1 <= src2 : src1 < src2); +#endif } static uint32_t glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) @@ -258,3 +294,4 @@ static int glue(compute_c_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) #undef DATA_TYPE #undef DATA_MASK #undef SUFFIX +#undef WIDER_TYPE |