svn commit: r278646 - stable/10/sys/arm/arm
Ian Lepore
ian at FreeBSD.org
Fri Feb 13 00:15:14 UTC 2015
Author: ian
Date: Fri Feb 13 00:15:13 2015
New Revision: 278646
URL: https://svnweb.freebsd.org/changeset/base/278646
Log:
MFC r276518: Rework vfp code so it will compile on clang 3.4 and 3.5.
Modified:
stable/10/sys/arm/arm/vfp.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/arm/arm/vfp.c
==============================================================================
--- stable/10/sys/arm/arm/vfp.c Fri Feb 13 00:12:21 2015 (r278645)
+++ stable/10/sys/arm/arm/vfp.c Fri Feb 13 00:15:13 2015 (r278646)
@@ -51,30 +51,35 @@ static struct undefined_handler vfp10_uh
/* If true the VFP unit has 32 double registers, otherwise it has 16 */
static int is_d32;
-/* The VFMXR command using coprocessor commands */
+/*
+ * About .fpu directives in this file...
+ *
+ * We should need simply .fpu vfpv3, but clang 3.5 has a quirk where setting
+ * vfpv3 doesn't imply that vfp2 features are also available -- both have to be
+ * explicitly set to get all the features of both. This is probably a bug in
+ * clang, so it may get fixed and require changes here some day. Other changes
+ * are probably coming in clang too, because there is email and open PRs
+ * indicating they want to completely disable the ability to use .fpu and
+ * similar directives in inline asm. That would be catastrophic for us,
+ * hopefully they come to their senses. There was also some discusion of a new
+ * syntax such as .push fpu=vfpv3; ...; .pop fpu; and that would be ideal for
+ * us, better than what we have now really.
+ *
+ * For gcc, each .fpu directive completely overrides the prior directive, unlike
+ * with clang, but luckily on gcc saying v3 implies all the v2 features as well.
+ */
+
#define fmxr(reg, val) \
- __asm __volatile("mcr p10, 7, %0, " __STRING(reg) " , c0, 0" :: "r"(val));
+ __asm __volatile(" .fpu vfpv2\n .fpu vfpv3\n" \
+ " vmsr " __STRING(reg) ", %0" :: "r"(val));
-/* The VFMRX command using coprocessor commands */
#define fmrx(reg) \
({ u_int val = 0;\
- __asm __volatile("mrc p10, 7, %0, " __STRING(reg) " , c0, 0" : "=r"(val));\
+ __asm __volatile(" .fpu vfpv2\n .fpu vfpv3\n" \
+ " vmrs %0, " __STRING(reg) : "=r"(val)); \
val; \
})
-/*
- * Work around an issue with GCC where the asm it generates is not unified
- * syntax and fails to assemble because it expects the ldcleq instruction in the
- * form ldc<c>l, not in the UAL form ldcl<c>, and similar for stcleq.
- */
-#ifdef __clang__
-#define LDCLNE "ldclne "
-#define STCLNE "stclne "
-#else
-#define LDCLNE "ldcnel "
-#define STCLNE "stcnel "
-#endif
-
static u_int
get_coprocessorACR(void)
{
@@ -103,25 +108,25 @@ vfp_init(void)
coproc |= COPROC10 | COPROC11;
set_coprocessorACR(coproc);
- fpsid = fmrx(VFPSID); /* read the vfp system id */
- fpexc = fmrx(VFPEXC); /* read the vfp exception reg */
+ fpsid = fmrx(fpsid); /* read the vfp system id */
+ fpexc = fmrx(fpexc); /* read the vfp exception reg */
if (!(fpsid & VFPSID_HARDSOFT_IMP)) {
vfp_exists = 1;
is_d32 = 0;
- PCPU_SET(vfpsid, fpsid); /* save the VFPSID */
+ PCPU_SET(vfpsid, fpsid); /* save the fpsid */
vfp_arch =
(fpsid & VFPSID_SUBVERSION2_MASK) >> VFPSID_SUBVERSION_OFF;
if (vfp_arch >= VFP_ARCH3) {
- tmp = fmrx(VMVFR0);
+ tmp = fmrx(mvfr0);
PCPU_SET(vfpmvfr0, tmp);
if ((tmp & VMVFR0_RB_MASK) == 2)
is_d32 = 1;
- tmp = fmrx(VMVFR1);
+ tmp = fmrx(mvfr1);
PCPU_SET(vfpmvfr1, tmp);
}
@@ -161,10 +166,10 @@ vfp_bounce(u_int addr, u_int insn, struc
* something tried to executate a truly invalid instruction that maps to
* the VFP.
*/
- fpexc = fmrx(VFPEXC);
+ fpexc = fmrx(fpexc);
if (fpexc & VFPEXC_EN) {
/* Clear any exceptions */
- fmxr(VFPEXC, fpexc & ~(VFPEXC_EX | VFPEXC_FP2V));
+ fmxr(fpexc, fpexc & ~(VFPEXC_EX | VFPEXC_FP2V));
/* kill the process - we do not handle emulation */
critical_exit();
@@ -192,7 +197,7 @@ vfp_bounce(u_int addr, u_int insn, struc
* the last thread to use the VFP on this core was this thread, then the
* VFP state is valid, otherwise restore this thread's state to the VFP.
*/
- fmxr(VFPEXC, fpexc | VFPEXC_EN);
+ fmxr(fpexc, fpexc | VFPEXC_EN);
curpcb = curthread->td_pcb;
cpu = PCPU_GET(cpu);
if (curpcb->pcb_vfpcpu != cpu || curthread != PCPU_GET(fpcurthread)) {
@@ -213,22 +218,26 @@ vfp_restore(struct vfp_state *vfpsave)
{
uint32_t fpexc;
- /* On VFPv2 we may need to restore FPINST and FPINST2 */
+ /* On vfpv3 we may need to restore FPINST and FPINST2 */
fpexc = vfpsave->fpexec;
if (fpexc & VFPEXC_EX) {
- fmxr(VFPINST, vfpsave->fpinst);
+ fmxr(fpinst, vfpsave->fpinst);
if (fpexc & VFPEXC_FP2V)
- fmxr(VFPINST2, vfpsave->fpinst2);
+ fmxr(fpinst2, vfpsave->fpinst2);
}
- fmxr(VFPSCR, vfpsave->fpscr);
+ fmxr(fpscr, vfpsave->fpscr);
- __asm __volatile("ldc p10, c0, [%0], #128\n" /* d0-d15 */
- "cmp %1, #0\n" /* -D16 or -D32? */
- LDCLNE "p11, c0, [%0], #128\n" /* d16-d31 */
- "addeq %0, %0, #128\n" /* skip missing regs */
- : : "r" (vfpsave), "r" (is_d32) : "cc");
+ __asm __volatile(
+ " .fpu vfpv2\n"
+ " .fpu vfpv3\n"
+ " vldmia %0!, {d0-d15}\n" /* d0-d15 */
+ " cmp %1, #0\n" /* -D16 or -D32? */
+ " vldmiane %0!, {d16-d31}\n" /* d16-d31 */
+ " addeq %0, %0, #128\n" /* skip missing regs */
+ : "+&r" (vfpsave) : "r" (is_d32) : "cc"
+ );
- fmxr(VFPEXC, fpexc);
+ fmxr(fpexc, fpexc);
}
/*
@@ -241,28 +250,31 @@ vfp_store(struct vfp_state *vfpsave, boo
{
uint32_t fpexc;
- fpexc = fmrx(VFPEXC); /* Is the vfp enabled? */
+ fpexc = fmrx(fpexc); /* Is the vfp enabled? */
if (fpexc & VFPEXC_EN) {
vfpsave->fpexec = fpexc;
- vfpsave->fpscr = fmrx(VFPSCR);
+ vfpsave->fpscr = fmrx(fpscr);
- /* On VFPv2 we may need to save FPINST and FPINST2 */
+ /* On vfpv3 we may need to save FPINST and FPINST2 */
if (fpexc & VFPEXC_EX) {
- vfpsave->fpinst = fmrx(VFPINST);
+ vfpsave->fpinst = fmrx(fpinst);
if (fpexc & VFPEXC_FP2V)
- vfpsave->fpinst2 = fmrx(VFPINST2);
+ vfpsave->fpinst2 = fmrx(fpinst2);
fpexc &= ~VFPEXC_EX;
}
__asm __volatile(
- "stc p11, c0, [%0], #128\n" /* d0-d15 */
- "cmp %1, #0\n" /* -D16 or -D32? */
- STCLNE "p11, c0, [%0], #128\n" /* d16-d31 */
- "addeq %0, %0, #128\n" /* skip missing regs */
- : : "r" (vfpsave), "r" (is_d32) : "cc");
+ " .fpu vfpv2\n"
+ " .fpu vfpv3\n"
+ " vstmia %0!, {d0-d15}\n" /* d0-d15 */
+ " cmp %1, #0\n" /* -D16 or -D32? */
+ " vstmiane r0!, {d16-d31}\n" /* d16-d31 */
+ " addeq %0, %0, #128\n" /* skip missing regs */
+ : "+&r" (vfpsave) : "r" (is_d32) : "cc"
+ );
if (disable_vfp)
- fmxr(VFPEXC , fpexc & ~VFPEXC_EN);
+ fmxr(fpexc , fpexc & ~VFPEXC_EN);
}
}
@@ -281,9 +293,9 @@ vfp_discard(struct thread *td)
if (PCPU_GET(fpcurthread) == td)
PCPU_SET(fpcurthread, NULL);
- tmp = fmrx(VFPEXC);
+ tmp = fmrx(fpexc);
if (tmp & VFPEXC_EN)
- fmxr(VFPEXC, tmp & ~VFPEXC_EN);
+ fmxr(fpexc, tmp & ~VFPEXC_EN);
}
#endif
More information about the svn-src-stable-10
mailing list