From bc2ef10f1b658ea907736406814a6187b49ea3ec Mon Sep 17 00:00:00 2001 From: Alex Vaghin Date: Mon, 4 Jun 2018 16:47:02 +0200 Subject: [PATCH] cpu: add gccgo implementation It uses __get_cpuid_count, provided by cpuid.h. The xgetbv is implemented after its counterpart in cpu_x86.s. Change-Id: I97624d7da67ab4ec3c9a53b0bfc4dfcdf7d12c87 Reviewed-on: https://go-review.googlesource.com/116155 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- cpu/cpu_gccgo.c | 43 +++++++++++++++++++++++++++++++++++++++++++ cpu/cpu_gccgo.go | 26 ++++++++++++++++++++++++++ cpu/cpu_x86.go | 6 ++++-- cpu/cpu_x86.s | 1 + 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 cpu/cpu_gccgo.c create mode 100644 cpu/cpu_gccgo.go diff --git a/cpu/cpu_gccgo.c b/cpu/cpu_gccgo.c new file mode 100644 index 00000000..e363c7d1 --- /dev/null +++ b/cpu/cpu_gccgo.c @@ -0,0 +1,43 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build gccgo + +#include +#include + +// Need to wrap __get_cpuid_count because it's declared as static. +int +gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); +} + +// xgetbv reads the contents of an XCR (Extended Control Register) +// specified in the ECX register into registers EDX:EAX. +// Currently, the only supported value for XCR is 0. +// +// TODO: Replace with a better alternative: +// +// #include +// +// #pragma GCC target("xsave") +// +// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { +// unsigned long long x = _xgetbv(0); +// *eax = x & 0xffffffff; +// *edx = (x >> 32) & 0xffffffff; +// } +// +// Note that _xgetbv is defined starting with GCC 8. +void +gccgoXgetbv(uint32_t *eax, uint32_t *edx) +{ + __asm(" xorl %%ecx, %%ecx\n" + " xgetbv" + : "=a"(*eax), "=d"(*edx)); +} diff --git a/cpu/cpu_gccgo.go b/cpu/cpu_gccgo.go new file mode 100644 index 00000000..ba49b91b --- /dev/null +++ b/cpu/cpu_gccgo.go @@ -0,0 +1,26 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build gccgo + +package cpu + +//extern gccgoGetCpuidCount +func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32) + +func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) { + var a, b, c, d uint32 + gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d) + return a, b, c, d +} + +//extern gccgoXgetbv +func gccgoXgetbv(eax, edx *uint32) + +func xgetbv() (eax, edx uint32) { + var a, d uint32 + gccgoXgetbv(&a, &d) + return a, d +} diff --git a/cpu/cpu_x86.go b/cpu/cpu_x86.go index 8842b7cf..ffc90d67 100644 --- a/cpu/cpu_x86.go +++ b/cpu/cpu_x86.go @@ -8,10 +8,12 @@ package cpu const cacheLineSize = 64 -// cpuid is implemented in cpu_x86.s. +// cpuid is implemented in cpu_x86.s for gc compiler +// and in cpu_gccgo.c for gccgo. func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) -// xgetbv with ecx = 0 is implemented in cpu_x86.s. +// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler +// and in cpu_gccgo.c for gccgo. func xgetbv() (eax, edx uint32) func init() { diff --git a/cpu/cpu_x86.s b/cpu/cpu_x86.s index 4ff61e00..47f08412 100644 --- a/cpu/cpu_x86.s +++ b/cpu/cpu_x86.s @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // +build 386 amd64 amd64p32 +// +build !gccgo #include "textflag.h"