diff mbox series

[v2,03/32] s390x/tcg: Utilities for vector instruction helpers

Message ID 20190301115413.27153-4-david@redhat.com (mailing list archive)
State New, archived
Headers show
Series s390x/tcg: Vector Instruction Support Part 1 | expand

Commit Message

David Hildenbrand March 1, 2019, 11:53 a.m. UTC
We'll have to read/write vector elements quite frequently from helpers.
The tricky bit is properly taking care of endianess. Handle it similar
to aarch64.

target/s390x/vec_helper.c will later also contain vector support
instruction helpers.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/Makefile.objs |  1 +
 target/s390x/vec.h         | 31 +++++++++++++
 target/s390x/vec_helper.c  | 90 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 122 insertions(+)
 create mode 100644 target/s390x/vec.h
 create mode 100644 target/s390x/vec_helper.c

Comments

Richard Henderson March 1, 2019, 4:09 p.m. UTC | #1
On 3/1/19 3:53 AM, David Hildenbrand wrote:
> +#ifndef S390X_VEC_H
> +#define S390X_VEC_H
> +
> +typedef union S390Vector {
> +    uint64_t doubleword[2];
> +    uint32_t word[4];
> +    uint16_t halfword[8];
> +    uint8_t byte[16];
> +} S390Vector;
> +
> +uint8_t s390_vec_read_element8(const S390Vector *v, uint8_t enr);
> +uint16_t s390_vec_read_element16(const S390Vector *v, uint8_t enr);
> +uint32_t s390_vec_read_element32(const S390Vector *v, uint8_t enr);
> +uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr);
> +void s390_vec_write_element8(S390Vector *v, uint8_t enr, uint8_t data);
> +void s390_vec_write_element16(S390Vector *v, uint8_t enr, uint16_t data);
> +void s390_vec_write_element32(S390Vector *v, uint8_t enr, uint32_t data);
> +void s390_vec_write_element64(S390Vector *v, uint8_t enr, uint64_t data);
> +

These, I think, should be static inline.  Certainly I think they're too small
to warrant a real call across modules, as you appear to be preparing for...

I'm not sure why else they're being declared outside vec_helper.c?


r~
David Hildenbrand March 1, 2019, 4:13 p.m. UTC | #2
On 01.03.19 17:09, Richard Henderson wrote:
> On 3/1/19 3:53 AM, David Hildenbrand wrote:
>> +#ifndef S390X_VEC_H
>> +#define S390X_VEC_H
>> +
>> +typedef union S390Vector {
>> +    uint64_t doubleword[2];
>> +    uint32_t word[4];
>> +    uint16_t halfword[8];
>> +    uint8_t byte[16];
>> +} S390Vector;
>> +
>> +uint8_t s390_vec_read_element8(const S390Vector *v, uint8_t enr);
>> +uint16_t s390_vec_read_element16(const S390Vector *v, uint8_t enr);
>> +uint32_t s390_vec_read_element32(const S390Vector *v, uint8_t enr);
>> +uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr);
>> +void s390_vec_write_element8(S390Vector *v, uint8_t enr, uint8_t data);
>> +void s390_vec_write_element16(S390Vector *v, uint8_t enr, uint16_t data);
>> +void s390_vec_write_element32(S390Vector *v, uint8_t enr, uint32_t data);
>> +void s390_vec_write_element64(S390Vector *v, uint8_t enr, uint64_t data);
>> +
> 
> These, I think, should be static inline.  Certainly I think they're too small
> to warrant a real call across modules, as you appear to be preparing for...

I'm wondering, won't link-time optimization properly handle this? (so
far the theory I know of)

But I can move these completely into the head.

> 
> I'm not sure why else they're being declared outside vec_helper.c?
> 

We'll have vec_int_helper.c, vec_fpu_helper.c vec_string_helper.c ....

