[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 13/44] target/ppc: fix setting of CR flags in bcdcfsq
From: |
David Gibson |
Subject: |
[PULL 13/44] target/ppc: fix setting of CR flags in bcdcfsq |
Date: |
Thu, 30 Sep 2021 15:43:55 +1000 |
From: Luis Pires <luis.pires@eldorado.org.br>
According to the ISA, CR should be set based on the source value, and
not on the packed decimal result.
The way this was implemented would cause GT, LT and EQ to be set
incorrectly when the source value was too large and the 31 least
significant digits of the packed decimal result ended up being all zero.
This would happen for source values of +/-10^31, +/-10^32, etc.
The new implementation fixes this and also skips the result calculation
altogether in case of src overflow.
Signed-off-by: Luis Pires <luis.pires@eldorado.org.br>
Message-Id: <20210823150235.35759-1-luis.pires@eldorado.org.br>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
target/ppc/int_helper.c | 61 ++++++++++++++++++++++++++++++++---------
1 file changed, 48 insertions(+), 13 deletions(-)
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index c2d3248d1e..f5dac3aa87 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2480,10 +2480,26 @@ uint32_t helper_bcdctz(ppc_avr_t *r, ppc_avr_t *b,
uint32_t ps)
return cr;
}
+/**
+ * Compare 2 128-bit unsigned integers, passed in as unsigned 64-bit pairs
+ *
+ * Returns:
+ * > 0 if ahi|alo > bhi|blo,
+ * 0 if ahi|alo == bhi|blo,
+ * < 0 if ahi|alo < bhi|blo
+ */
+static inline int ucmp128(uint64_t alo, uint64_t ahi,
+ uint64_t blo, uint64_t bhi)
+{
+ return (ahi == bhi) ?
+ (alo > blo ? 1 : (alo == blo ? 0 : -1)) :
+ (ahi > bhi ? 1 : -1);
+}
+
uint32_t helper_bcdcfsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
{
int i;
- int cr = 0;
+ int cr;
uint64_t lo_value;
uint64_t hi_value;
ppc_avr_t ret = { .u64 = { 0, 0 } };
@@ -2492,28 +2508,47 @@ uint32_t helper_bcdcfsq(ppc_avr_t *r, ppc_avr_t *b,
uint32_t ps)
lo_value = -b->VsrSD(1);
hi_value = ~b->VsrD(0) + !lo_value;
bcd_put_digit(&ret, 0xD, 0);
+
+ cr = CRF_LT;
} else {
lo_value = b->VsrD(1);
hi_value = b->VsrD(0);
bcd_put_digit(&ret, bcd_preferred_sgn(0, ps), 0);
- }
- if (divu128(&lo_value, &hi_value, 1000000000000000ULL) ||
- lo_value > 9999999999999999ULL) {
- cr = CRF_SO;
+ if (hi_value == 0 && lo_value == 0) {
+ cr = CRF_EQ;
+ } else {
+ cr = CRF_GT;
+ }
}
- for (i = 1; i < 16; hi_value /= 10, i++) {
- bcd_put_digit(&ret, hi_value % 10, i);
- }
+ /*
+ * Check src limits: abs(src) <= 10^31 - 1
+ *
+ * 10^31 - 1 = 0x0000007e37be2022 c0914b267fffffff
+ */
+ if (ucmp128(lo_value, hi_value,
+ 0xc0914b267fffffffULL, 0x7e37be2022ULL) > 0) {
+ cr |= CRF_SO;
- for (; i < 32; lo_value /= 10, i++) {
- bcd_put_digit(&ret, lo_value % 10, i);
- }
+ /*
+ * According to the ISA, if src wouldn't fit in the destination
+ * register, the result is undefined.
+ * In that case, we leave r unchanged.
+ */
+ } else {
+ divu128(&lo_value, &hi_value, 1000000000000000ULL);
- cr |= bcd_cmp_zero(&ret);
+ for (i = 1; i < 16; hi_value /= 10, i++) {
+ bcd_put_digit(&ret, hi_value % 10, i);
+ }
- *r = ret;
+ for (; i < 32; lo_value /= 10, i++) {
+ bcd_put_digit(&ret, lo_value % 10, i);
+ }
+
+ *r = ret;
+ }
return cr;
}
--
2.31.1
- [PULL 02/44] host-utils: fix missing zero-extension in divs128, (continued)
- [PULL 02/44] host-utils: fix missing zero-extension in divs128, David Gibson, 2021/09/30
- [PULL 01/44] host-utils: Fix overflow detection in divu128(), David Gibson, 2021/09/30
- [PULL 07/44] ppc/pnv: Remove useless variable, David Gibson, 2021/09/30
- [PULL 04/44] i386/kvm: Replace abs64() with uabs64() from host-utils, David Gibson, 2021/09/30
- [PULL 05/44] ppc/spapr: Add a POWER10 DD2 CPU, David Gibson, 2021/09/30
- [PULL 06/44] ppc/pnv: Add a comment on the "primary-topology-index" property, David Gibson, 2021/09/30
- [PULL 10/44] ppc/pnv: Rename "id" to "quad-id" in PnvQuad, David Gibson, 2021/09/30
- [PULL 12/44] ppc/pnv: Add an assert when calculating the RAM distribution on chips, David Gibson, 2021/09/30
- [PULL 15/44] spapr.c: handle dev->id in spapr_memory_unplug_rollback(), David Gibson, 2021/09/30
- [PULL 11/44] docs/system: ppc: Update the URL for OpenPOWER firmware images, David Gibson, 2021/09/30
- [PULL 13/44] target/ppc: fix setting of CR flags in bcdcfsq,
David Gibson <=
- [PULL 03/44] host-utils: introduce uabs64(), David Gibson, 2021/09/30
- [PULL 14/44] memory_hotplug.c: handle dev->id = NULL in acpi_memory_hotplug_write(), David Gibson, 2021/09/30
- [PULL 16/44] spapr_drc.c: do not error_report() when drc->dev->id == NULL, David Gibson, 2021/09/30
- [PULL 09/44] ppc/xive: Export xive_tctx_word2() helper, David Gibson, 2021/09/30
- [PULL 19/44] spapr: use DEVICE_UNPLUG_GUEST_ERROR to report unplug errors, David Gibson, 2021/09/30
- [PULL 18/44] qapi/qdev.json: add DEVICE_UNPLUG_GUEST_ERROR QAPI event, David Gibson, 2021/09/30
- [PULL 20/44] memory_hotplug.c: send DEVICE_UNPLUG_GUEST_ERROR in acpi_memory_hotplug_write(), David Gibson, 2021/09/30
- [PULL 08/44] ppc/xive: Export priority_to_ipb() helper, David Gibson, 2021/09/30
- [PULL 17/44] qapi/qdev.json: fix DEVICE_DELETED parameters doc, David Gibson, 2021/09/30
- [PULL 25/44] spapr_numa.c: split FORM1 code into helpers, David Gibson, 2021/09/30