Skip to content

Commit ff720cd

Browse files
dcpleungnashif
authored andcommitted
x86: enable soft float support for Zephyr SDK
This adds the correct compiler and linker flags to support software floating point operations. The flags need to be added to TOOLCHAIN_*_FLAGS for GCC to find the correct library (when calling GCC with --print-libgcc-file-name). Note that software floating point needs to be turned on for Newlib. This is due to Newlib having floating point numbers in its various printf() functions which results in floating point instructions being emitted from toolchain. These instructions are placed very early in the functions which results in them being executed even though the format string contains no floating point conversions. Without using CONFIG_FPU to enable hardware floating point support, any calls to printf() like functions will result in exceptions complaining FPU is not available. Although forcing CONFIG_FPU=y with newlib is an option, and because the OS doesn't know which threads would call these printf() functions, Zephyr has to assume all threads are using FPU and thus incurring performance penalty as every context switching now needs to save FPU registers. A compromise here is to use soft float instead. Newlib with soft float enabled does not have floating point instructions and yet can still support its printf() like functions. Signed-off-by: Daniel Leung <[email protected]>
1 parent d0dd2ac commit ff720cd

File tree

4 files changed

+301
-1
lines changed

4 files changed

+301
-1
lines changed

arch/x86/core/Kconfig.ia32

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ config X86_PAE
8686
more memory for paging structures.
8787

8888
menu "Architecture Floating Point Options"
89-
depends on CPU_HAS_FPU
89+
90+
if CPU_HAS_FPU
9091

9192
config SSE
9293
bool "SSE registers"
@@ -138,6 +139,15 @@ config LAZY_FPU_SHARING
138139
malware to read the contents of all floating point registers, see
139140
CVE-2018-3665.
140141

142+
endif # CPU_HAS_FPU
143+
144+
config X86_FP_USE_SOFT_FLOAT
145+
bool
146+
prompt "Use Software Floating Point Operations" if !(NEWLIB_LIBC && !FPU)
147+
default y if NEWLIB_LIBC && !FPU
148+
help
149+
Enable using software floating point operations.
150+
141151
endmenu
142152

143153
config DCACHE_LINE_SIZE

