From owner-svn-src-all@FreeBSD.ORG Thu Jan 1 23:15:53 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 84BA1A55; Thu, 1 Jan 2015 23:15:53 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 703D5E9E; Thu, 1 Jan 2015 23:15:53 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t01NFrtm015633; Thu, 1 Jan 2015 23:15:53 GMT (envelope-from ian@FreeBSD.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t01NFrPV015632; Thu, 1 Jan 2015 23:15:53 GMT (envelope-from ian@FreeBSD.org) Message-Id: <201501012315.t01NFrPV015632@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: ian set sender to ian@FreeBSD.org using -f From: Ian Lepore Date: Thu, 1 Jan 2015 23:15:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r276518 - head/sys/arm/arm X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 01 Jan 2015 23:15:53 -0000 Author: ian Date: Thu Jan 1 23:15:52 2015 New Revision: 276518 URL: https://svnweb.freebsd.org/changeset/base/276518 Log: Rework the vpf support code so that it compiles with clang 3.4, 3.5, and gcc. Michal Meloun did most of the hard work in figuring out what would work with which compiler, I just reformated things a bit before committing. Modified: head/sys/arm/arm/vfp.c Modified: head/sys/arm/arm/vfp.c ============================================================================== --- head/sys/arm/arm/vfp.c Thu Jan 1 22:49:17 2015 (r276517) +++ head/sys/arm/arm/vfp.c Thu Jan 1 23:15:52 2015 (r276518) @@ -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 ldcl, not in the UAL form ldcl, 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