11.8Smatt/*	$NetBSD: fpsetround.c,v 1.8 2013/02/03 01:50:54 matt Exp $	*/
21.1Sbjh21
31.7Smatt/*-
41.7Smatt * Copyright (c) 2013 The NetBSD Foundation, Inc.
51.1Sbjh21 * All rights reserved.
61.1Sbjh21 *
71.7Smatt * This code is derived from software contributed to The NetBSD Foundation
81.7Smatt * by Matt Thomas of 3am Software Foundry.
91.7Smatt *
101.1Sbjh21 * Redistribution and use in source and binary forms, with or without
111.1Sbjh21 * modification, are permitted provided that the following conditions
121.1Sbjh21 * are met:
131.1Sbjh21 * 1. Redistributions of source code must retain the above copyright
141.1Sbjh21 *    notice, this list of conditions and the following disclaimer.
151.1Sbjh21 * 2. Redistributions in binary form must reproduce the above copyright
161.1Sbjh21 *    notice, this list of conditions and the following disclaimer in the
171.1Sbjh21 *    documentation and/or other materials provided with the distribution.
181.1Sbjh21 *
191.7Smatt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201.7Smatt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211.7Smatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221.7Smatt * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231.7Smatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241.7Smatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251.7Smatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261.7Smatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271.7Smatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281.7Smatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291.7Smatt * POSSIBILITY OF SUCH DAMAGE.
301.1Sbjh21 */
311.1Sbjh21
321.7Smatt#ifndef __VFP_FP__
331.7Smatt#error FPA is not supported anymore
341.7Smatt#endif
351.7Smatt
361.2Sthorpej#include <sys/cdefs.h>
371.5Slukem#if defined(LIBC_SCCS) && !defined(lint)
381.8Smatt__RCSID("$NetBSD: fpsetround.c,v 1.8 2013/02/03 01:50:54 matt Exp $");
391.5Slukem#endif /* LIBC_SCCS and not lint */
401.2Sthorpej
411.2Sthorpej#include "namespace.h"
421.2Sthorpej
431.1Sbjh21#include <sys/types.h>
441.1Sbjh21#include <ieeefp.h>
451.2Sthorpej
461.8Smatt#include <arm/vfpreg.h>
471.8Smatt
481.2Sthorpej#ifdef __weak_alias
491.2Sthorpej__weak_alias(fpsetround,_fpsetround)
501.2Sthorpej#endif
511.1Sbjh21
521.1Sbjh21/*
531.1Sbjh21 * Return the current FP rounding mode
541.1Sbjh21 */
551.1Sbjh21
561.1Sbjh21fp_rnd
571.7Smattfpsetround(fp_rnd new_rnd)
581.1Sbjh21{
591.7Smatt	__CTASSERT(__SHIFTOUT(VFP_FPSCR_RN, VFP_FPSCR_RMODE) == FP_RN);
601.7Smatt	__CTASSERT(__SHIFTOUT(VFP_FPSCR_RP, VFP_FPSCR_RMODE) == FP_RP);
611.7Smatt	__CTASSERT(__SHIFTOUT(VFP_FPSCR_RM, VFP_FPSCR_RMODE) == FP_RM);
621.7Smatt	__CTASSERT(__SHIFTOUT(VFP_FPSCR_RZ, VFP_FPSCR_RMODE) == FP_RZ);
631.7Smatt	uint32_t fpscr;
641.7Smatt	__asm __volatile("vmrs %0, fpscr" : "=r" (fpscr));
651.7Smatt	fp_rnd old_rnd = __SHIFTOUT(fpscr, VFP_FPSCR_RMODE);
661.7Smatt	fpscr ^= __SHIFTIN(new_rnd ^ old_rnd, VFP_FPSCR_RMODE);
671.7Smatt	__asm __volatile("vmsr fpscr, %0" :: "r" (fpscr));
681.7Smatt	return old_rnd;
691.1Sbjh21}
70