arch/x86/core/ia32.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,8 @@ zephyr_library_sources_ifdef(
3333

3434
# Last since we declare default exception handlers here
3535
zephyr_library_sources(ia32/fatal.c)
36+
37+
zephyr_library_sources_ifdef(
38+
CONFIG_X86_FP_USE_SOFT_FLOAT
39+
ia32/soft_float_stubs.c
40+
)
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
/*
2+
* Copyright (c) 2021 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <kernel.h>
8+
#include <toolchain.h>
9+
10+
/**
11+
* @file
12+
* @brief Provide soft float function stubs for long double operations.
13+
*
14+
* GCC soft float does not support long double so these need to be
15+
* stubbed out.
16+
*
17+
* The function names come from the GCC public documentation.
18+
*/
19+
20+
extern void abort(void);
21+
22+
__weak void __addtf3(long double a, long double b)
23+
{
24+
k_oops();
25+
}
26+
27+
__weak void __addxf3(long double a, long double b)
28+
{
29+
k_oops();
30+
}
31+
32+
__weak void __subtf3(long double a, long double b)
33+
{
34+
k_oops();
35+
}
36+
37+
__weak void __subxf3(long double a, long double b)
38+
{
39+
k_oops();
40+
}
41+
42+
__weak void __multf3(long double a, long double b)
43+
{
44+
k_oops();
45+
}
46+
47+
__weak void __mulxf3(long double a, long double b)
48+
{
49+
k_oops();
50+
}
51+
52+
__weak void __divtf3(long double a, long double b)
53+
{
54+
k_oops();
55+
}
56+
57+
__weak void __divxf3(long double a, long double b)
58+
{
59+
k_oops();
60+
}
61+
62+
__weak void __negtf2(long double a)
63+
{
64+
k_oops();
65+
}
66+
67+
__weak void __negxf2(long double a)
68+
{
69+
k_oops();
70+
}
71+
72+
__weak void __extendsftf2(float a)
73+
{
74+
k_oops();
75+
}
76+
77+
__weak void __extendsfxf2(float a)
78+
{
79+
k_oops();
80+
}
81+
82+
__weak void __extenddftf2(double a)
83+
{
84+
k_oops();
85+
}
86+
87+
__weak void __extenddfxf2(double a)
88+
{
89+
k_oops();
90+
}
91+
92+
__weak void __truncxfdf2(long double a)
93+
{
94+
k_oops();
95+
}
96+
97+
__weak void __trunctfdf2(long double a)
98+
{
99+
k_oops();
100+
}
101+
102+
__weak void __truncxfsf2(long double a)
103+
{
104+
k_oops();
105+
}
106+
107+
__weak void __trunctfsf2(long double a)
108+
{
109+
k_oops();
110+
}
111+
112+
__weak void __fixtfsi(long double a)
113+
{
114+
k_oops();
115+
}
116+
117+
__weak void __fixxfsi(long double a)
118+
{
119+
k_oops();
120+
}
121+
122+
__weak void __fixtfdi(long double a)
123+
{
124+
k_oops();
125+
}
126+
127+
__weak void __fixxfdi(long double a)
128+
{
129+
k_oops();
130+
}
131+
132+
__weak void __fixtfti(long double a)
133+
{
134+
k_oops();
135+
}
136+
137+
__weak void __fixxfti(long double a)
138+
{
139+
k_oops();
140+
}
141+
142+
__weak void __fixunstfsi(long double a)
143+
{
144+
k_oops();
145+
}
146+
147+
__weak void __fixunsxfsi(long double a)
148+
{
149+
k_oops();
150+
}
151+
152+
__weak void __fixunstfdi(long double a)
153+
{
154+
k_oops();
155+
}
156+
157+
__weak void __fixunsxfdi(long double a)
158+
{
159+
k_oops();
160+
}
161+
162+
__weak void __fixunstfti(long double a)
163+
{
164+
k_oops();
165+
}
166+
167+
__weak void __fixunsxfti(long double a)
168+
{
169+
k_oops();
170+
}
171+
172+
__weak void __floatsitf(int i)
173+
{
174+
k_oops();
175+
}
176+
177+
__weak void __floatsixf(int i)
178+
{
179+
k_oops();
180+
}
181+
182+
__weak void __floatditf(long i)
183+
{
184+
k_oops();
185+
}
186+
187+
__weak void __floatdixf(long i)
188+
{
189+
k_oops();
190+
}
191+
192+
__weak void __floattitf(long long i)
193+
{
194+
k_oops();
195+
}
196+
197+
__weak void __floattixf(long long i)
198+
{
199+
k_oops();
200+
}
201+
202+
__weak void __floatunsitf(unsigned int i)
203+
{
204+
k_oops();
205+
}
206+
207+
__weak void __floatunsixf(unsigned int i)
208+
{
209+
k_oops();
210+
}
211+
212+
__weak void __floatunditf(unsigned long i)
213+
{
214+
k_oops();
215+
}
216+
217+
__weak void __floatundixf(unsigned long i)
218+
{
219+
k_oops();
220+
}
221+
222+
__weak void __floatuntitf(unsigned long long i)
223+
{
224+
k_oops();
225+
}
226+
227+
__weak void __floatuntixf(unsigned long long i)
228+
{
229+
k_oops();
230+
}
231+
232+
__weak void __cmptf2(long double a, long double b)
233+
{
234+
k_oops();
235+
}
236+
237+
__weak void __unordtf2(long double a, long double b)
238+
{
239+
k_oops();
240+
}
241+
242+
__weak void __eqtf2(long double a, long double b)
243+
{
244+
k_oops();
245+
}
246+
247+
__weak void __netf2(long double a, long double b)
248+
{
249+
k_oops();
250+
}
251+
252+
__weak void __getf2(long double a, long double b)
253+
{
254+
k_oops();
255+
}
256+
257+
__weak void __lttf2(long double a, long double b)
258+
{
259+
k_oops();
260+
}
261+
262+
__weak void __letf2(long double a, long double b)
263+
{
264+
k_oops();
265+
}
266+
267+
__weak void __gttf2(long double a, long double b)
268+
{
269+
k_oops();
270+
}
271+
272+
__weak void __powitf2(long double a, int b)
273+
{
274+
k_oops();
275+
}
276+
277+
__weak void __powixf2(long double a, int b)
278+
{
279+
k_oops();
280+
}

cmake/compiler/gcc/target_x86.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ else()
88
string(PREPEND CMAKE_ASM_FLAGS "-m32 ")
99
string(PREPEND CMAKE_C_FLAGS "-m32 ")
1010
string(PREPEND CMAKE_CXX_FLAGS "-m32 ")
11+
12+
if(CONFIG_X86_FP_USE_SOFT_FLOAT)
13+
list(APPEND TOOLCHAIN_C_FLAGS -msoft-float)
14+
list(APPEND TOOLCHAIN_LD_FLAGS -msoft-float)
15+
endif()
1116
endif()
1217

1318
# GNU Assembler, by default on non-Linux targets, treats slashes as

0 commit comments

Comments
 (0)