From 61bd904b61ef893246791746517ef7a38ed732db Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 21 May 2016 14:33:28 +0100 Subject: [PATCH] Add support machinery for ARM hosts. There's currently no ARM code here, but we can probe for the features (and it seems to work). --- base/asm-common.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ base/dispatch.c | 19 +++++++++++++++++++ base/dispatch.h | 6 +++++- configure.ac | 3 ++- 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/base/asm-common.h b/base/asm-common.h index 8745ea43..0af9cb58 100644 --- a/base/asm-common.h +++ b/base/asm-common.h @@ -149,6 +149,50 @@ _where_am_i.\got : #endif ///-------------------------------------------------------------------------- +/// ARM-specific hacking. + +#if CPUFAM_ARM + +// Set the function hooks. +#define FUNC_PREHOOK(_) .balign 4 +#define ENDFUNC_HOOK(name) .ltorg + +// Call external subroutine at ADDR, possibly via PLT. + .macro callext addr, cond= +#if WANT_PIC + bl\cond \addr(PLT) +#else + bl\cond \addr +#endif + .endm + +// Do I need to arrange a spare GOT register? +#if WANT_PIC +# define NEED_GOT 1 +#endif +#define GOTREG r9 + +// Maybe load GOT address into GOT. + .macro ldgot got=r9 +#if WANT_PIC + ldr \got, =_GLOBAL_OFFSET_TABLE_ - . - 12 + add \got, pc, \got +#endif + .endm + +// Load address of external symbol ADDR into REG, maybe using GOT. + .macro leaext reg, addr, cond=, got=GOTREG +#if WANT_PIC + ldr \reg, =\addr(GOT) + ldr \reg, [\got, \reg] +#else + ldr \reg, =\addr +#endif + .endm + +#endif + +///-------------------------------------------------------------------------- /// Final stuff. // Default values for the various hooks. diff --git a/base/dispatch.c b/base/dispatch.c index 10ae4044..1b0ab2b1 100644 --- a/base/dispatch.c +++ b/base/dispatch.c @@ -224,6 +224,10 @@ struct auxentry { unsigned long type; union auxval value; }; * that the necessary entry types are defined. This is primarily ordered by * entry type to minimize duplication. */ +#if defined(AT_HWCAP) && CPUFAM_ARMEL +# define WANT_ANY 1 +# define WANT_AT_HWCAP(_) _(AT_HWCAP, u, hwcap) +#endif /* If we couldn't find any interesting entries then we can switch all of this * machinery off. Also do that if we have no means for atomic updates. @@ -255,6 +259,15 @@ static unsigned hwcaps = 0; * intends to satisfy from the auxiliary vector. Each entry contains a * feature name suffix, and the token name (for `check_env'). */ +#if CPUFAM_ARMEL +# define WANTAUX(_) \ + WANT_AT_HWCAP(_) +# define CAPMAP(_) \ + _(ARM_VFP, "arm:vfp") \ + _(ARM_NEON, "arm:neon") \ + _(ARM_V4, "arm:v4") \ + _(ARM_D32, "arm:d32") +#endif /* Build the bitmask for `hwcaps' from the `CAPMAP' list. */ enum { @@ -358,6 +371,12 @@ static void probe_hwcaps(void) /* Each CPU family now has to pick through what was found and stashed in * `probed', and set the appropriate flag bits in `hw'. */ +#if CPUFAM_ARMEL + if (probed.hwcap & HWCAP_VFPv3) hw |= HF_ARM_VFP; + if (probed.hwcap & HWCAP_NEON) hw |= HF_ARM_NEON; + if (probed.hwcap & HWCAP_VFPD32) hw |= HF_ARM_D32; + if (probed.hwcap & HWCAP_VFPv4) hw |= HF_ARM_V4; +#endif /* Store the bitmask of features we probed for everyone to see. */ DISPATCH_STORE(hwcaps, hw); diff --git a/base/dispatch.h b/base/dispatch.h index bbb81f30..1e463bdc 100644 --- a/base/dispatch.h +++ b/base/dispatch.h @@ -175,7 +175,11 @@ extern void dispatch_debug(const char */*fmt*/, ...); enum { CPUFEAT_X86_SSE2, /* Streaming SIMD Extensions 2 */ - CPUFEAT_X86_AESNI /* AES Native Instructions */ + CPUFEAT_X86_AESNI, /* AES Native Instructions */ + CPUFEAT_ARM_VFP, /* VFP floating-point (v3 or v4) */ + CPUFEAT_ARM_NEON, /* Advanced SIMD (v1 or v2) */ + CPUFEAT_ARM_V4, /* VFPv4 and/or SIMD v2 */ + CPUFEAT_ARM_D32 /* 32 double registers, not 16 */ }; extern int cpu_feature_p(int /*feat*/); diff --git a/configure.ac b/configure.ac index dcf70281..e3e5c21a 100644 --- a/configure.ac +++ b/configure.ac @@ -58,7 +58,8 @@ AC_DEFUN([catacomb_CPU_FAMILIES], [$1([i[[3-6]]86,cygwin], [x86], [win]) $1([i[[3-6]]86,*], [x86], [sysv]) $1([x86_64,cygwin], [amd64], [win]) - $1([x86_64,*], [amd64], [sysv])]) + $1([x86_64,*], [amd64], [sysv]) + $1([armv*,*-gnueabi | armv*,*-gnueabihf], [armel], [gnueabi])]) dnl A utility to clear the `seen' flags, used so as to process each CPU or dnl ABI once. -- 2.11.0