* [Qemu-devel] [PATCH v3 1/6] target-ppc: Implement unsigned quadword left/right shift and unit tests
2016-12-08 2:07 [Qemu-devel] [PATCH v3 0/6] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
@ 2016-12-08 2:07 ` Jose Ricardo Ziviani
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 2/6] target-ppc: Implement bcds. instruction Jose Ricardo Ziviani
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-08 2:07 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 designed for signed numbers.
Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
---
include/qemu/host-utils.h | 3 ++
tests/Makefile.include | 5 ++-
tests/test-shift128.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++
util/Makefile.objs | 2 +-
util/host-utils.c | 44 +++++++++++++++++++++
5 files changed, 150 insertions(+), 2 deletions(-)
create mode 100644 tests/test-shift128.c
diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
index 46187bb..e87de19 100644
--- a/include/qemu/host-utils.h
+++ b/include/qemu/host-utils.h
@@ -516,4 +516,7 @@ static inline uint64_t pow2ceil(uint64_t value)
return 1ULL << (64 - nlz);
}
+void urshift(uint64_t *plow, uint64_t *phigh, uint32_t shift);
+void ulshift(uint64_t *plow, uint64_t *phigh, uint32_t shift, bool *overflow);
+
#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();
+}
diff --git a/util/Makefile.objs b/util/Makefile.objs
index ad0f9c7..39ae26e 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -11,7 +11,7 @@ util-obj-$(CONFIG_POSIX) += memfd.o
util-obj-$(CONFIG_WIN32) += oslib-win32.o
util-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
util-obj-y += envlist.o path.o module.o
-util-obj-$(call lnot,$(CONFIG_INT128)) += host-utils.o
+util-obj-y += host-utils.o
util-obj-y += bitmap.o bitops.o hbitmap.o
util-obj-y += fifo8.o
util-obj-y += acl.o
diff --git a/util/host-utils.c b/util/host-utils.c
index b166e57..1ee2433 100644
--- a/util/host-utils.c
+++ b/util/host-utils.c
@@ -26,6 +26,7 @@
#include "qemu/osdep.h"
#include "qemu/host-utils.h"
+#ifndef CONFIG_INT128
/* Long integer helpers */
static inline void mul64(uint64_t *plow, uint64_t *phigh,
uint64_t a, uint64_t b)
@@ -158,4 +159,47 @@ int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
return overflow;
}
+#endif
+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;
+ }
+}
+
+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;
+ }
+}
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v3 2/6] target-ppc: Implement bcds. instruction
2016-12-08 2:07 [Qemu-devel] [PATCH v3 0/6] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 1/6] target-ppc: Implement unsigned quadword left/right shift and unit tests Jose Ricardo Ziviani
@ 2016-12-08 2:07 ` Jose Ricardo Ziviani
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 3/6] target-ppc: Implement bcdus. instruction Jose Ricardo Ziviani
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-08 2:07 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] 9+ messages in thread
* [Qemu-devel] [PATCH v3 3/6] target-ppc: Implement bcdus. instruction
2016-12-08 2:07 [Qemu-devel] [PATCH v3 0/6] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 1/6] target-ppc: Implement unsigned quadword left/right shift and unit tests Jose Ricardo Ziviani
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 2/6] target-ppc: Implement bcds. instruction Jose Ricardo Ziviani
@ 2016-12-08 2:07 ` Jose Ricardo Ziviani
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 4/6] target-ppc: Implement bcdsr. instruction Jose Ricardo Ziviani
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-08 2:07 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] 9+ messages in thread
* [Qemu-devel] [PATCH v3 4/6] target-ppc: Implement bcdsr. instruction
2016-12-08 2:07 [Qemu-devel] [PATCH v3 0/6] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
` (2 preceding siblings ...)
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 3/6] target-ppc: Implement bcdus. instruction Jose Ricardo Ziviani
@ 2016-12-08 2:07 ` Jose Ricardo Ziviani
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 5/6] target-ppc: Implement bcdtrunc. instruction Jose Ricardo Ziviani
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 6/6] target-ppc: Implement bcdutrunc. instruction Jose Ricardo Ziviani
5 siblings, 0 replies; 9+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-08 2:07 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] 9+ messages in thread
* [Qemu-devel] [PATCH v3 5/6] target-ppc: Implement bcdtrunc. instruction
2016-12-08 2:07 [Qemu-devel] [PATCH v3 0/6] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
` (3 preceding siblings ...)
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 4/6] target-ppc: Implement bcdsr. instruction Jose Ricardo Ziviani
@ 2016-12-08 2:07 ` Jose Ricardo Ziviani
2016-12-08 21:06 ` David Gibson
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 6/6] target-ppc: Implement bcdutrunc. instruction Jose Ricardo Ziviani
5 siblings, 1 reply; 9+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-08 2:07 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 | 40 +++++++++++++++++++++++++++++++++++++
target-ppc/translate/vmx-impl.inc.c | 5 +++++
target-ppc/translate/vmx-ops.inc.c | 4 ++--
4 files changed, 48 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..dea08e6 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -3169,6 +3169,46 @@ 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)
+{
+ uint64_t mask;
+ uint32_t bits;
+ uint32_t ox_flag = 0;
+ ppc_avr_t ret = *b;
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ int upper = ARRAY_SIZE(a->u16) - 1;
+#else
+ int upper = 0;
+#endif
+
+ if (bcd_is_valid(b) == false) {
+ return CRF_SO;
+ }
+
+ bits = (a->u16[upper] & 31) << 2;
+ if (bits >= 64) {
+ if (ret.u64[HI_IDX] || (ret.u64[LO_IDX] >> (128 - bits))) {
+ ox_flag = CRF_SO;
+ }
+
+ mask = (uint64_t)-1 >> (bits - 64);
+ ret.u64[HI_IDX] = 0;
+ ret.u64[LO_IDX] &= mask;
+ } else {
+ if (ret.u64[HI_IDX] >> (64 - bits)) {
+ ox_flag = CRF_SO;
+ }
+
+ mask = (uint64_t)-1 >> bits;
+ ret.u64[HI_IDX] &= mask;
+ }
+ bcd_put_digit(&ret, bcd_preferred_sgn(bcd_get_sgn(b), ps), 0);
+ *r = ret;
+
+ return bcd_cmp_zero(&ret) | ox_flag;
+}
+
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] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v3 5/6] target-ppc: Implement bcdtrunc. instruction
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 5/6] target-ppc: Implement bcdtrunc. instruction Jose Ricardo Ziviani
@ 2016-12-08 21:06 ` David Gibson
2016-12-08 23:29 ` [Qemu-devel] [Qemu-ppc] " joserz
0 siblings, 1 reply; 9+ messages in thread
From: David Gibson @ 2016-12-08 21:06 UTC (permalink / raw)
To: Jose Ricardo Ziviani; +Cc: qemu-ppc, qemu-devel, nikunj, bharata
[-- Attachment #1: Type: text/plain, Size: 5306 bytes --]
On Thu, Dec 08, 2016 at 12:07:07AM -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>
Um.. this is wrong on multiple accounts. Have you actually tested
this with any input at all?
> ---
> target-ppc/helper.h | 1 +
> target-ppc/int_helper.c | 40 +++++++++++++++++++++++++++++++++++++
> target-ppc/translate/vmx-impl.inc.c | 5 +++++
> target-ppc/translate/vmx-ops.inc.c | 4 ++--
> 4 files changed, 48 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..dea08e6 100644
> --- a/target-ppc/int_helper.c
> +++ b/target-ppc/int_helper.c
> @@ -3169,6 +3169,46 @@ 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)
> +{
> + uint64_t mask;
> + uint32_t bits;
> + uint32_t ox_flag = 0;
> + ppc_avr_t ret = *b;
> +
> +#if defined(HOST_WORDS_BIGENDIAN)
> + int upper = ARRAY_SIZE(a->u16) - 1;
> +#else
> + int upper = 0;
> +#endif
> +
> + if (bcd_is_valid(b) == false) {
> + return CRF_SO;
> + }
> +
> + bits = (a->u16[upper] & 31) << 2;
According to the ISA, the value here gives the number of digits to
*retain*, you're treating it as the number of digits to clear. You're
also not accounting for the sign marker, which should be retained in
any case.
Finally, the ISA says the value in bits 48:63 are treated as length
with no mention of being truncated to 5 bits. Which means it's not
clear what should happen if length > 31. You'll need to check with
the hardware people about this.
> + if (bits >= 64) {
> + if (ret.u64[HI_IDX] || (ret.u64[LO_IDX] >> (128 - bits))) {
> + ox_flag = CRF_SO;
> + }
> +
> + mask = (uint64_t)-1 >> (bits - 64);
> + ret.u64[HI_IDX] = 0;
> + ret.u64[LO_IDX] &= mask;
> + } else {
> + if (ret.u64[HI_IDX] >> (64 - bits)) {
> + ox_flag = CRF_SO;
> + }
> +
> + mask = (uint64_t)-1 >> bits;
> + ret.u64[HI_IDX] &= mask;
> + }
> + bcd_put_digit(&ret, bcd_preferred_sgn(bcd_get_sgn(b), ps), 0);
> + *r = ret;
> +
> + return bcd_cmp_zero(&ret) | ox_flag;
> +}
> +
> 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] 9+ messages in thread
* Re: [Qemu-devel] [Qemu-ppc] [PATCH v3 5/6] target-ppc: Implement bcdtrunc. instruction
2016-12-08 21:06 ` David Gibson
@ 2016-12-08 23:29 ` joserz
0 siblings, 0 replies; 9+ messages in thread
From: joserz @ 2016-12-08 23:29 UTC (permalink / raw)
To: David Gibson; +Cc: qemu-ppc, qemu-devel, bharata
On Fri, Dec 09, 2016 at 08:06:14AM +1100, David Gibson wrote:
> On Thu, Dec 08, 2016 at 12:07:07AM -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>
>
> Um.. this is wrong on multiple accounts. Have you actually tested
> this with any input at all?
yes I did, a lot but it's possible that I get the idea wrong.
>
> > ---
> > target-ppc/helper.h | 1 +
> > target-ppc/int_helper.c | 40 +++++++++++++++++++++++++++++++++++++
> > target-ppc/translate/vmx-impl.inc.c | 5 +++++
> > target-ppc/translate/vmx-ops.inc.c | 4 ++--
> > 4 files changed, 48 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..dea08e6 100644
> > --- a/target-ppc/int_helper.c
> > +++ b/target-ppc/int_helper.c
> > @@ -3169,6 +3169,46 @@ 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)
> > +{
> > + uint64_t mask;
> > + uint32_t bits;
> > + uint32_t ox_flag = 0;
> > + ppc_avr_t ret = *b;
> > +
> > +#if defined(HOST_WORDS_BIGENDIAN)
> > + int upper = ARRAY_SIZE(a->u16) - 1;
> > +#else
> > + int upper = 0;
> > +#endif
> > +
> > + if (bcd_is_valid(b) == false) {
> > + return CRF_SO;
> > + }
> > +
> > + bits = (a->u16[upper] & 31) << 2;
>
> According to the ISA, the value here gives the number of digits to
> *retain*, you're treating it as the number of digits to clear. You're
> also not accounting for the sign marker, which should be retained in
> any case.
I understood it is the number of bits to clear, I'll review it.
>
> Finally, the ISA says the value in bits 48:63 are treated as length
> with no mention of being truncated to 5 bits. Which means it's not
> clear what should happen if length > 31. You'll need to check with
> the hardware people about this.
ok
>
> > + if (bits >= 64) {
> > + if (ret.u64[HI_IDX] || (ret.u64[LO_IDX] >> (128 - bits))) {
> > + ox_flag = CRF_SO;
> > + }
> > +
> > + mask = (uint64_t)-1 >> (bits - 64);
> > + ret.u64[HI_IDX] = 0;
> > + ret.u64[LO_IDX] &= mask;
> > + } else {
> > + if (ret.u64[HI_IDX] >> (64 - bits)) {
> > + ox_flag = CRF_SO;
> > + }
> > +
> > + mask = (uint64_t)-1 >> bits;
> > + ret.u64[HI_IDX] &= mask;
> > + }
> > + bcd_put_digit(&ret, bcd_preferred_sgn(bcd_get_sgn(b), ps), 0);
> > + *r = ret;
> > +
> > + return bcd_cmp_zero(&ret) | ox_flag;
> > +}
> > +
> > 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
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v3 6/6] target-ppc: Implement bcdutrunc. instruction
2016-12-08 2:07 [Qemu-devel] [PATCH v3 0/6] POWER9 TCG enablements - BCD functions - final part Jose Ricardo Ziviani
` (4 preceding siblings ...)
2016-12-08 2:07 ` [Qemu-devel] [PATCH v3 5/6] target-ppc: Implement bcdtrunc. instruction Jose Ricardo Ziviani
@ 2016-12-08 2:07 ` Jose Ricardo Ziviani
5 siblings, 0 replies; 9+ messages in thread
From: Jose Ricardo Ziviani @ 2016-12-08 2:07 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 | 54 +++++++++++++++++++++++++++++++++++++
target-ppc/translate/vmx-impl.inc.c | 4 +++
target-ppc/translate/vmx-ops.inc.c | 2 +-
4 files changed, 60 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 dea08e6..e4f5980 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -3209,6 +3209,60 @@ uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
return bcd_cmp_zero(&ret) | ox_flag;
}
+uint32_t helper_bcdutrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
+{
+ int i;
+ uint64_t mask;
+ uint32_t bits;
+ uint32_t 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
+
+ for (i = 0; i < 32; i++) {
+ bcd_get_digit(b, i, &invalid);
+
+ if (unlikely(invalid)) {
+ return CRF_SO;
+ }
+ }
+
+ bits = (a->u16[upper] % 33) << 2;
+ if (bits == 128) {
+ if (ret.u64[HI_IDX] || ret.u64[LO_IDX]) {
+ ox_flag = CRF_SO;
+ }
+ ret.u64[HI_IDX] = ret.u64[LO_IDX] = 0;
+ } else if (bits >= 64) {
+ if (ret.u64[HI_IDX] || (ret.u64[LO_IDX] >> (128 - bits))) {
+ ox_flag = CRF_SO;
+ }
+
+ mask = (uint64_t)-1 >> (bits - 64);
+ ret.u64[HI_IDX] = 0;
+ ret.u64[LO_IDX] &= mask;
+ } else {
+ if (bits > 0 && (ret.u64[HI_IDX] >> (64 - bits))) {
+ ox_flag = CRF_SO;
+ }
+
+ mask = (uint64_t)-1 >> bits;
+ ret.u64[HI_IDX] &= mask;
+ }
+
+ *r = ret;
+ if (r->u64[HI_IDX] == 0 && r->u64[LO_IDX] == 0) {
+ return ox_flag | CRF_EQ;
+ }
+
+ return ox_flag | 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] 9+ messages in thread