diff options
author | Luis Pires <luis.pires@eldorado.org.br> | 2021-10-29 16:24:03 -0300 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2021-11-09 10:32:52 +1100 |
commit | 727385c4e13e1a5a985124a20a2370855141111d (patch) | |
tree | fd30395145becf57fc15c55fb4cb3ed2e6fce81a | |
parent | 8bdb760606dadf6b7454aac84f214bb0f2c80654 (diff) |
libdecnumber: introduce decNumberFrom[U]Int128
This will be used to implement PowerPC's dcffixqq.
Signed-off-by: Luis Pires <luis.pires@eldorado.org.br>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20211029192417.400707-2-luis.pires@eldorado.org.br>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r-- | include/libdecnumber/decNumber.h | 2 | ||||
-rw-r--r-- | libdecnumber/decNumber.c | 36 |
2 files changed, 38 insertions, 0 deletions
diff --git a/include/libdecnumber/decNumber.h b/include/libdecnumber/decNumber.h index aa115fed07..0cf69c7db2 100644 --- a/include/libdecnumber/decNumber.h +++ b/include/libdecnumber/decNumber.h @@ -116,6 +116,8 @@ decNumber * decNumberFromUInt32(decNumber *, uint32_t); decNumber *decNumberFromInt64(decNumber *, int64_t); decNumber *decNumberFromUInt64(decNumber *, uint64_t); + decNumber *decNumberFromInt128(decNumber *, uint64_t, int64_t); + decNumber *decNumberFromUInt128(decNumber *, uint64_t, uint64_t); decNumber * decNumberFromString(decNumber *, const char *, decContext *); char * decNumberToString(const decNumber *, char *); char * decNumberToEngString(const decNumber *, char *); diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c index 1ffe458ad8..d7716ce175 100644 --- a/libdecnumber/decNumber.c +++ b/libdecnumber/decNumber.c @@ -167,6 +167,7 @@ /* ------------------------------------------------------------------ */ #include "qemu/osdep.h" +#include "qemu/host-utils.h" #include "libdecnumber/dconfig.h" #include "libdecnumber/decNumber.h" #include "libdecnumber/decNumberLocal.h" @@ -462,6 +463,41 @@ decNumber *decNumberFromUInt64(decNumber *dn, uint64_t uin) return dn; } /* decNumberFromUInt64 */ +decNumber *decNumberFromInt128(decNumber *dn, uint64_t lo, int64_t hi) +{ + uint64_t unsig_hi = hi; + if (hi < 0) { + if (lo == 0) { + unsig_hi = -unsig_hi; + } else { + unsig_hi = ~unsig_hi; + lo = -lo; + } + } + + decNumberFromUInt128(dn, lo, unsig_hi); + if (hi < 0) { + dn->bits = DECNEG; /* sign needed */ + } + return dn; +} /* decNumberFromInt128 */ + +decNumber *decNumberFromUInt128(decNumber *dn, uint64_t lo, uint64_t hi) +{ + uint64_t rem; + Unit *up; /* work pointer */ + decNumberZero(dn); /* clean */ + if (lo == 0 && hi == 0) { + return dn; /* [or decGetDigits bad call] */ + } + for (up = dn->lsu; hi > 0 || lo > 0; up++) { + rem = divu128(&lo, &hi, DECDPUNMAX + 1); + *up = (Unit)rem; + } + dn->digits = decGetDigits(dn->lsu, up - dn->lsu); + return dn; +} /* decNumberFromUInt128 */ + /* ------------------------------------------------------------------ */ /* to-int64 -- conversion to int64 */ /* */ |