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>
This commit is contained in:
parent
24899cdcd2
commit
134ffcb276
@ -22,12 +22,17 @@
|
|||||||
#if DATA_BITS == 8
|
#if DATA_BITS == 8
|
||||||
#define SUFFIX b
|
#define SUFFIX b
|
||||||
#define DATA_TYPE uint8_t
|
#define DATA_TYPE uint8_t
|
||||||
|
#define WIDER_TYPE uint32_t
|
||||||
#elif DATA_BITS == 16
|
#elif DATA_BITS == 16
|
||||||
#define SUFFIX w
|
#define SUFFIX w
|
||||||
#define DATA_TYPE uint16_t
|
#define DATA_TYPE uint16_t
|
||||||
|
#define WIDER_TYPE uint32_t
|
||||||
#elif DATA_BITS == 32
|
#elif DATA_BITS == 32
|
||||||
#define SUFFIX l
|
#define SUFFIX l
|
||||||
#define DATA_TYPE uint32_t
|
#define DATA_TYPE uint32_t
|
||||||
|
#if HOST_LONG_BITS >= 64
|
||||||
|
#define WIDER_TYPE uint64_t
|
||||||
|
#endif
|
||||||
#elif DATA_BITS == 64
|
#elif DATA_BITS == 64
|
||||||
#define SUFFIX q
|
#define SUFFIX q
|
||||||
#define DATA_TYPE uint64_t
|
#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)
|
DATA_TYPE src3)
|
||||||
{
|
{
|
||||||
uint32_t cf, pf, af, zf, sf, of;
|
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;
|
DATA_TYPE src2 = dst - src1 - src3;
|
||||||
|
|
||||||
cf = (src3 ? dst <= src1 : dst < src1);
|
cf = (src3 ? dst <= src1 : dst < src1);
|
||||||
|
#endif
|
||||||
|
|
||||||
pf = compute_pf(dst);
|
pf = compute_pf(dst);
|
||||||
af = (dst ^ src1 ^ src2) & 0x10;
|
af = (dst ^ src1 ^ src2) & 0x10;
|
||||||
zf = (dst == 0) << 6;
|
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,
|
static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
|
||||||
DATA_TYPE src3)
|
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;
|
return src3 ? dst <= src1 : dst < src1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
|
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)
|
DATA_TYPE src3)
|
||||||
{
|
{
|
||||||
uint32_t cf, pf, af, zf, sf, of;
|
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;
|
DATA_TYPE src1 = dst + src2 + src3;
|
||||||
|
|
||||||
cf = (src3 ? src1 <= src2 : src1 < src2);
|
cf = (src3 ? src1 <= src2 : src1 < src2);
|
||||||
|
#endif
|
||||||
|
|
||||||
pf = compute_pf(dst);
|
pf = compute_pf(dst);
|
||||||
af = (dst ^ src1 ^ src2) & 0x10;
|
af = (dst ^ src1 ^ src2) & 0x10;
|
||||||
zf = (dst == 0) << 6;
|
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,
|
static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
|
||||||
DATA_TYPE src3)
|
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;
|
DATA_TYPE src1 = dst + src2 + src3;
|
||||||
|
|
||||||
return (src3 ? src1 <= src2 : src1 < src2);
|
return (src3 ? src1 <= src2 : src1 < src2);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
|
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_TYPE
|
||||||
#undef DATA_MASK
|
#undef DATA_MASK
|
||||||
#undef SUFFIX
|
#undef SUFFIX
|
||||||
|
#undef WIDER_TYPE
|
||||||
|
Loading…
Reference in New Issue
Block a user