Thanks!
Richard Henderson March 1, 2019, 4:16 p.m. UTC | #3
On 3/1/19 8:13 AM, David Hildenbrand wrote:
>> These, I think, should be static inline.  Certainly I think they're too small
>> to warrant a real call across modules, as you appear to be preparing for...
> 
> I'm wondering, won't link-time optimization properly handle this? (so
> far the theory I know of)

It would, but who does that?  It's certainly not in -O2.

I suspect -flto is a set of -Werror and other sorts of compiler appeasement
changes beyond what anyone has tried.


r~
David Hildenbrand March 1, 2019, 4:16 p.m. UTC | #4
On 01.03.19 17:13, David Hildenbrand wrote:
> On 01.03.19 17:09, Richard Henderson wrote:
>> On 3/1/19 3:53 AM, David Hildenbrand wrote:
>>> +#ifndef S390X_VEC_H
>>> +#define S390X_VEC_H
>>> +
>>> +typedef union S390Vector {
>>> +    uint64_t doubleword[2];
>>> +    uint32_t word[4];
>>> +    uint16_t halfword[8];
>>> +    uint8_t byte[16];
>>> +} S390Vector;
>>> +
>>> +uint8_t s390_vec_read_element8(const S390Vector *v, uint8_t enr);
>>> +uint16_t s390_vec_read_element16(const S390Vector *v, uint8_t enr);
>>> +uint32_t s390_vec_read_element32(const S390Vector *v, uint8_t enr);
>>> +uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr);
>>> +void s390_vec_write_element8(S390Vector *v, uint8_t enr, uint8_t data);
>>> +void s390_vec_write_element16(S390Vector *v, uint8_t enr, uint16_t data);
>>> +void s390_vec_write_element32(S390Vector *v, uint8_t enr, uint32_t data);
>>> +void s390_vec_write_element64(S390Vector *v, uint8_t enr, uint64_t data);
>>> +
>>
>> These, I think, should be static inline.  Certainly I think they're too small
>> to warrant a real call across modules, as you appear to be preparing for...
> 
> I'm wondering, won't link-time optimization properly handle this? (so
> far the theory I know of)
> 
> But I can move these completely into the head.

Just checked the binary, definetly not optimized during link time. Will
make them static inline. Thanks!
David Hildenbrand March 1, 2019, 4:18 p.m. UTC | #5
On 01.03.19 17:16, Richard Henderson wrote:
> On 3/1/19 8:13 AM, David Hildenbrand wrote:
>>> These, I think, should be static inline.  Certainly I think they're too small
>>> to warrant a real call across modules, as you appear to be preparing for...
>>
>> I'm wondering, won't link-time optimization properly handle this? (so
>> far the theory I know of)
> 
> It would, but who does that?  It's certainly not in -O2.

I know that GCC and LLVM do it, but as you correctly state, most
probably not for O2.
diff mbox series

Patch

diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs
index 22a9a9927a..68eeee3d2f 100644
--- a/target/s390x/Makefile.objs
+++ b/target/s390x/Makefile.objs
@@ -1,6 +1,7 @@ 
 obj-y += cpu.o cpu_models.o cpu_features.o gdbstub.o interrupt.o helper.o
 obj-$(CONFIG_TCG) += translate.o cc_helper.o excp_helper.o fpu_helper.o
 obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o crypto_helper.o
+obj-$(CONFIG_TCG) += vec_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o diag.o
 obj-$(CONFIG_SOFTMMU) += sigp.o
 obj-$(CONFIG_KVM) += kvm.o
