Re: [Qemu-devel] [PATCH 6/7] target/s390x: fix PACK reading 1 byte less and writing 1 byte more
On 21.08.2018 04:51, Pavel Zbitskiy wrote: > PACK fails on the test from the Principles of Operation: F1F2F3F4 > becomes 234C instead of 0001234C due to an off-by-one error. > Furthermore, it overwrites one extra byte to the left of F1. > > If len_dest is 0, then we only want to flip the 1st byte and never loop > over the rest. Therefore, the loop condition should be > and not >=. > > If len_src is 1, then we should flip the 1st byte and pack the 2nd. > Since len_src is already decremented before the loop, the first > condition should be >=, and not >. > > Likewise for len_src == 2 and the second condition. > > Signed-off-by: Pavel Zbitskiy > --- > target/s390x/mem_helper.c | 6 +++--- > tests/tcg/s390x/Makefile.target | 1 + > tests/tcg/s390x/pack.c | 21 + > 3 files changed, 25 insertions(+), 3 deletions(-) > create mode 100644 tests/tcg/s390x/pack.c > > diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c > index 704d0193b5..bacae4f503 100644 > --- a/target/s390x/mem_helper.c > +++ b/target/s390x/mem_helper.c > @@ -1019,15 +1019,15 @@ void HELPER(pack)(CPUS390XState *env, uint32_t len, > uint64_t dest, uint64_t src) > len_src--; > > /* now pack every value */ > -while (len_dest >= 0) { > +while (len_dest > 0) { > b = 0; > > -if (len_src > 0) { > +if (len_src >= 0) { > b = cpu_ldub_data_ra(env, src, ra) & 0x0f; > src--; > len_src--; > } > -if (len_src > 0) { > +if (len_src >= 0) { > b |= cpu_ldub_data_ra(env, src, ra) << 4; > src--; > len_src--; > diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target > index 7de4376f52..151dc075aa 100644 > --- a/tests/tcg/s390x/Makefile.target > +++ b/tests/tcg/s390x/Makefile.target > @@ -5,3 +5,4 @@ TESTS+=csst > TESTS+=ipm > TESTS+=exrl-trt > TESTS+=exrl-trtr > +TESTS+=pack > diff --git a/tests/tcg/s390x/pack.c b/tests/tcg/s390x/pack.c > new file mode 100644 > index 00..4be36f29a7 > --- /dev/null > +++ b/tests/tcg/s390x/pack.c > @@ -0,0 +1,21 @@ > +#include > + > +int main(void) > +{ > +char data[] = {0xaa, 0xaa, 0xf1, 0xf2, 0xf3, 0xc4, 0xaa, 0xaa}; > +char exp[] = {0xaa, 0xaa, 0x00, 0x01, 0x23, 0x4c, 0xaa, 0xaa}; > +int i; > + > +asm volatile( > +"pack 2(4,%[data]),2(4,%[data])\n" > +: > +: [data] "r" ([0]) > +: "memory"); > +for (i = 0; i < 8; i++) { > +if (data[i] != exp[i]) { > +write(1, "bad data\n", 9); > +return 1; > +} > +} > +return 0; > +} > Reviewed-by: David Hildenbrand -- Thanks, David / dhildenb
[Qemu-devel] [PATCH 6/7] target/s390x: fix PACK reading 1 byte less and writing 1 byte more
PACK fails on the test from the Principles of Operation: F1F2F3F4 becomes 234C instead of 0001234C due to an off-by-one error. Furthermore, it overwrites one extra byte to the left of F1. If len_dest is 0, then we only want to flip the 1st byte and never loop over the rest. Therefore, the loop condition should be > and not >=. If len_src is 1, then we should flip the 1st byte and pack the 2nd. Since len_src is already decremented before the loop, the first condition should be >=, and not >. Likewise for len_src == 2 and the second condition. Signed-off-by: Pavel Zbitskiy --- target/s390x/mem_helper.c | 6 +++--- tests/tcg/s390x/Makefile.target | 1 + tests/tcg/s390x/pack.c | 21 + 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tests/tcg/s390x/pack.c diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 704d0193b5..bacae4f503 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1019,15 +1019,15 @@ void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) len_src--; /* now pack every value */ -while (len_dest >= 0) { +while (len_dest > 0) { b = 0; -if (len_src > 0) { +if (len_src >= 0) { b = cpu_ldub_data_ra(env, src, ra) & 0x0f; src--; len_src--; } -if (len_src > 0) { +if (len_src >= 0) { b |= cpu_ldub_data_ra(env, src, ra) << 4; src--; len_src--; diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 7de4376f52..151dc075aa 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -5,3 +5,4 @@ TESTS+=csst TESTS+=ipm TESTS+=exrl-trt TESTS+=exrl-trtr +TESTS+=pack diff --git a/tests/tcg/s390x/pack.c b/tests/tcg/s390x/pack.c new file mode 100644 index 00..4be36f29a7 --- /dev/null +++ b/tests/tcg/s390x/pack.c @@ -0,0 +1,21 @@ +#include + +int main(void) +{ +char data[] = {0xaa, 0xaa, 0xf1, 0xf2, 0xf3, 0xc4, 0xaa, 0xaa}; +char exp[] = {0xaa, 0xaa, 0x00, 0x01, 0x23, 0x4c, 0xaa, 0xaa}; +int i; + +asm volatile( +"pack 2(4,%[data]),2(4,%[data])\n" +: +: [data] "r" ([0]) +: "memory"); +for (i = 0; i < 8; i++) { +if (data[i] != exp[i]) { +write(1, "bad data\n", 9); +return 1; +} +} +return 0; +} -- 2.18.0
[Qemu-devel] [PATCH 6/7] target/s390x: fix PACK reading 1 byte less and writing 1 byte more
PACK fails on the test from the Principles of Operation: F1F2F3F4 becomes 234C instead of 0001234C due to an off-by-one error. Furthermore, it overwrites one extra byte to the left of F1. If len_dest is 0, then we only want to flip the 1st byte and never loop over the rest. Therefore, the loop condition should be > and not >=. If len_src is 1, then we should flip the 1st byte and pack the 2nd. Since len_src is already decremented before the loop, the first condition should be >=, and not >. Likewise for len_src == 2 and the second condition. Signed-off-by: Pavel Zbitskiy --- target/s390x/mem_helper.c | 6 +++--- tests/tcg/s390x/Makefile.target | 1 + tests/tcg/s390x/pack.c | 21 + 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tests/tcg/s390x/pack.c diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 704d0193b5..bacae4f503 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1019,15 +1019,15 @@ void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) len_src--; /* now pack every value */ -while (len_dest >= 0) { +while (len_dest > 0) { b = 0; -if (len_src > 0) { +if (len_src >= 0) { b = cpu_ldub_data_ra(env, src, ra) & 0x0f; src--; len_src--; } -if (len_src > 0) { +if (len_src >= 0) { b |= cpu_ldub_data_ra(env, src, ra) << 4; src--; len_src--; diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 7de4376f52..151dc075aa 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -5,3 +5,4 @@ TESTS+=csst TESTS+=ipm TESTS+=exrl-trt TESTS+=exrl-trtr +TESTS+=pack diff --git a/tests/tcg/s390x/pack.c b/tests/tcg/s390x/pack.c new file mode 100644 index 00..4be36f29a7 --- /dev/null +++ b/tests/tcg/s390x/pack.c @@ -0,0 +1,21 @@ +#include + +int main(void) +{ +char data[] = {0xaa, 0xaa, 0xf1, 0xf2, 0xf3, 0xc4, 0xaa, 0xaa}; +char exp[] = {0xaa, 0xaa, 0x00, 0x01, 0x23, 0x4c, 0xaa, 0xaa}; +int i; + +asm volatile( +"pack 2(4,%[data]),2(4,%[data])\n" +: +: [data] "r" ([0]) +: "memory"); +for (i = 0; i < 8; i++) { +if (data[i] != exp[i]) { +write(1, "bad data\n", 9); +return 1; +} +} +return 0; +} -- 2.18.0