diff options
author | andrew <andrew@FreeBSD.org> | 2013-07-16 23:19:05 +0000 |
---|---|---|
committer | andrew <andrew@FreeBSD.org> | 2013-07-16 23:19:05 +0000 |
commit | ba840962e3fa284766290d9cdab82a949fb9e192 (patch) | |
tree | fc158df124703a5ec56a038f59acfd33eee5b0ae /sys/arm | |
parent | 2bcd8f2bdde51839ef449bf6de4ef3c24d0e3639 (diff) | |
download | FreeBSD-src-ba840962e3fa284766290d9cdab82a949fb9e192.zip FreeBSD-src-ba840962e3fa284766290d9cdab82a949fb9e192.tar.gz |
Fix vfp:
- We should check is_d32 to see howmany registers we have
- In vfp_restore mark vfpscr as an output register
Without the second part it appears we can return the incorrect value from
vfp_bounce if the VFP condition flags are set as it may override the
register holding the return value.
Diffstat (limited to 'sys/arm')
-rw-r--r-- | sys/arm/arm/vfp.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/sys/arm/arm/vfp.c b/sys/arm/arm/vfp.c index 212e4c3..b9dce13 100644 --- a/sys/arm/arm/vfp.c +++ b/sys/arm/arm/vfp.c @@ -202,21 +202,20 @@ vfp_restore(struct vfp_state *vfpsave) * form ldcl<c>, and similar for stcleq. */ #ifdef __clang__ -#define ldcleq "ldcleq" -#define stcleq "stcleq" +#define ldclne "ldclne" +#define stclne "stclne" #else -#define ldcleq "ldceql" -#define stcleq "stceql" +#define ldclne "ldcnel" +#define stclne "stcnel" #endif if (vfpsave) { - __asm __volatile("ldc p10, c0, [%0], #128\n" /* d0-d15 */ - "cmp %0, #0\n" /* -D16 or -D32? */ - ldcleq" p11, c0, [%0], #128\n" /* d16-d31 */ - "addne %0, %0, #128\n" /* skip missing regs */ - "ldr %1, [%0]\n" /* set old vfpscr */ - "mcr p10, 7, %1, cr1, c0, 0\n" - :: "r" (vfpsave), "r" (vfpscr), "r" (is_d32) - : "cc"); + __asm __volatile("ldc p10, c0, [%1], #128\n" /* d0-d15 */ + "cmp %2, #0\n" /* -D16 or -D32? */ + ldclne" p11, c0, [%1], #128\n" /* d16-d31 */ + "addeq %1, %1, #128\n" /* skip missing regs */ + "ldr %0, [%1]\n" /* set old vfpscr */ + "mcr p10, 7, %0, cr1, c0, 0\n" + : "=&r" (vfpscr) : "r" (vfpsave), "r" (is_d32) : "cc"); PCPU_SET(vfpcthread, PCPU_GET(curthread)); } } @@ -238,12 +237,12 @@ vfp_store(struct vfp_state *vfpsave) tmp = fmrx(VFPEXC); /* Is the vfp enabled? */ if (vfpsave && tmp & VFPEXC_EN) { __asm __volatile("stc p11, c0, [%1], #128\n" /* d0-d15 */ - "cmp %0, #0\n" /* -D16 or -D32? */ - stcleq" p11, c0, [%1], #128\n" /* d16-d31 */ - "addne %1, %1, #128\n" /* skip missing regs */ + "cmp %2, #0\n" /* -D16 or -D32? */ + stclne" p11, c0, [%1], #128\n" /* d16-d31 */ + "addeq %1, %1, #128\n" /* skip missing regs */ "mrc p10, 7, %0, cr1, c0, 0\n" /* fmxr(VFPSCR) */ "str %0, [%1]\n" /* save vfpscr */ - : "=&r" (vfpscr) : "r" (vfpsave), "r" (is_d32) : "cc"); + : "=&r" (vfpscr) : "r" (vfpsave), "r" (is_d32) : "cc"); } #undef ldcleq #undef stcleq |