This patch by Robin Dapp adds S/390 support to the internal/cpu
package.  This partially addresses PR 89123.  I bootstrapped it on
x86_64-pc-linux-gnu, which means little.  Committed to mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE     (revision 268940)
+++ gcc/go/gofrontend/MERGE     (working copy)
@@ -1,4 +1,4 @@
-6877c95a5f44c3ab4f492d2000ce07771341d7b7
+0563f2d018cdb2cd685c254bac5ceb38396d0a27
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: libgo/go/internal/cpu/cpu_gccgo.c
===================================================================
--- libgo/go/internal/cpu/cpu_gccgo.c   (revision 268369)
+++ libgo/go/internal/cpu/cpu_gccgo.c   (working copy)
@@ -70,3 +70,118 @@ struct xgetbv_ret xgetbv(void) {
 #pragma GCC pop_options
 
 #endif /* defined(__i386__) || defined(__x86_64__)  */
+
+#ifdef __s390__
+
+struct facilityList {
+       uint64_t bits[4];
+};
+
+struct queryResult {
+       uint64_t bits[2];
+};
+
+struct facilityList stfle(void)
+  __asm__(GOSYM_PREFIX "internal..z2fcpu.stfle")
+  __attribute__((no_split_stack));
+
+struct facilityList stfle(void) {
+    struct facilityList ret;
+    __asm__ ("la    %%r1, %[ret]\t\n"
+            "lghi  %%r0, 3\t\n" // last doubleword index to store
+            "xc    0(32,%%r1), 0(%%r1)\t\n" // clear 4 doublewords (32 bytes)
+            ".long 0xb2b01000\t\n"  // store facility list extended (STFLE)
+            :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+    return ret;
+}
+
+struct queryResult kmQuery(void)
+  __asm__(GOSYM_PREFIX "internal..z2fcpu.kmQuery")
+  __attribute__((no_split_stack));
+
+struct queryResult kmQuery() {
+    struct queryResult ret;
+
+    __asm__ ("lghi   %%r0, 0\t\n" // set function code to 0 (KM-Query)
+            "la     %%r1, %[ret]\t\n"
+            ".long  0xb92e0024\t\n" // cipher message (KM)
+            :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+    return ret;
+}
+
+struct queryResult kmcQuery(void)
+  __asm__(GOSYM_PREFIX "internal..z2fcpu.kmcQuery")
+  __attribute__((no_split_stack));
+
+struct queryResult kmcQuery() {
+    struct queryResult ret;
+
+    __asm__ ("lghi   %%r0, 0\t\n" // set function code to 0 (KMC-Query)
+            "la     %%r1, %[ret]\t\n"
+            ".long  0xb92f0024\t\n"  // cipher message with chaining (KMC)
+            :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+    return ret;
+}
+
+struct queryResult kmctrQuery(void)
+  __asm__(GOSYM_PREFIX "internal..z2fcpu.kmctrQuery")
+  __attribute__((no_split_stack));
+
+struct queryResult kmctrQuery() {
+    struct queryResult ret;
+
+    __asm__ ("lghi   %%r0, 0\t\n" // set function code to 0 (KMCTR-Query)
+            "la     %%r1, %[ret]\t\n"
+            ".long  0xb92d4024\t\n" // cipher message with counter (KMCTR)
+            :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+    return ret;
+}
+
+struct queryResult kmaQuery(void)
+  __asm__(GOSYM_PREFIX "internal..z2fcpu.kmaQuery")
+  __attribute__((no_split_stack));
+
+struct queryResult kmaQuery() {
+    struct queryResult ret;
+
+    __asm__ ("lghi   %%r0, 0\t\n" // set function code to 0 (KMA-Query)
+            "la     %%r1, %[ret]\t\n"
+            ".long  0xb9296024\t\n" // cipher message with authentication (KMA)
+            :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+    return ret;
+}
+
+struct queryResult kimdQuery(void)
+  __asm__(GOSYM_PREFIX "internal..z2fcpu.kimdQuery")
+  __attribute__((no_split_stack));
+
+struct queryResult kimdQuery() {
+    struct queryResult ret;
+
+    __asm__ ("lghi   %%r0, 0\t\n"  // set function code to 0 (KIMD-Query)
+            "la     %%r1, %[ret]\t\n"
+            ".long  0xb93e0024\t\n"  // compute intermediate message digest 
(KIMD)
+            :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+    return ret;
+}
+
+struct queryResult klmdQuery(void)
+  __asm__(GOSYM_PREFIX "internal..z2fcpu.klmdQuery")
+  __attribute__((no_split_stack));
+
+struct queryResult klmdQuery() {
+    struct queryResult ret;
+
+    __asm__ ("lghi   %%r0, 0\t\n"  // set function code to 0 (KLMD-Query)
+            "la     %%r1, %[ret]\t\n"
+            ".long  0xb93f0024\t\n"  // compute last message digest (KLMD)
+            :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+    return ret;
+}
+
+#endif /* defined(__s390__)  */
Index: libgo/go/internal/cpu/cpu_s390x.go
===================================================================
--- libgo/go/internal/cpu/cpu_s390x.go  (revision 268369)
+++ libgo/go/internal/cpu/cpu_s390x.go  (working copy)
@@ -98,13 +98,13 @@ func (s *facilityList) Has(fs ...facilit
 
 // The following feature detection functions are defined in cpu_s390x.s.
 // They are likely to be expensive to call so the results should be cached.
-func stfle() facilityList     { panic("not implemented for gccgo") }
-func kmQuery() queryResult    { panic("not implemented for gccgo") }
-func kmcQuery() queryResult   { panic("not implemented for gccgo") }
-func kmctrQuery() queryResult { panic("not implemented for gccgo") }
-func kmaQuery() queryResult   { panic("not implemented for gccgo") }
-func kimdQuery() queryResult  { panic("not implemented for gccgo") }
-func klmdQuery() queryResult  { panic("not implemented for gccgo") }
+func stfle() facilityList
+func kmQuery() queryResult
+func kmcQuery() queryResult
+func kmctrQuery() queryResult
+func kmaQuery() queryResult
+func kimdQuery() queryResult
+func klmdQuery() queryResult
 
 func doinit() {
        options = []option{
@@ -122,14 +122,6 @@ func doinit() {
        aes := []function{aes128, aes192, aes256}
        facilities := stfle()
 
-       S390X.HasZArch = facilities.Has(zarch)
-       S390X.HasSTFLE = facilities.Has(stflef)
-       S390X.HasLDisp = facilities.Has(ldisp)
-       S390X.HasEImm = facilities.Has(eimm)
-       S390X.HasDFP = facilities.Has(dfp)
-       S390X.HasETF3Enhanced = facilities.Has(etf3eh)
-       S390X.HasMSA = facilities.Has(msa)
-
        if S390X.HasMSA {
                // cipher message
                km, kmc := kmQuery(), kmcQuery()
Index: libgo/go/runtime/os_linux_s390x.go
===================================================================
--- libgo/go/runtime/os_linux_s390x.go  (revision 268369)
+++ libgo/go/runtime/os_linux_s390x.go  (working copy)
@@ -8,12 +8,26 @@ import "internal/cpu"
 
 const (
        // bit masks taken from bits/hwcap.h
-       _HWCAP_S390_VX = 2048 // vector facility
+       _HWCAP_S390_ZARCH  = 2
+       _HWCAP_S390_STFLE  = 4
+       _HWCAP_S390_MSA    = 8
+       _HWCAP_S390_LDISP  = 16
+       _HWCAP_S390_EIMM   = 32
+       _HWCAP_S390_DFP    = 64
+       _HWCAP_S390_ETF3EH = 256
+       _HWCAP_S390_VX     = 2048 // vector facility
 )
 
 func archauxv(tag, val uintptr) {
        switch tag {
        case _AT_HWCAP: // CPU capability bit flags
+               cpu.S390X.HasZArch = val&_HWCAP_S390_ZARCH != 0
+               cpu.S390X.HasSTFLE = val&_HWCAP_S390_STFLE != 0
+               cpu.S390X.HasMSA = val&_HWCAP_S390_MSA != 0
+               cpu.S390X.HasLDisp = val&_HWCAP_S390_LDISP != 0
+               cpu.S390X.HasEImm = val&_HWCAP_S390_EIMM != 0
+               cpu.S390X.HasDFP = val&_HWCAP_S390_DFP != 0
+               cpu.S390X.HasETF3Enhanced = val&_HWCAP_S390_ETF3EH != 0
                cpu.S390X.HasVX = val&_HWCAP_S390_VX != 0
        }
 }

Reply via email to