diff --git a/target/s390x/vec.h b/target/s390x/vec.h
new file mode 100644
index 0000000000..c03be1a9c9
--- /dev/null
+++ b/target/s390x/vec.h
@@ -0,0 +1,31 @@ 
+/*
+ * QEMU TCG support -- s390x vector utilitites
+ *
+ * Copyright (C) 2019 Red Hat Inc
+ *
+ * Authors:
+ *   David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef S390X_VEC_H
+#define S390X_VEC_H
+
+typedef union S390Vector {
+    uint64_t doubleword[2];
+    uint32_t word[4];
+    uint16_t halfword[8];
+    uint8_t byte[16];
+} S390Vector;
+
+uint8_t s390_vec_read_element8(const S390Vector *v, uint8_t enr);
+uint16_t s390_vec_read_element16(const S390Vector *v, uint8_t enr);
+uint32_t s390_vec_read_element32(const S390Vector *v, uint8_t enr);
+uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr);
+void s390_vec_write_element8(S390Vector *v, uint8_t enr, uint8_t data);
+void s390_vec_write_element16(S390Vector *v, uint8_t enr, uint16_t data);
+void s390_vec_write_element32(S390Vector *v, uint8_t enr, uint32_t data);
+void s390_vec_write_element64(S390Vector *v, uint8_t enr, uint64_t data);
+
+#endif /* S390X_VEC_H */
diff --git a/target/s390x/vec_helper.c b/target/s390x/vec_helper.c
new file mode 100644
index 0000000000..3e21e440ba
--- /dev/null
+++ b/target/s390x/vec_helper.c
@@ -0,0 +1,90 @@ 
+/*
+ * QEMU TCG support -- s390x vector support instructions and utilitites
+ *
+ * Copyright (C) 2019 Red Hat Inc
+ *
+ * Authors:
+ *   David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "vec.h"
+#include "tcg/tcg.h"
+
+/*
+ * Each vector is stored as two 64bit host values. So when talking about
+ * byte/halfword/word numbers, we have to take care of proper translation
+ * between element numbers.
+ *
+ * Big Endian (target/possible host)
+ * B:  [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7] - [ 8][ 9][10][11][12][13][14][15]
+ * HW: [     0][     1][     2][     3] - [     4][     5][     6][     7]
+ * W:  [             0][             1] - [             2][             3]
+ * DW: [                             0] - [                             1]
+ *
+ * Little Endian (possible host)
+ * B:  [ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0] - [15][14][13][12][11][10][ 9][ 8]
+ * HW: [     3][     2][     1][     0] - [     7][     6][     5][     4]
+ * W:  [             1][             0] - [             3][             2]
+ * DW: [                             0] - [                             1]
+ */
+#ifndef HOST_WORDS_BIGENDIAN
+#define H1(x)  ((x) ^ 7)
+#define H2(x)  ((x) ^ 3)
+#define H4(x)  ((x) ^ 1)
+#else
+#define H1(x)  (x)
+#define H2(x)  (x)
+#define H4(x)  (x)
+#endif
+
+uint8_t s390_vec_read_element8(const S390Vector *v, uint8_t enr)
+{
+    g_assert(enr < 16);
+    return v->byte[H1(enr)];
+}
+
+uint16_t s390_vec_read_element16(const S390Vector *v, uint8_t enr)
+{
+    g_assert(enr < 8);
+    return v->halfword[H2(enr)];
+}
+
+uint32_t s390_vec_read_element32(const S390Vector *v, uint8_t enr)
+{
+    g_assert(enr < 4);
+    return v->word[H4(enr)];
+}
+
+uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr)
+{
+    g_assert(enr < 2);
+    return v->doubleword[enr];
+}
+
+void s390_vec_write_element8(S390Vector *v, uint8_t enr, uint8_t data)
+{
+    g_assert(enr < 16);
+    v->byte[H1(enr)] = data;
+}
+
+void s390_vec_write_element16(S390Vector *v, uint8_t enr, uint16_t data)
+{
+    g_assert(enr < 8);
+    v->halfword[H2(enr)] = data;
+}
+
+void s390_vec_write_element32(S390Vector *v, uint8_t enr, uint32_t data)
+{
+    g_assert(enr < 4);
+    v->word[H4(enr)] = data;
+}
+
+void s390_vec_write_element64(S390Vector *v, uint8_t enr, uint64_t data)
+{
+    g_assert(enr < 2);
+    v->doubleword[enr] = data;
+}