* [Qemu-devel] [PATCH v2 0/7] POWER9 TCG enablements - BCD functions - final part
@ 2016-12-06 19:40 Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 1/7] target-ppc: Implement bcd_is_valid function Jose Ricardo Ziviani
` (6 more replies)
0 siblings, 7 replies; 13+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-06 19:40 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, david, nikunj, bharata
v2:
- bcd[s,sr,us] uses 1 byte for shifting instead of 4 bytes
- left/right functions in host-utils are out of CONFIG_INT128
- fixes overflowing issue in left shift and added a testcase
This serie contains 5 new instructions for POWER9 ISA3.0, left/right shifts for
unsigned quadwords and a small improvement to check whether a bcd value is
valid or not.
bcds.: Decimal signed shift
bcdus.: Decimal unsigned shift
bcdsr.: Decimal shift and round
bcdtrunc.: Decimal signed trucate
bcdtrunc.: Decimal unsigned truncate
Jose Ricardo Ziviani (7):
target-ppc: Implement bcd_is_valid function
target-ppc: Implement unsigned quadword left/right shift and unit
tests
target-ppc: Implement bcds. instruction
target-ppc: Implement bcdus. instruction
target-ppc: Implement bcdsr. instruction
target-ppc: Implement bcdtrunc. instruction
target-ppc: Implement bcdtrunc. instruction
include/qemu/host-utils.h | 43 +++++++
target-ppc/helper.h | 5 +
target-ppc/int_helper.c | 229 +++++++++++++++++++++++++++++++++++-
target-ppc/translate/vmx-impl.inc.c | 16 +++
target-ppc/translate/vmx-ops.inc.c | 13 +-
tests/Makefile.include | 5 +-
tests/test-shift128.c | 98 +++++++++++++++
7 files changed, 399 insertions(+), 10 deletions(-)
create mode 100644 tests/test-shift128.c
--
2.7.4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 1/7] target-ppc: Implement bcd_is_valid function
2016-12-06 19:40 [Qemu-devel] [PATCH v2 0/7] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
@ 2016-12-06 19:40 ` Jose Ricardo Ziviani
2016-12-07 5:48 ` David Gibson
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 2/7] target-ppc: Implement unsigned quadword left/right shift and unit tests Jose Ricardo Ziviani
` (5 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-06 19:40 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, david, nikunj, bharata
A function to check if all digits of a given BCD number is valid is
here presented because more instructions will need to reuse the
same code.
Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
---
target-ppc/int_helper.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index 7030f61..7989b1f 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -2596,6 +2596,24 @@ static void bcd_put_digit(ppc_avr_t *bcd, uint8_t digit, int n)
}
}
+static bool bcd_is_valid(ppc_avr_t *bcd)
+{
+ int i;
+ int invalid = 0;
+
+ if (bcd_get_sgn(bcd) == 0) {
+ return false;
+ }
+
+ for (i = 1; i < 32; i++) {
+ bcd_get_digit(bcd, i, &invalid);
+ if (unlikely(invalid)) {
+ return false;
+ }
+ }
+ return true;
+}
+
static int bcd_cmp_zero(ppc_avr_t *bcd)
{
if (bcd->u64[HI_IDX] == 0 && (bcd->u64[LO_IDX] >> 4) == 0) {
@@ -3013,18 +3031,13 @@ uint32_t helper_bcdcpsgn(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
uint32_t helper_bcdsetsgn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
{
- int i;
- int invalid = 0;
int sgnb = bcd_get_sgn(b);
*r = *b;
bcd_put_digit(r, bcd_preferred_sgn(sgnb, ps), 0);
- for (i = 1; i < 32; i++) {
- bcd_get_digit(b, i, &invalid);
- if (unlikely(invalid)) {
- return CRF_SO;
- }
+ if (bcd_is_valid(b) == false) {
+ return CRF_SO;
}
return bcd_cmp_zero(r);
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 2/7] target-ppc: Implement unsigned quadword left/right shift and unit tests
2016-12-06 19:40 [Qemu-devel] [PATCH v2 0/7] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 1/7] target-ppc: Implement bcd_is_valid function Jose Ricardo Ziviani
@ 2016-12-06 19:40 ` Jose Ricardo Ziviani
2016-12-07 5:41 ` David Gibson
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 3/7] target-ppc: Implement bcds. instruction Jose Ricardo Ziviani
` (4 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-06 19:40 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, david, nikunj, bharata
This commit implements functions to right and left shifts and the
unittest for them. Such functions is needed due to instructions
that requires them.
Today, there is already a right shift implementation in int128.h
but it's for signed numbers.
Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
---
include/qemu/host-utils.h | 43 +++++++++++++++++++++
tests/Makefile.include | 5 ++-
tests/test-shift128.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 145 insertions(+), 1 deletion(-)
create mode 100644 tests/test-shift128.c
diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
index 46187bb..e22d723 100644
--- a/include/qemu/host-utils.h
+++ b/include/qemu/host-utils.h
@@ -516,4 +516,47 @@ static inline uint64_t pow2ceil(uint64_t value)
return 1ULL << (64 - nlz);
}
+static inline void urshift(uint64_t *plow, uint64_t *phigh, uint32_t shift)
+{
+ shift &= 127;
+ uint64_t h = *phigh >> (shift & 63);
+ if (shift == 0) {
+ return;
+ } else if (shift >= 64) {
+ *plow = h;
+ *phigh = 0;
+ } else {
+ *plow = (*plow >> (shift & 63)) | (*phigh << (64 - (shift & 63)));
+ *phigh = h;
+ }
+}
+
+static inline void ulshift(uint64_t *plow, uint64_t *phigh, uint32_t shift,
+ bool *overflow)
+{
+ uint64_t low = *plow;
+ uint64_t high = *phigh;
+
+ if (shift > 127 && (low | high)) {
+ *overflow = true;
+ }
+ shift &= 127;
+
+ if (shift == 0) {
+ return;
+ }
+
+ urshift(&low, &high, 128 - shift);
+ if (low > 0 || high > 0) {
+ *overflow = true;
+ }
+
+ if (shift >= 64) {
+ *phigh = *plow << (shift & 63);
+ *plow = 0;
+ } else {
+ *phigh = (*plow >> (64 - (shift & 63))) | (*phigh << (shift & 63));
+ *plow = *plow << shift;
+ }
+}
#endif
diff --git a/tests/Makefile.include b/tests/Makefile.include
index e98d3b6..89e5e85 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -65,6 +65,8 @@ check-unit-$(CONFIG_POSIX) += tests/test-vmstate$(EXESUF)
endif
check-unit-y += tests/test-cutils$(EXESUF)
gcov-files-test-cutils-y += util/cutils.c
+check-unit-y += tests/test-shift128$(EXESUF)
+gcov-files-test-shift128-y = util/host-utils.c
check-unit-y += tests/test-mul64$(EXESUF)
gcov-files-test-mul64-y = util/host-utils.c
check-unit-y += tests/test-int128$(EXESUF)
@@ -460,7 +462,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
tests/test-opts-visitor.o tests/test-qmp-event.o \
tests/rcutorture.o tests/test-rcu-list.o \
- tests/test-qdist.o \
+ tests/test-qdist.o tests/test-shift128.o \
tests/test-qht.o tests/qht-bench.o tests/test-qht-par.o \
tests/atomic_add-bench.o
@@ -568,6 +570,7 @@ tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marsh
tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
+tests/test-shift128$(EXESUF): tests/test-shift128.o $(test-util-obj-y)
tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y)
tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y)
tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y)
diff --git a/tests/test-shift128.c b/tests/test-shift128.c
new file mode 100644
index 0000000..52be6a2
--- /dev/null
+++ b/tests/test-shift128.c
@@ -0,0 +1,98 @@
+/*
+ * Test unsigned left and right shift
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+
+typedef struct {
+ uint64_t low;
+ uint64_t high;
+ uint64_t rlow;
+ uint64_t rhigh;
+ int32_t shift;
+ bool overflow;
+} test_data;
+
+static const test_data test_ltable[] = {
+ { 1223ULL, 0, 1223ULL, 0, 0, false },
+ { 1ULL, 0, 2ULL, 0, 1, false },
+ { 1ULL, 0, 4ULL, 0, 2, false },
+ { 1ULL, 0, 16ULL, 0, 4, false },
+ { 1ULL, 0, 256ULL, 0, 8, false },
+ { 1ULL, 0, 65536ULL, 0, 16, false },
+ { 1ULL, 0, 2147483648ULL, 0, 31, false },
+ { 1ULL, 0, 35184372088832ULL, 0, 45, false },
+ { 1ULL, 0, 1152921504606846976ULL, 0, 60, false },
+ { 1ULL, 0, 0, 1ULL, 64, false },
+ { 1ULL, 0, 0, 65536ULL, 80, false },
+ { 1ULL, 0, 0, 9223372036854775808ULL, 127, false },
+ { 0ULL, 1, 0, 0, 64, true },
+ { 0x8888888888888888ULL, 0x9999999999999999ULL,
+ 0x8000000000000000ULL, 0x9888888888888888ULL, 60, true },
+ { 0x8888888888888888ULL, 0x9999999999999999ULL,
+ 0, 0x8888888888888888ULL, 64, true },
+ { 0x8ULL, 0, 0, 0x8ULL, 64, false },
+ { 0x8ULL, 0, 0, 0x8000000000000000ULL, 124, false },
+ { 0x1ULL, 0, 0, 0x4000000000000000ULL, 126, false },
+ { 0x1ULL, 0, 0, 0x8000000000000000ULL, 127, false },
+ { 0x1ULL, 0, 0x1ULL, 0, 128, true },
+ { 0, 0, 0ULL, 0, 200, false },
+};
+
+static const test_data test_rtable[] = {
+ { 1223ULL, 0, 1223ULL, 0, 0, false },
+ { 9223372036854775808ULL, 9223372036854775808ULL,
+ 2147483648L, 2147483648ULL, 32, false },
+ { 9223372036854775808ULL, 9223372036854775808ULL,
+ 9223372036854775808ULL, 0, 64, false },
+ { 9223372036854775808ULL, 9223372036854775808ULL,
+ 36028797018963968ULL, 0, 72, false },
+ { 9223372036854775808ULL, 9223372036854775808ULL,
+ 1ULL, 0, 127, false },
+ { 9223372036854775808ULL, 0, 4611686018427387904ULL, 0, 1, false },
+ { 9223372036854775808ULL, 0, 2305843009213693952ULL, 0, 2, false },
+ { 9223372036854775808ULL, 0, 36028797018963968ULL, 0, 8, false },
+ { 9223372036854775808ULL, 0, 140737488355328ULL, 0, 16, false },
+ { 9223372036854775808ULL, 0, 2147483648ULL, 0, 32, false },
+ { 9223372036854775808ULL, 0, 1ULL, 0, 63, false },
+ { 9223372036854775808ULL, 0, 0ULL, 0, 64, false },
+};
+
+static void test_lshift(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test_ltable); ++i) {
+ bool overflow = false;
+ test_data tmp = test_ltable[i];
+ ulshift(&tmp.low, &tmp.high, tmp.shift, &overflow);
+ g_assert_cmpuint(tmp.low, ==, tmp.rlow);
+ g_assert_cmpuint(tmp.high, ==, tmp.rhigh);
+ g_assert_cmpuint(tmp.overflow, ==, overflow);
+ }
+}
+
+static void test_rshift(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test_rtable); ++i) {
+ test_data tmp = test_rtable[i];
+ urshift(&tmp.low, &tmp.high, tmp.shift);
+ g_assert_cmpuint(tmp.low, ==, tmp.rlow);
+ g_assert_cmpuint(tmp.high, ==, tmp.rhigh);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/host-utils/test_lshift", test_lshift);
+ g_test_add_func("/host-utils/test_rshift", test_rshift);
+ return g_test_run();
+}
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 3/7] target-ppc: Implement bcds. instruction
2016-12-06 19:40 [Qemu-devel] [PATCH v2 0/7] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 1/7] target-ppc: Implement bcd_is_valid function Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 2/7] target-ppc: Implement unsigned quadword left/right shift and unit tests Jose Ricardo Ziviani
@ 2016-12-06 19:40 ` Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 4/7] target-ppc: Implement bcdus. instruction Jose Ricardo Ziviani
` (3 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-06 19:40 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, david, nikunj, bharata
bcds.: Decimal shift. Given two registers vra and vrb, this instruction
shift the vrb value by vra bits into the result register.
Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
---
target-ppc/helper.h | 1 +
target-ppc/int_helper.c | 38 +++++++++++++++++++++++++++++++++++++
target-ppc/translate/vmx-impl.inc.c | 3 +++
target-ppc/translate/vmx-ops.inc.c | 3 ++-
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index bc39efb..471a1da 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -392,6 +392,7 @@ DEF_HELPER_3(bcdcfsq, i32, avr, avr, i32)
DEF_HELPER_3(bcdctsq, i32, avr, avr, i32)
DEF_HELPER_4(bcdcpsgn, i32, avr, avr, avr, i32)
DEF_HELPER_3(bcdsetsgn, i32, avr, avr, i32)
+DEF_HELPER_4(bcds, i32, avr, avr, avr, i32)
DEF_HELPER_2(xsadddp, void, env, i32)
DEF_HELPER_2(xssubdp, void, env, i32)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index 7989b1f..854cf3a 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -3043,6 +3043,44 @@ uint32_t helper_bcdsetsgn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
return bcd_cmp_zero(r);
}
+uint32_t helper_bcds(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
+{
+ int cr;
+ int i = 0;
+ bool ox_flag = false;
+ int sgnb = bcd_get_sgn(b);
+ ppc_avr_t ret = *b;
+ ret.u64[LO_IDX] &= ~0xf;
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ int upper = ARRAY_SIZE(a->s8) - 1;
+#else
+ int upper = 0;
+#endif
+
+ if (bcd_is_valid(b) == false) {
+ return CRF_SO;
+ }
+
+ if (a->s8[upper] > 0) {
+ i = (a->s8[upper] > 31) ? 31 : a->s8[upper];
+ ulshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4, &ox_flag);
+ } else {
+ i = (a->s8[upper] < -31) ? 31 : -a->s8[upper];
+ urshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4);
+ }
+ bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0);
+
+ *r = ret;
+
+ cr = bcd_cmp_zero(r);
+ if (unlikely(ox_flag)) {
+ cr |= CRF_SO;
+ }
+
+ return cr;
+}
+
void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
{
int i;
diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c
index e8e527f..84ebb7e 100644
--- a/target-ppc/translate/vmx-impl.inc.c
+++ b/target-ppc/translate/vmx-impl.inc.c
@@ -1016,6 +1016,7 @@ GEN_BCD2(bcdcfsq)
GEN_BCD2(bcdctsq)
GEN_BCD2(bcdsetsgn)
GEN_BCD(bcdcpsgn);
+GEN_BCD(bcds);
static void gen_xpnd04_1(DisasContext *ctx)
{
@@ -1090,6 +1091,8 @@ GEN_VXFORM_DUAL(vsubuhs, PPC_ALTIVEC, PPC_NONE, \
bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
GEN_VXFORM_DUAL(vaddshs, PPC_ALTIVEC, PPC_NONE, \
bcdcpsgn, PPC_NONE, PPC2_ISA300)
+GEN_VXFORM_DUAL(vsubudm, PPC2_ALTIVEC_207, PPC_NONE, \
+ bcds, PPC_NONE, PPC2_ISA300)
static void gen_vsbox(DisasContext *ctx)
{
diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c
index 57dce6e..7b4b009 100644
--- a/target-ppc/translate/vmx-ops.inc.c
+++ b/target-ppc/translate/vmx-ops.inc.c
@@ -62,7 +62,8 @@ GEN_VXFORM_207(vaddudm, 0, 3),
GEN_VXFORM_DUAL(vsububm, bcdadd, 0, 16, PPC_ALTIVEC, PPC_NONE),
GEN_VXFORM_DUAL(vsubuhm, bcdsub, 0, 17, PPC_ALTIVEC, PPC_NONE),
GEN_VXFORM(vsubuwm, 0, 18),
-GEN_VXFORM_207(vsubudm, 0, 19),
+GEN_VXFORM_DUAL(vsubudm, bcds, 0, 19, PPC2_ALTIVEC_207, PPC2_ISA300),
+GEN_VXFORM_300(bcds, 0, 27),
GEN_VXFORM(vmaxub, 1, 0),
GEN_VXFORM(vmaxuh, 1, 1),
GEN_VXFORM(vmaxuw, 1, 2),
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 4/7] target-ppc: Implement bcdus. instruction
2016-12-06 19:40 [Qemu-devel] [PATCH v2 0/7] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
` (2 preceding siblings ...)
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 3/7] target-ppc: Implement bcds. instruction Jose Ricardo Ziviani
@ 2016-12-06 19:40 ` Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 5/7] target-ppc: Implement bcdsr. instruction Jose Ricardo Ziviani
` (2 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-06 19:40 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, david, nikunj, bharata
bcdus.: Decimal unsigned shift. This instruction works like bcds. but
considers only unsigned BCDs (no sign in least meaning 4 bits).
Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
---
target-ppc/helper.h | 1 +
target-ppc/int_helper.c | 43 +++++++++++++++++++++++++++++++++++++
target-ppc/translate/vmx-impl.inc.c | 3 +++
target-ppc/translate/vmx-ops.inc.c | 2 +-
4 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 471a1da..386ea67 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -393,6 +393,7 @@ DEF_HELPER_3(bcdctsq, i32, avr, avr, i32)
DEF_HELPER_4(bcdcpsgn, i32, avr, avr, avr, i32)
DEF_HELPER_3(bcdsetsgn, i32, avr, avr, i32)
DEF_HELPER_4(bcds, i32, avr, avr, avr, i32)
+DEF_HELPER_4(bcdus, i32, avr, avr, avr, i32)
DEF_HELPER_2(xsadddp, void, env, i32)
DEF_HELPER_2(xssubdp, void, env, i32)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index 854cf3a..342fb41 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -3081,6 +3081,49 @@ uint32_t helper_bcds(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
return cr;
}
+uint32_t helper_bcdus(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
+{
+ int cr;
+ int i;
+ int invalid = 0;
+ bool ox_flag = false;
+ ppc_avr_t ret = *b;
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ int upper = ARRAY_SIZE(a->s8) - 1;
+#else
+ int upper = 0;
+#endif
+
+ for (i = 0; i < 32; i++) {
+ bcd_get_digit(b, i, &invalid);
+
+ if (unlikely(invalid)) {
+ return CRF_SO;
+ }
+ }
+
+ if (a->s8[upper] >= 32) {
+ ox_flag = true;
+ ret.u64[LO_IDX] = ret.u64[HI_IDX] = 0;
+ } else if (a->s8[upper] <= -32) {
+ ret.u64[LO_IDX] = ret.u64[HI_IDX] = 0;
+ } else if (a->s8[upper] > 0) {
+ i = a->s8[upper] & 31;
+ ulshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4, &ox_flag);
+ } else {
+ i = (-a->s8[upper]) & 31;
+ urshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4);
+ }
+
+ cr = bcd_cmp_zero(r);
+ if (unlikely(ox_flag)) {
+ cr |= CRF_SO;
+ }
+
+ return cr;
+}
+
void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
{
int i;
diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c
index 84ebb7e..fc54881 100644
--- a/target-ppc/translate/vmx-impl.inc.c
+++ b/target-ppc/translate/vmx-impl.inc.c
@@ -1017,6 +1017,7 @@ GEN_BCD2(bcdctsq)
GEN_BCD2(bcdsetsgn)
GEN_BCD(bcdcpsgn);
GEN_BCD(bcds);
+GEN_BCD(bcdus);
static void gen_xpnd04_1(DisasContext *ctx)
{
@@ -1093,6 +1094,8 @@ GEN_VXFORM_DUAL(vaddshs, PPC_ALTIVEC, PPC_NONE, \
bcdcpsgn, PPC_NONE, PPC2_ISA300)
GEN_VXFORM_DUAL(vsubudm, PPC2_ALTIVEC_207, PPC_NONE, \
bcds, PPC_NONE, PPC2_ISA300)
+GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \
+ bcdus, PPC_NONE, PPC2_ISA300)
static void gen_vsbox(DisasContext *ctx)
{
diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c
index 7b4b009..cdd3abe 100644
--- a/target-ppc/translate/vmx-ops.inc.c
+++ b/target-ppc/translate/vmx-ops.inc.c
@@ -61,7 +61,7 @@ GEN_VXFORM(vadduwm, 0, 2),
GEN_VXFORM_207(vaddudm, 0, 3),
GEN_VXFORM_DUAL(vsububm, bcdadd, 0, 16, PPC_ALTIVEC, PPC_NONE),
GEN_VXFORM_DUAL(vsubuhm, bcdsub, 0, 17, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM(vsubuwm, 0, 18),
+GEN_VXFORM_DUAL(vsubuwm, bcdus, 0, 18, PPC_ALTIVEC, PPC2_ISA300),
GEN_VXFORM_DUAL(vsubudm, bcds, 0, 19, PPC2_ALTIVEC_207, PPC2_ISA300),
GEN_VXFORM_300(bcds, 0, 27),
GEN_VXFORM(vmaxub, 1, 0),
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 5/7] target-ppc: Implement bcdsr. instruction
2016-12-06 19:40 [Qemu-devel] [PATCH v2 0/7] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
` (3 preceding siblings ...)
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 4/7] target-ppc: Implement bcdus. instruction Jose Ricardo Ziviani
@ 2016-12-06 19:40 ` Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 6/7] target-ppc: Implement bcdtrunc. instruction Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 7/7] " Jose Ricardo Ziviani
6 siblings, 0 replies; 13+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-06 19:40 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, david, nikunj, bharata
bcdsr.: Decimal shift and round. This instruction works like bcds.
however, when performing right shift, 1 will be added to the
result if the last digit was >= 5.
Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
---
target-ppc/helper.h | 1 +
target-ppc/int_helper.c | 45 +++++++++++++++++++++++++++++++++++++
target-ppc/translate/vmx-impl.inc.c | 1 +
target-ppc/translate/vmx-ops.inc.c | 2 ++
4 files changed, 49 insertions(+)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 386ea67..d9528eb 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -394,6 +394,7 @@ DEF_HELPER_4(bcdcpsgn, i32, avr, avr, avr, i32)
DEF_HELPER_3(bcdsetsgn, i32, avr, avr, i32)
DEF_HELPER_4(bcds, i32, avr, avr, avr, i32)
DEF_HELPER_4(bcdus, i32, avr, avr, avr, i32)
+DEF_HELPER_4(bcdsr, i32, avr, avr, avr, i32)
DEF_HELPER_2(xsadddp, void, env, i32)
DEF_HELPER_2(xssubdp, void, env, i32)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index 342fb41..cfef25f 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -3124,6 +3124,51 @@ uint32_t helper_bcdus(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
return cr;
}
+uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
+{
+ int cr;
+ int i;
+ int unused = 0;
+ int invalid = 0;
+ bool ox_flag = false;
+ int sgnb = bcd_get_sgn(b);
+ ppc_avr_t ret = *b;
+ ret.u64[LO_IDX] &= ~0xf;
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ ppc_avr_t bcd_one = { .u64 = { 0, 0x10 } };
+ int upper = ARRAY_SIZE(a->s8) - 1;
+#else
+ ppc_avr_t bcd_one = { .u64 = { 0x10, 0 } };
+ int upper = 0;
+#endif
+
+ if (bcd_is_valid(b) == false) {
+ return CRF_SO;
+ }
+
+ if (a->s8[upper] > 0) {
+ i = (a->s8[upper] > 31) ? 31 : a->s8[upper];
+ ulshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4, &ox_flag);
+ } else {
+ i = (a->s8[upper] < -31) ? 31 : -a->s8[upper];
+ urshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4);
+
+ if (bcd_get_digit(&ret, 0, &invalid) >= 5) {
+ bcd_add_mag(&ret, &ret, &bcd_one, &invalid, &unused);
+ }
+ }
+ bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0);
+
+ cr = bcd_cmp_zero(&ret);
+ if (unlikely(ox_flag)) {
+ cr |= CRF_SO;
+ }
+ *r = ret;
+
+ return cr;
+}
+
void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
{
int i;
diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c
index fc54881..451abb5 100644
--- a/target-ppc/translate/vmx-impl.inc.c
+++ b/target-ppc/translate/vmx-impl.inc.c
@@ -1018,6 +1018,7 @@ GEN_BCD2(bcdsetsgn)
GEN_BCD(bcdcpsgn);
GEN_BCD(bcds);
GEN_BCD(bcdus);
+GEN_BCD(bcdsr);
static void gen_xpnd04_1(DisasContext *ctx)
{
diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c
index cdd3abe..fa9c996 100644
--- a/target-ppc/translate/vmx-ops.inc.c
+++ b/target-ppc/translate/vmx-ops.inc.c
@@ -132,6 +132,8 @@ GEN_HANDLER_E_2(vprtybd, 0x4, 0x1, 0x18, 9, 0, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E_2(vprtybq, 0x4, 0x1, 0x18, 10, 0, PPC_NONE, PPC2_ISA300),
GEN_VXFORM_DUAL(vsubcuw, xpnd04_1, 0, 22, PPC_ALTIVEC, PPC_NONE),
+GEN_VXFORM_300(bcdsr, 0, 23),
+GEN_VXFORM_300(bcdsr, 0, 31),
GEN_VXFORM_DUAL(vaddubs, vmul10uq, 0, 8, PPC_ALTIVEC, PPC_NONE),
GEN_VXFORM_DUAL(vadduhs, vmul10euq, 0, 9, PPC_ALTIVEC, PPC_NONE),
GEN_VXFORM(vadduws, 0, 10),
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 6/7] target-ppc: Implement bcdtrunc. instruction
2016-12-06 19:40 [Qemu-devel] [PATCH v2 0/7] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
` (4 preceding siblings ...)
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 5/7] target-ppc: Implement bcdsr. instruction Jose Ricardo Ziviani
@ 2016-12-06 19:40 ` Jose Ricardo Ziviani
2016-12-07 5:47 ` David Gibson
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 7/7] " Jose Ricardo Ziviani
6 siblings, 1 reply; 13+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-06 19:40 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, david, nikunj, bharata
bcdtrunc.: Decimal integer truncate. Given a BCD number in vrb and the
number of bytes to truncate in vra, the return register will have vrb
with such bits truncated.
Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
---
target-ppc/helper.h | 1 +
target-ppc/int_helper.c | 43 +++++++++++++++++++++++++++++++++++++
target-ppc/translate/vmx-impl.inc.c | 5 +++++
target-ppc/translate/vmx-ops.inc.c | 4 ++--
4 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index d9528eb..49965b0 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -395,6 +395,7 @@ DEF_HELPER_3(bcdsetsgn, i32, avr, avr, i32)
DEF_HELPER_4(bcds, i32, avr, avr, avr, i32)
DEF_HELPER_4(bcdus, i32, avr, avr, avr, i32)
DEF_HELPER_4(bcdsr, i32, avr, avr, avr, i32)
+DEF_HELPER_4(bcdtrunc, i32, avr, avr, avr, i32)
DEF_HELPER_2(xsadddp, void, env, i32)
DEF_HELPER_2(xssubdp, void, env, i32)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index cfef25f..faf34c1 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -3169,6 +3169,49 @@ uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
return cr;
}
+uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
+{
+ int i;
+ int cr;
+ int ox_flag;
+ uint8_t digit;
+ uint8_t trunc;
+ int invalid = 0;
+ int sgnb = bcd_get_sgn(b);
+ ppc_avr_t ret = *b;
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ int upper = ARRAY_SIZE(a->u16) - 1;
+#else
+ int upper = 0;
+#endif
+
+ trunc = 32 - (a->u16[upper] & 31);
+ for (i = 1; i < 32; i++) {
+ digit = bcd_get_digit(b, i, &invalid);
+
+ if (unlikely(invalid)) {
+ return CRF_SO;
+ }
+
+ if (i >= trunc) {
+ if (!ox_flag && digit > 0x0) {
+ ox_flag = 1;
+ }
+ bcd_put_digit(&ret, 0, i);
+ }
+ }
+ bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0);
+
+ cr = bcd_cmp_zero(&ret);
+ if (unlikely(ox_flag)) {
+ cr |= CRF_SO;
+ }
+ *r = ret;
+
+ return cr;
+}
+
void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
{
int i;
diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c
index 451abb5..1683f42 100644
--- a/target-ppc/translate/vmx-impl.inc.c
+++ b/target-ppc/translate/vmx-impl.inc.c
@@ -1019,6 +1019,7 @@ GEN_BCD(bcdcpsgn);
GEN_BCD(bcds);
GEN_BCD(bcdus);
GEN_BCD(bcdsr);
+GEN_BCD(bcdtrunc);
static void gen_xpnd04_1(DisasContext *ctx)
{
@@ -1097,6 +1098,10 @@ GEN_VXFORM_DUAL(vsubudm, PPC2_ALTIVEC_207, PPC_NONE, \
bcds, PPC_NONE, PPC2_ISA300)
GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \
bcdus, PPC_NONE, PPC2_ISA300)
+GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
+ bcdtrunc, PPC_NONE, PPC2_ISA300)
+GEN_VXFORM_DUAL(vsubuqm, PPC2_ALTIVEC_207, PPC_NONE, \
+ bcdtrunc, PPC_NONE, PPC2_ISA300)
static void gen_vsbox(DisasContext *ctx)
{
diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c
index fa9c996..e6167a4 100644
--- a/target-ppc/translate/vmx-ops.inc.c
+++ b/target-ppc/translate/vmx-ops.inc.c
@@ -143,14 +143,14 @@ GEN_VXFORM(vaddsws, 0, 14),
GEN_VXFORM_DUAL(vsububs, bcdadd, 0, 24, PPC_ALTIVEC, PPC_NONE),
GEN_VXFORM_DUAL(vsubuhs, bcdsub, 0, 25, PPC_ALTIVEC, PPC_NONE),
GEN_VXFORM(vsubuws, 0, 26),
-GEN_VXFORM(vsubsbs, 0, 28),
+GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_NONE, PPC2_ISA300),
GEN_VXFORM(vsubshs, 0, 29),
GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
GEN_VXFORM_207(vadduqm, 0, 4),
GEN_VXFORM_207(vaddcuq, 0, 5),
GEN_VXFORM_DUAL(vaddeuqm, vaddecuq, 30, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
-GEN_VXFORM_207(vsubuqm, 0, 20),
GEN_VXFORM_207(vsubcuq, 0, 21),
+GEN_VXFORM_DUAL(vsubuqm, bcdtrunc, 0, 20, PPC2_ALTIVEC_207, PPC2_ISA300),
GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
GEN_VXFORM(vrlb, 2, 0),
GEN_VXFORM(vrlh, 2, 1),
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 7/7] target-ppc: Implement bcdtrunc. instruction
2016-12-06 19:40 [Qemu-devel] [PATCH v2 0/7] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
` (5 preceding siblings ...)
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 6/7] target-ppc: Implement bcdtrunc. instruction Jose Ricardo Ziviani
@ 2016-12-06 19:40 ` Jose Ricardo Ziviani
2016-12-07 5:48 ` David Gibson
6 siblings, 1 reply; 13+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-06 19:40 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, david, nikunj, bharata
bcdutrunc. Decimal unsigned truncate. Works like bcdtrunc. with
unsigned BCD numbers.
Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
---
target-ppc/helper.h | 1 +
target-ppc/int_helper.c | 39 +++++++++++++++++++++++++++++++++++++
target-ppc/translate/vmx-impl.inc.c | 4 ++++
target-ppc/translate/vmx-ops.inc.c | 2 +-
4 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 49965b0..52a2707 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -396,6 +396,7 @@ DEF_HELPER_4(bcds, i32, avr, avr, avr, i32)
DEF_HELPER_4(bcdus, i32, avr, avr, avr, i32)
DEF_HELPER_4(bcdsr, i32, avr, avr, avr, i32)
DEF_HELPER_4(bcdtrunc, i32, avr, avr, avr, i32)
+DEF_HELPER_4(bcdutrunc, i32, avr, avr, avr, i32)
DEF_HELPER_2(xsadddp, void, env, i32)
DEF_HELPER_2(xssubdp, void, env, i32)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index faf34c1..6167f52 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -3212,6 +3212,45 @@ uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
return cr;
}
+uint32_t helper_bcdutrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
+{
+ int i;
+ uint8_t digit;
+ uint8_t trunc;
+ int ox_flag = 0;
+ int invalid = 0;
+ ppc_avr_t ret = *b;
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ int upper = ARRAY_SIZE(a->u16) - 1;
+#else
+ int upper = 0;
+#endif
+
+ trunc = 32 - (a->u16[upper] % 33);
+ for (i = 0; i < 32; i++) {
+ digit = bcd_get_digit(b, i, &invalid);
+
+ if (unlikely(invalid)) {
+ return CRF_SO;
+ }
+
+ if (i >= trunc) {
+ if (unlikely(!ox_flag && digit > 0x0)) {
+ ox_flag = 1;
+ }
+ bcd_put_digit(&ret, 0, i);
+ }
+ }
+
+ *r = ret;
+ if (r->u64[HI_IDX] == 0 && r->u64[LO_IDX] == 0) {
+ return (ox_flag) ? CRF_SO | CRF_EQ : CRF_EQ;
+ } else {
+ return (ox_flag) ? CRF_SO | CRF_GT : CRF_GT;
+ }
+}
+
void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
{
int i;
diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c
index 1683f42..3cb6fc2 100644
--- a/target-ppc/translate/vmx-impl.inc.c
+++ b/target-ppc/translate/vmx-impl.inc.c
@@ -1020,6 +1020,7 @@ GEN_BCD(bcds);
GEN_BCD(bcdus);
GEN_BCD(bcdsr);
GEN_BCD(bcdtrunc);
+GEN_BCD(bcdutrunc);
static void gen_xpnd04_1(DisasContext *ctx)
{
@@ -1102,6 +1103,9 @@ GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
bcdtrunc, PPC_NONE, PPC2_ISA300)
GEN_VXFORM_DUAL(vsubuqm, PPC2_ALTIVEC_207, PPC_NONE, \
bcdtrunc, PPC_NONE, PPC2_ISA300)
+GEN_VXFORM_DUAL(vsubcuq, PPC2_ALTIVEC_207, PPC_NONE, \
+ bcdutrunc, PPC_NONE, PPC2_ISA300)
+
static void gen_vsbox(DisasContext *ctx)
{
diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c
index e6167a4..139f80c 100644
--- a/target-ppc/translate/vmx-ops.inc.c
+++ b/target-ppc/translate/vmx-ops.inc.c
@@ -149,8 +149,8 @@ GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
GEN_VXFORM_207(vadduqm, 0, 4),
GEN_VXFORM_207(vaddcuq, 0, 5),
GEN_VXFORM_DUAL(vaddeuqm, vaddecuq, 30, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
-GEN_VXFORM_207(vsubcuq, 0, 21),
GEN_VXFORM_DUAL(vsubuqm, bcdtrunc, 0, 20, PPC2_ALTIVEC_207, PPC2_ISA300),
+GEN_VXFORM_DUAL(vsubcuq, bcdutrunc, 0, 21, PPC2_ALTIVEC_207, PPC2_ISA300),
GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
GEN_VXFORM(vrlb, 2, 0),
GEN_VXFORM(vrlh, 2, 1),
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/7] target-ppc: Implement unsigned quadword left/right shift and unit tests
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 2/7] target-ppc: Implement unsigned quadword left/right shift and unit tests Jose Ricardo Ziviani
@ 2016-12-07 5:41 ` David Gibson
2016-12-08 0:24 ` [Qemu-devel] [Qemu-ppc] " joserz
0 siblings, 1 reply; 13+ messages in thread
From: David Gibson @ 2016-12-07 5:41 UTC (permalink / raw)
To: Jose Ricardo Ziviani; +Cc: qemu-ppc, qemu-devel, nikunj, bharata
[-- Attachment #1: Type: text/plain, Size: 7962 bytes --]
On Tue, Dec 06, 2016 at 05:40:05PM -0200, Jose Ricardo Ziviani wrote:
> This commit implements functions to right and left shifts and the
> unittest for them. Such functions is needed due to instructions
> that requires them.
>
> Today, there is already a right shift implementation in int128.h
> but it's for signed numbers.
>
> Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
> ---
> include/qemu/host-utils.h | 43 +++++++++++++++++++++
> tests/Makefile.include | 5 ++-
> tests/test-shift128.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 145 insertions(+), 1 deletion(-)
> create mode 100644 tests/test-shift128.c
>
> diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
> index 46187bb..e22d723 100644
> --- a/include/qemu/host-utils.h
> +++ b/include/qemu/host-utils.h
> @@ -516,4 +516,47 @@ static inline uint64_t pow2ceil(uint64_t value)
> return 1ULL << (64 - nlz);
> }
>
> +static inline void urshift(uint64_t *plow, uint64_t *phigh, uint32_t shift)
These are complicated enough that they probably shouldn't be inlines.
> +{
> + shift &= 127;
> + uint64_t h = *phigh >> (shift & 63);
> + if (shift == 0) {
> + return;
> + } else if (shift >= 64) {
> + *plow = h;
> + *phigh = 0;
> + } else {
> + *plow = (*plow >> (shift & 63)) | (*phigh << (64 - (shift & 63)));
> + *phigh = h;
> + }
> +}
> +
> +static inline void ulshift(uint64_t *plow, uint64_t *phigh, uint32_t shift,
> + bool *overflow)
> +{
> + uint64_t low = *plow;
> + uint64_t high = *phigh;
> +
> + if (shift > 127 && (low | high)) {
> + *overflow = true;
> + }
> + shift &= 127;
> +
> + if (shift == 0) {
> + return;
> + }
> +
> + urshift(&low, &high, 128 - shift);
> + if (low > 0 || high > 0) {
> + *overflow = true;
> + }
> +
> + if (shift >= 64) {
> + *phigh = *plow << (shift & 63);
> + *plow = 0;
> + } else {
> + *phigh = (*plow >> (64 - (shift & 63))) | (*phigh << (shift & 63));
> + *plow = *plow << shift;
> + }
> +}
> #endif
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index e98d3b6..89e5e85 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -65,6 +65,8 @@ check-unit-$(CONFIG_POSIX) += tests/test-vmstate$(EXESUF)
> endif
> check-unit-y += tests/test-cutils$(EXESUF)
> gcov-files-test-cutils-y += util/cutils.c
> +check-unit-y += tests/test-shift128$(EXESUF)
> +gcov-files-test-shift128-y = util/host-utils.c
> check-unit-y += tests/test-mul64$(EXESUF)
> gcov-files-test-mul64-y = util/host-utils.c
> check-unit-y += tests/test-int128$(EXESUF)
> @@ -460,7 +462,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
> tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
> tests/test-opts-visitor.o tests/test-qmp-event.o \
> tests/rcutorture.o tests/test-rcu-list.o \
> - tests/test-qdist.o \
> + tests/test-qdist.o tests/test-shift128.o \
> tests/test-qht.o tests/qht-bench.o tests/test-qht-par.o \
> tests/atomic_add-bench.o
>
> @@ -568,6 +570,7 @@ tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marsh
> tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
> tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
>
> +tests/test-shift128$(EXESUF): tests/test-shift128.o $(test-util-obj-y)
> tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y)
> tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y)
> tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y)
> diff --git a/tests/test-shift128.c b/tests/test-shift128.c
> new file mode 100644
> index 0000000..52be6a2
> --- /dev/null
> +++ b/tests/test-shift128.c
> @@ -0,0 +1,98 @@
> +/*
> + * Test unsigned left and right shift
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2 or later.
> + * See the COPYING.LIB file in the top-level directory.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/host-utils.h"
> +
> +typedef struct {
> + uint64_t low;
> + uint64_t high;
> + uint64_t rlow;
> + uint64_t rhigh;
> + int32_t shift;
> + bool overflow;
> +} test_data;
> +
> +static const test_data test_ltable[] = {
> + { 1223ULL, 0, 1223ULL, 0, 0, false },
> + { 1ULL, 0, 2ULL, 0, 1, false },
> + { 1ULL, 0, 4ULL, 0, 2, false },
> + { 1ULL, 0, 16ULL, 0, 4, false },
> + { 1ULL, 0, 256ULL, 0, 8, false },
> + { 1ULL, 0, 65536ULL, 0, 16, false },
> + { 1ULL, 0, 2147483648ULL, 0, 31, false },
> + { 1ULL, 0, 35184372088832ULL, 0, 45, false },
> + { 1ULL, 0, 1152921504606846976ULL, 0, 60, false },
> + { 1ULL, 0, 0, 1ULL, 64, false },
> + { 1ULL, 0, 0, 65536ULL, 80, false },
> + { 1ULL, 0, 0, 9223372036854775808ULL, 127, false },
> + { 0ULL, 1, 0, 0, 64, true },
> + { 0x8888888888888888ULL, 0x9999999999999999ULL,
> + 0x8000000000000000ULL, 0x9888888888888888ULL, 60, true },
> + { 0x8888888888888888ULL, 0x9999999999999999ULL,
> + 0, 0x8888888888888888ULL, 64, true },
> + { 0x8ULL, 0, 0, 0x8ULL, 64, false },
> + { 0x8ULL, 0, 0, 0x8000000000000000ULL, 124, false },
> + { 0x1ULL, 0, 0, 0x4000000000000000ULL, 126, false },
> + { 0x1ULL, 0, 0, 0x8000000000000000ULL, 127, false },
> + { 0x1ULL, 0, 0x1ULL, 0, 128, true },
> + { 0, 0, 0ULL, 0, 200, false },
> +};
> +
> +static const test_data test_rtable[] = {
> + { 1223ULL, 0, 1223ULL, 0, 0, false },
> + { 9223372036854775808ULL, 9223372036854775808ULL,
> + 2147483648L, 2147483648ULL, 32, false },
> + { 9223372036854775808ULL, 9223372036854775808ULL,
> + 9223372036854775808ULL, 0, 64, false },
> + { 9223372036854775808ULL, 9223372036854775808ULL,
> + 36028797018963968ULL, 0, 72, false },
> + { 9223372036854775808ULL, 9223372036854775808ULL,
> + 1ULL, 0, 127, false },
> + { 9223372036854775808ULL, 0, 4611686018427387904ULL, 0, 1, false },
> + { 9223372036854775808ULL, 0, 2305843009213693952ULL, 0, 2, false },
> + { 9223372036854775808ULL, 0, 36028797018963968ULL, 0, 8, false },
> + { 9223372036854775808ULL, 0, 140737488355328ULL, 0, 16, false },
> + { 9223372036854775808ULL, 0, 2147483648ULL, 0, 32, false },
> + { 9223372036854775808ULL, 0, 1ULL, 0, 63, false },
> + { 9223372036854775808ULL, 0, 0ULL, 0, 64, false },
> +};
> +
> +static void test_lshift(void)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(test_ltable); ++i) {
> + bool overflow = false;
> + test_data tmp = test_ltable[i];
> + ulshift(&tmp.low, &tmp.high, tmp.shift, &overflow);
> + g_assert_cmpuint(tmp.low, ==, tmp.rlow);
> + g_assert_cmpuint(tmp.high, ==, tmp.rhigh);
> + g_assert_cmpuint(tmp.overflow, ==, overflow);
> + }
> +}
> +
> +static void test_rshift(void)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(test_rtable); ++i) {
> + test_data tmp = test_rtable[i];
> + urshift(&tmp.low, &tmp.high, tmp.shift);
> + g_assert_cmpuint(tmp.low, ==, tmp.rlow);
> + g_assert_cmpuint(tmp.high, ==, tmp.rhigh);
> + }
> +}
> +
> +int main(int argc, char **argv)
> +{
> + g_test_init(&argc, &argv, NULL);
> + g_test_add_func("/host-utils/test_lshift", test_lshift);
> + g_test_add_func("/host-utils/test_rshift", test_rshift);
> + return g_test_run();
> +}
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 6/7] target-ppc: Implement bcdtrunc. instruction
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 6/7] target-ppc: Implement bcdtrunc. instruction Jose Ricardo Ziviani
@ 2016-12-07 5:47 ` David Gibson
0 siblings, 0 replies; 13+ messages in thread
From: David Gibson @ 2016-12-07 5:47 UTC (permalink / raw)
To: Jose Ricardo Ziviani; +Cc: qemu-ppc, qemu-devel, nikunj, bharata
[-- Attachment #1: Type: text/plain, Size: 4842 bytes --]
On Tue, Dec 06, 2016 at 05:40:09PM -0200, Jose Ricardo Ziviani wrote:
> bcdtrunc.: Decimal integer truncate. Given a BCD number in vrb and the
> number of bytes to truncate in vra, the return register will have vrb
> with such bits truncated.
>
> Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
> ---
> target-ppc/helper.h | 1 +
> target-ppc/int_helper.c | 43 +++++++++++++++++++++++++++++++++++++
> target-ppc/translate/vmx-impl.inc.c | 5 +++++
> target-ppc/translate/vmx-ops.inc.c | 4 ++--
> 4 files changed, 51 insertions(+), 2 deletions(-)
>
> diff --git a/target-ppc/helper.h b/target-ppc/helper.h
> index d9528eb..49965b0 100644
> --- a/target-ppc/helper.h
> +++ b/target-ppc/helper.h
> @@ -395,6 +395,7 @@ DEF_HELPER_3(bcdsetsgn, i32, avr, avr, i32)
> DEF_HELPER_4(bcds, i32, avr, avr, avr, i32)
> DEF_HELPER_4(bcdus, i32, avr, avr, avr, i32)
> DEF_HELPER_4(bcdsr, i32, avr, avr, avr, i32)
> +DEF_HELPER_4(bcdtrunc, i32, avr, avr, avr, i32)
>
> DEF_HELPER_2(xsadddp, void, env, i32)
> DEF_HELPER_2(xssubdp, void, env, i32)
> diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
> index cfef25f..faf34c1 100644
> --- a/target-ppc/int_helper.c
> +++ b/target-ppc/int_helper.c
> @@ -3169,6 +3169,49 @@ uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
> return cr;
> }
>
> +uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
> +{
> + int i;
> + int cr;
> + int ox_flag;
> + uint8_t digit;
> + uint8_t trunc;
> + int invalid = 0;
> + int sgnb = bcd_get_sgn(b);
> + ppc_avr_t ret = *b;
> +
> +#if defined(HOST_WORDS_BIGENDIAN)
> + int upper = ARRAY_SIZE(a->u16) - 1;
> +#else
> + int upper = 0;
> +#endif
> +
> + trunc = 32 - (a->u16[upper] & 31);
> + for (i = 1; i < 32; i++) {
> + digit = bcd_get_digit(b, i, &invalid);
> +
> + if (unlikely(invalid)) {
> + return CRF_SO;
> + }
> +
> + if (i >= trunc) {
> + if (!ox_flag && digit > 0x0) {
> + ox_flag = 1;
> + }
> + bcd_put_digit(&ret, 0, i);
> + }
> + }
You should be able to do this by generating a couple of masks and
bitwise ands, rather than having to loop through all the digis.
> + bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0);
> +
> + cr = bcd_cmp_zero(&ret);
> + if (unlikely(ox_flag)) {
> + cr |= CRF_SO;
> + }
> + *r = ret;
> +
> + return cr;
> +}
> +
> void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
> {
> int i;
> diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c
> index 451abb5..1683f42 100644
> --- a/target-ppc/translate/vmx-impl.inc.c
> +++ b/target-ppc/translate/vmx-impl.inc.c
> @@ -1019,6 +1019,7 @@ GEN_BCD(bcdcpsgn);
> GEN_BCD(bcds);
> GEN_BCD(bcdus);
> GEN_BCD(bcdsr);
> +GEN_BCD(bcdtrunc);
>
> static void gen_xpnd04_1(DisasContext *ctx)
> {
> @@ -1097,6 +1098,10 @@ GEN_VXFORM_DUAL(vsubudm, PPC2_ALTIVEC_207, PPC_NONE, \
> bcds, PPC_NONE, PPC2_ISA300)
> GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \
> bcdus, PPC_NONE, PPC2_ISA300)
> +GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
> + bcdtrunc, PPC_NONE, PPC2_ISA300)
> +GEN_VXFORM_DUAL(vsubuqm, PPC2_ALTIVEC_207, PPC_NONE, \
> + bcdtrunc, PPC_NONE, PPC2_ISA300)
>
> static void gen_vsbox(DisasContext *ctx)
> {
> diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c
> index fa9c996..e6167a4 100644
> --- a/target-ppc/translate/vmx-ops.inc.c
> +++ b/target-ppc/translate/vmx-ops.inc.c
> @@ -143,14 +143,14 @@ GEN_VXFORM(vaddsws, 0, 14),
> GEN_VXFORM_DUAL(vsububs, bcdadd, 0, 24, PPC_ALTIVEC, PPC_NONE),
> GEN_VXFORM_DUAL(vsubuhs, bcdsub, 0, 25, PPC_ALTIVEC, PPC_NONE),
> GEN_VXFORM(vsubuws, 0, 26),
> -GEN_VXFORM(vsubsbs, 0, 28),
> +GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_NONE, PPC2_ISA300),
> GEN_VXFORM(vsubshs, 0, 29),
> GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
> GEN_VXFORM_207(vadduqm, 0, 4),
> GEN_VXFORM_207(vaddcuq, 0, 5),
> GEN_VXFORM_DUAL(vaddeuqm, vaddecuq, 30, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
> -GEN_VXFORM_207(vsubuqm, 0, 20),
> GEN_VXFORM_207(vsubcuq, 0, 21),
> +GEN_VXFORM_DUAL(vsubuqm, bcdtrunc, 0, 20, PPC2_ALTIVEC_207, PPC2_ISA300),
> GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
> GEN_VXFORM(vrlb, 2, 0),
> GEN_VXFORM(vrlh, 2, 1),
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 7/7] target-ppc: Implement bcdtrunc. instruction
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 7/7] " Jose Ricardo Ziviani
@ 2016-12-07 5:48 ` David Gibson
0 siblings, 0 replies; 13+ messages in thread
From: David Gibson @ 2016-12-07 5:48 UTC (permalink / raw)
To: Jose Ricardo Ziviani; +Cc: qemu-ppc, qemu-devel, nikunj, bharata
[-- Attachment #1: Type: text/plain, Size: 4335 bytes --]
On Tue, Dec 06, 2016 at 05:40:10PM -0200, Jose Ricardo Ziviani wrote:
> bcdutrunc. Decimal unsigned truncate. Works like bcdtrunc. with
> unsigned BCD numbers.
>
> Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
Short description (subject line) says 'bcdtrunc.' instead of
'bcdutrunc'.
Also same comment as previous patch.
> ---
> target-ppc/helper.h | 1 +
> target-ppc/int_helper.c | 39 +++++++++++++++++++++++++++++++++++++
> target-ppc/translate/vmx-impl.inc.c | 4 ++++
> target-ppc/translate/vmx-ops.inc.c | 2 +-
> 4 files changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/target-ppc/helper.h b/target-ppc/helper.h
> index 49965b0..52a2707 100644
> --- a/target-ppc/helper.h
> +++ b/target-ppc/helper.h
> @@ -396,6 +396,7 @@ DEF_HELPER_4(bcds, i32, avr, avr, avr, i32)
> DEF_HELPER_4(bcdus, i32, avr, avr, avr, i32)
> DEF_HELPER_4(bcdsr, i32, avr, avr, avr, i32)
> DEF_HELPER_4(bcdtrunc, i32, avr, avr, avr, i32)
> +DEF_HELPER_4(bcdutrunc, i32, avr, avr, avr, i32)
>
> DEF_HELPER_2(xsadddp, void, env, i32)
> DEF_HELPER_2(xssubdp, void, env, i32)
> diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
> index faf34c1..6167f52 100644
> --- a/target-ppc/int_helper.c
> +++ b/target-ppc/int_helper.c
> @@ -3212,6 +3212,45 @@ uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
> return cr;
> }
>
> +uint32_t helper_bcdutrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
> +{
> + int i;
> + uint8_t digit;
> + uint8_t trunc;
> + int ox_flag = 0;
> + int invalid = 0;
> + ppc_avr_t ret = *b;
> +
> +#if defined(HOST_WORDS_BIGENDIAN)
> + int upper = ARRAY_SIZE(a->u16) - 1;
> +#else
> + int upper = 0;
> +#endif
> +
> + trunc = 32 - (a->u16[upper] % 33);
> + for (i = 0; i < 32; i++) {
> + digit = bcd_get_digit(b, i, &invalid);
> +
> + if (unlikely(invalid)) {
> + return CRF_SO;
> + }
> +
> + if (i >= trunc) {
> + if (unlikely(!ox_flag && digit > 0x0)) {
> + ox_flag = 1;
> + }
> + bcd_put_digit(&ret, 0, i);
> + }
> + }
> +
> + *r = ret;
> + if (r->u64[HI_IDX] == 0 && r->u64[LO_IDX] == 0) {
> + return (ox_flag) ? CRF_SO | CRF_EQ : CRF_EQ;
> + } else {
> + return (ox_flag) ? CRF_SO | CRF_GT : CRF_GT;
> + }
> +}
> +
> void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
> {
> int i;
> diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c
> index 1683f42..3cb6fc2 100644
> --- a/target-ppc/translate/vmx-impl.inc.c
> +++ b/target-ppc/translate/vmx-impl.inc.c
> @@ -1020,6 +1020,7 @@ GEN_BCD(bcds);
> GEN_BCD(bcdus);
> GEN_BCD(bcdsr);
> GEN_BCD(bcdtrunc);
> +GEN_BCD(bcdutrunc);
>
> static void gen_xpnd04_1(DisasContext *ctx)
> {
> @@ -1102,6 +1103,9 @@ GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
> bcdtrunc, PPC_NONE, PPC2_ISA300)
> GEN_VXFORM_DUAL(vsubuqm, PPC2_ALTIVEC_207, PPC_NONE, \
> bcdtrunc, PPC_NONE, PPC2_ISA300)
> +GEN_VXFORM_DUAL(vsubcuq, PPC2_ALTIVEC_207, PPC_NONE, \
> + bcdutrunc, PPC_NONE, PPC2_ISA300)
> +
>
> static void gen_vsbox(DisasContext *ctx)
> {
> diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c
> index e6167a4..139f80c 100644
> --- a/target-ppc/translate/vmx-ops.inc.c
> +++ b/target-ppc/translate/vmx-ops.inc.c
> @@ -149,8 +149,8 @@ GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
> GEN_VXFORM_207(vadduqm, 0, 4),
> GEN_VXFORM_207(vaddcuq, 0, 5),
> GEN_VXFORM_DUAL(vaddeuqm, vaddecuq, 30, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
> -GEN_VXFORM_207(vsubcuq, 0, 21),
> GEN_VXFORM_DUAL(vsubuqm, bcdtrunc, 0, 20, PPC2_ALTIVEC_207, PPC2_ISA300),
> +GEN_VXFORM_DUAL(vsubcuq, bcdutrunc, 0, 21, PPC2_ALTIVEC_207, PPC2_ISA300),
> GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
> GEN_VXFORM(vrlb, 2, 0),
> GEN_VXFORM(vrlh, 2, 1),
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/7] target-ppc: Implement bcd_is_valid function
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 1/7] target-ppc: Implement bcd_is_valid function Jose Ricardo Ziviani
@ 2016-12-07 5:48 ` David Gibson
0 siblings, 0 replies; 13+ messages in thread
From: David Gibson @ 2016-12-07 5:48 UTC (permalink / raw)
To: Jose Ricardo Ziviani; +Cc: qemu-ppc, qemu-devel, nikunj, bharata
[-- Attachment #1: Type: text/plain, Size: 2094 bytes --]
On Tue, Dec 06, 2016 at 05:40:04PM -0200, Jose Ricardo Ziviani wrote:
> A function to check if all digits of a given BCD number is valid is
> here presented because more instructions will need to reuse the
> same code.
>
> Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
I've applied this patch to ppc-for-2.9, the rest still have comments
on them.
> ---
> target-ppc/int_helper.c | 27 ++++++++++++++++++++-------
> 1 file changed, 20 insertions(+), 7 deletions(-)
>
> diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
> index 7030f61..7989b1f 100644
> --- a/target-ppc/int_helper.c
> +++ b/target-ppc/int_helper.c
> @@ -2596,6 +2596,24 @@ static void bcd_put_digit(ppc_avr_t *bcd, uint8_t digit, int n)
> }
> }
>
> +static bool bcd_is_valid(ppc_avr_t *bcd)
> +{
> + int i;
> + int invalid = 0;
> +
> + if (bcd_get_sgn(bcd) == 0) {
> + return false;
> + }
> +
> + for (i = 1; i < 32; i++) {
> + bcd_get_digit(bcd, i, &invalid);
> + if (unlikely(invalid)) {
> + return false;
> + }
> + }
> + return true;
> +}
> +
> static int bcd_cmp_zero(ppc_avr_t *bcd)
> {
> if (bcd->u64[HI_IDX] == 0 && (bcd->u64[LO_IDX] >> 4) == 0) {
> @@ -3013,18 +3031,13 @@ uint32_t helper_bcdcpsgn(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
>
> uint32_t helper_bcdsetsgn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
> {
> - int i;
> - int invalid = 0;
> int sgnb = bcd_get_sgn(b);
>
> *r = *b;
> bcd_put_digit(r, bcd_preferred_sgn(sgnb, ps), 0);
>
> - for (i = 1; i < 32; i++) {
> - bcd_get_digit(b, i, &invalid);
> - if (unlikely(invalid)) {
> - return CRF_SO;
> - }
> + if (bcd_is_valid(b) == false) {
> + return CRF_SO;
> }
>
> return bcd_cmp_zero(r);
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [Qemu-ppc] [PATCH v2 2/7] target-ppc: Implement unsigned quadword left/right shift and unit tests
2016-12-07 5:41 ` David Gibson
@ 2016-12-08 0:24 ` joserz
0 siblings, 0 replies; 13+ messages in thread
From: joserz @ 2016-12-08 0:24 UTC (permalink / raw)
To: David Gibson; +Cc: qemu-ppc, qemu-devel, bharata
On Wed, Dec 07, 2016 at 04:41:53PM +1100, David Gibson wrote:
> On Tue, Dec 06, 2016 at 05:40:05PM -0200, Jose Ricardo Ziviani wrote:
> > This commit implements functions to right and left shifts and the
> > unittest for them. Such functions is needed due to instructions
> > that requires them.
> >
> > Today, there is already a right shift implementation in int128.h
> > but it's for signed numbers.
> >
> > Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
> > ---
> > include/qemu/host-utils.h | 43 +++++++++++++++++++++
> > tests/Makefile.include | 5 ++-
> > tests/test-shift128.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 145 insertions(+), 1 deletion(-)
> > create mode 100644 tests/test-shift128.c
> >
> > diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
> > index 46187bb..e22d723 100644
> > --- a/include/qemu/host-utils.h
> > +++ b/include/qemu/host-utils.h
> > @@ -516,4 +516,47 @@ static inline uint64_t pow2ceil(uint64_t value)
> > return 1ULL << (64 - nlz);
> > }
> >
> > +static inline void urshift(uint64_t *plow, uint64_t *phigh, uint32_t shift)
>
> These are complicated enough that they probably shouldn't be inlines.
I'm only allowed to implement inline functions in header, otherwise
I get "error: no previous prototype for ‘ulshift’
[-Werror=missing-prototypes]"
But host-utils.c is compiled only if CONFIG_INT128 is false:
util-obj-$(call lnot,$(CONFIG_INT128)) += host-utils.o
Is that ok for you if I remove this condition from the Makefile and put
the #ifdef in .c, to guard the existing functions and put mine after it?
Thanks
>
> > +{
> > + shift &= 127;
> > + uint64_t h = *phigh >> (shift & 63);
> > + if (shift == 0) {
> > + return;
> > + } else if (shift >= 64) {
> > + *plow = h;
> > + *phigh = 0;
> > + } else {
> > + *plow = (*plow >> (shift & 63)) | (*phigh << (64 - (shift & 63)));
> > + *phigh = h;
> > + }
> > +}
> > +
> > +static inline void ulshift(uint64_t *plow, uint64_t *phigh, uint32_t shift,
> > + bool *overflow)
> > +{
> > + uint64_t low = *plow;
> > + uint64_t high = *phigh;
> > +
> > + if (shift > 127 && (low | high)) {
> > + *overflow = true;
> > + }
> > + shift &= 127;
> > +
> > + if (shift == 0) {
> > + return;
> > + }
> > +
> > + urshift(&low, &high, 128 - shift);
> > + if (low > 0 || high > 0) {
> > + *overflow = true;
> > + }
> > +
> > + if (shift >= 64) {
> > + *phigh = *plow << (shift & 63);
> > + *plow = 0;
> > + } else {
> > + *phigh = (*plow >> (64 - (shift & 63))) | (*phigh << (shift & 63));
> > + *plow = *plow << shift;
> > + }
> > +}
> > #endif
> > diff --git a/tests/Makefile.include b/tests/Makefile.include
> > index e98d3b6..89e5e85 100644
> > --- a/tests/Makefile.include
> > +++ b/tests/Makefile.include
> > @@ -65,6 +65,8 @@ check-unit-$(CONFIG_POSIX) += tests/test-vmstate$(EXESUF)
> > endif
> > check-unit-y += tests/test-cutils$(EXESUF)
> > gcov-files-test-cutils-y += util/cutils.c
> > +check-unit-y += tests/test-shift128$(EXESUF)
> > +gcov-files-test-shift128-y = util/host-utils.c
> > check-unit-y += tests/test-mul64$(EXESUF)
> > gcov-files-test-mul64-y = util/host-utils.c
> > check-unit-y += tests/test-int128$(EXESUF)
> > @@ -460,7 +462,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
> > tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
> > tests/test-opts-visitor.o tests/test-qmp-event.o \
> > tests/rcutorture.o tests/test-rcu-list.o \
> > - tests/test-qdist.o \
> > + tests/test-qdist.o tests/test-shift128.o \
> > tests/test-qht.o tests/qht-bench.o tests/test-qht-par.o \
> > tests/atomic_add-bench.o
> >
> > @@ -568,6 +570,7 @@ tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marsh
> > tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
> > tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
> >
> > +tests/test-shift128$(EXESUF): tests/test-shift128.o $(test-util-obj-y)
> > tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y)
> > tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y)
> > tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y)
> > diff --git a/tests/test-shift128.c b/tests/test-shift128.c
> > new file mode 100644
> > index 0000000..52be6a2
> > --- /dev/null
> > +++ b/tests/test-shift128.c
> > @@ -0,0 +1,98 @@
> > +/*
> > + * Test unsigned left and right shift
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2 or later.
> > + * See the COPYING.LIB file in the top-level directory.
> > + *
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qemu/host-utils.h"
> > +
> > +typedef struct {
> > + uint64_t low;
> > + uint64_t high;
> > + uint64_t rlow;
> > + uint64_t rhigh;
> > + int32_t shift;
> > + bool overflow;
> > +} test_data;
> > +
> > +static const test_data test_ltable[] = {
> > + { 1223ULL, 0, 1223ULL, 0, 0, false },
> > + { 1ULL, 0, 2ULL, 0, 1, false },
> > + { 1ULL, 0, 4ULL, 0, 2, false },
> > + { 1ULL, 0, 16ULL, 0, 4, false },
> > + { 1ULL, 0, 256ULL, 0, 8, false },
> > + { 1ULL, 0, 65536ULL, 0, 16, false },
> > + { 1ULL, 0, 2147483648ULL, 0, 31, false },
> > + { 1ULL, 0, 35184372088832ULL, 0, 45, false },
> > + { 1ULL, 0, 1152921504606846976ULL, 0, 60, false },
> > + { 1ULL, 0, 0, 1ULL, 64, false },
> > + { 1ULL, 0, 0, 65536ULL, 80, false },
> > + { 1ULL, 0, 0, 9223372036854775808ULL, 127, false },
> > + { 0ULL, 1, 0, 0, 64, true },
> > + { 0x8888888888888888ULL, 0x9999999999999999ULL,
> > + 0x8000000000000000ULL, 0x9888888888888888ULL, 60, true },
> > + { 0x8888888888888888ULL, 0x9999999999999999ULL,
> > + 0, 0x8888888888888888ULL, 64, true },
> > + { 0x8ULL, 0, 0, 0x8ULL, 64, false },
> > + { 0x8ULL, 0, 0, 0x8000000000000000ULL, 124, false },
> > + { 0x1ULL, 0, 0, 0x4000000000000000ULL, 126, false },
> > + { 0x1ULL, 0, 0, 0x8000000000000000ULL, 127, false },
> > + { 0x1ULL, 0, 0x1ULL, 0, 128, true },
> > + { 0, 0, 0ULL, 0, 200, false },
> > +};
> > +
> > +static const test_data test_rtable[] = {
> > + { 1223ULL, 0, 1223ULL, 0, 0, false },
> > + { 9223372036854775808ULL, 9223372036854775808ULL,
> > + 2147483648L, 2147483648ULL, 32, false },
> > + { 9223372036854775808ULL, 9223372036854775808ULL,
> > + 9223372036854775808ULL, 0, 64, false },
> > + { 9223372036854775808ULL, 9223372036854775808ULL,
> > + 36028797018963968ULL, 0, 72, false },
> > + { 9223372036854775808ULL, 9223372036854775808ULL,
> > + 1ULL, 0, 127, false },
> > + { 9223372036854775808ULL, 0, 4611686018427387904ULL, 0, 1, false },
> > + { 9223372036854775808ULL, 0, 2305843009213693952ULL, 0, 2, false },
> > + { 9223372036854775808ULL, 0, 36028797018963968ULL, 0, 8, false },
> > + { 9223372036854775808ULL, 0, 140737488355328ULL, 0, 16, false },
> > + { 9223372036854775808ULL, 0, 2147483648ULL, 0, 32, false },
> > + { 9223372036854775808ULL, 0, 1ULL, 0, 63, false },
> > + { 9223372036854775808ULL, 0, 0ULL, 0, 64, false },
> > +};
> > +
> > +static void test_lshift(void)
> > +{
> > + int i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(test_ltable); ++i) {
> > + bool overflow = false;
> > + test_data tmp = test_ltable[i];
> > + ulshift(&tmp.low, &tmp.high, tmp.shift, &overflow);
> > + g_assert_cmpuint(tmp.low, ==, tmp.rlow);
> > + g_assert_cmpuint(tmp.high, ==, tmp.rhigh);
> > + g_assert_cmpuint(tmp.overflow, ==, overflow);
> > + }
> > +}
> > +
> > +static void test_rshift(void)
> > +{
> > + int i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(test_rtable); ++i) {
> > + test_data tmp = test_rtable[i];
> > + urshift(&tmp.low, &tmp.high, tmp.shift);
> > + g_assert_cmpuint(tmp.low, ==, tmp.rlow);
> > + g_assert_cmpuint(tmp.high, ==, tmp.rhigh);
> > + }
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > + g_test_init(&argc, &argv, NULL);
> > + g_test_add_func("/host-utils/test_lshift", test_lshift);
> > + g_test_add_func("/host-utils/test_rshift", test_rshift);
> > + return g_test_run();
> > +}
>
> --
> David Gibson | I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
> | _way_ _around_!
> http://www.ozlabs.org/~dgibson
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2016-12-08 0:25 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-06 19:40 [Qemu-devel] [PATCH v2 0/7] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 1/7] target-ppc: Implement bcd_is_valid function Jose Ricardo Ziviani
2016-12-07 5:48 ` David Gibson
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 2/7] target-ppc: Implement unsigned quadword left/right shift and unit tests Jose Ricardo Ziviani
2016-12-07 5:41 ` David Gibson
2016-12-08 0:24 ` [Qemu-devel] [Qemu-ppc] " joserz
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 3/7] target-ppc: Implement bcds. instruction Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 4/7] target-ppc: Implement bcdus. instruction Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 5/7] target-ppc: Implement bcdsr. instruction Jose Ricardo Ziviani
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 6/7] target-ppc: Implement bcdtrunc. instruction Jose Ricardo Ziviani
2016-12-07 5:47 ` David Gibson
2016-12-06 19:40 ` [Qemu-devel] [PATCH v2 7/7] " Jose Ricardo Ziviani
2016-12-07 5:48 ` David Gibson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).