1 /*
2  * Copyright (C) 2016-2017 Andes Technology, Inc.
3  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
4  */
5 
6 /* Raise given exceptions.
7    Copyright (C) 2004-2013 Free Software Foundation, Inc.
8 
9    The GNU C Library is free software; you can redistribute it and/or
10    modify it under the terms of the GNU Lesser General Public
11    License as published by the Free Software Foundation; either
12    version 2.1 of the License, or (at your option) any later version.
13 
14    The GNU C Library is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    Lesser General Public License for more details.
18 
19    You should have received a copy of the GNU Lesser General Public
20    License along with the GNU C Library.  If not, see
21    <http://www.gnu.org/licenses/>.  */
22 
23 #include <fpu_control.h>
24 #include <fenv.h>
25 #include <float.h>
26 #include "fenv_libc.h"
27 
28 int
feraiseexcept(int excepts)29 feraiseexcept (int excepts)
30 {
31 #ifdef __NDS32_ABI_2FP_PLUS__
32 	float temp1 = 0.0, temp2 = 1.0;
33 	if (FE_INVALID & excepts)
34 	{
35 		__asm__ volatile(
36 			"fmtsr\t %0, $fs0\n\t"
37 			"fdivs\t $fs0, $fs0, $fs0\n\t"
38 			:
39 			:"r"(temp1)
40 			:"$fs0"
41 			);
42 	}
43 	if (FE_DIVBYZERO & excepts)
44 	{
45 		__asm__ volatile(
46 			"fmtsr\t %0, $fs0\n\t"
47 			"fmtsr\t %1, $fs1\n\t"
48 			"fdivs\t $fs0, $fs1, $fs0\n\t"
49 			:
50 			:"r"(temp1),"r"(temp2)
51 			:"$fs0"
52 			);
53 	}
54 	if (FE_OVERFLOW & excepts)
55 	{
56 	/* There's no way to raise overflow without also raising inexact.
57 	*/
58 		unsigned int fpcsr;
59 		temp1 = FLT_MAX;
60 		__asm__ volatile(
61 			"fmfcsr\t %0\n\t"
62 			"fmtsr\t %1, $fs0\n\t"
63 			"fadds\t $fs0, $fs0, $fs0\n\t"
64 			"ori\t %0,%0,0x10\n\t"
65 			"fmtcsr\t %0\n\t"
66 			:"=&r"(fpcsr)
67 			:"r"(temp1)
68 			:"$fs0"
69 			);
70 	}
71 	if (FE_UNDERFLOW & excepts)
72 	{
73 	/* There's no way to raise overflow without also raising inexact.
74 	*/
75 		temp1 = FLT_MIN;
76 		temp2 = 2.0;
77 		__asm__ volatile(
78 			"fmtsr\t %0, $fs0\n\t"
79 			"fmtsr\t %1, $fs1\n\t"
80 			"fdivs\t $fs1, $fs0, $fs1\n\t"
81 			:
82 			:"r"(temp1),"r"(temp2)
83 			:"$fs0","$fs1"
84 			);
85 	}
86 	if (FE_INEXACT & excepts)
87 	{
88 		temp1 = 3.0;
89 		__asm__ volatile(
90 			"fmtsr\t %0, $fs1\n\t"
91 			"fmtsr\t %1, $fs0\n\t"
92 			"fdivs\t $fs1, $fs0, $fs1\n\t"
93 			:
94 			:"r"(temp1),"r"(temp2)
95 			:"$fs0","$fs1"
96 			);
97 	}
98 
99 	return 0;
100 
101 #endif
102 	/* Unsupported, so fail unless nothing needs to be done.  */
103 	return (excepts != 0);
104 }
105