#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.
* 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.
* 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 {
/* 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);
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*/);
[$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.