1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth * FPU op helpers
3fcf5ef2aSThomas Huth *
4fcf5ef2aSThomas Huth * Copyright (c) 2003-2005 Fabrice Bellard
5fcf5ef2aSThomas Huth *
6fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or
7fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public
8fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either
95650b549SChetan Pant * version 2.1 of the License, or (at your option) any later version.
10fcf5ef2aSThomas Huth *
11fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful,
12fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of
13fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14fcf5ef2aSThomas Huth * Lesser General Public License for more details.
15fcf5ef2aSThomas Huth *
16fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public
17fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18fcf5ef2aSThomas Huth */
19fcf5ef2aSThomas Huth
20fcf5ef2aSThomas Huth #include "qemu/osdep.h"
21fcf5ef2aSThomas Huth #include "cpu.h"
22fcf5ef2aSThomas Huth #include "exec/exec-all.h"
23fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
2424f91e81SAlex Bennée #include "fpu/softfloat.h"
25fcf5ef2aSThomas Huth
f128_in(Int128 i)26e41716beSRichard Henderson static inline float128 f128_in(Int128 i)
27e41716beSRichard Henderson {
28e41716beSRichard Henderson union {
29e41716beSRichard Henderson Int128 i;
30e41716beSRichard Henderson float128 f;
31e41716beSRichard Henderson } u;
32e41716beSRichard Henderson
33e41716beSRichard Henderson u.i = i;
34e41716beSRichard Henderson return u.f;
35e41716beSRichard Henderson }
36e41716beSRichard Henderson
f128_ret(float128 f)37e41716beSRichard Henderson static inline Int128 f128_ret(float128 f)
38e41716beSRichard Henderson {
39e41716beSRichard Henderson union {
40e41716beSRichard Henderson Int128 i;
41e41716beSRichard Henderson float128 f;
42e41716beSRichard Henderson } u;
43e41716beSRichard Henderson
44e41716beSRichard Henderson u.f = f;
45e41716beSRichard Henderson return u.i;
46e41716beSRichard Henderson }
47e41716beSRichard Henderson
check_ieee_exceptions(CPUSPARCState * env,uintptr_t ra)48db713911SRichard Henderson static void check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra)
49fcf5ef2aSThomas Huth {
50fcf5ef2aSThomas Huth target_ulong status = get_float_exception_flags(&env->fp_status);
513590f01eSRichard Henderson uint32_t cexc = 0;
52efeb8b07SRichard Henderson
53fcf5ef2aSThomas Huth if (unlikely(status)) {
54fcf5ef2aSThomas Huth /* Keep exception flags clear for next time. */
55fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
56fcf5ef2aSThomas Huth
57fcf5ef2aSThomas Huth /* Copy IEEE 754 flags into FSR */
58fcf5ef2aSThomas Huth if (status & float_flag_invalid) {
593590f01eSRichard Henderson cexc |= FSR_NVC;
60fcf5ef2aSThomas Huth }
61fcf5ef2aSThomas Huth if (status & float_flag_overflow) {
623590f01eSRichard Henderson cexc |= FSR_OFC;
63fcf5ef2aSThomas Huth }
64fcf5ef2aSThomas Huth if (status & float_flag_underflow) {
653590f01eSRichard Henderson cexc |= FSR_UFC;
66fcf5ef2aSThomas Huth }
67fcf5ef2aSThomas Huth if (status & float_flag_divbyzero) {
683590f01eSRichard Henderson cexc |= FSR_DZC;
69fcf5ef2aSThomas Huth }
70fcf5ef2aSThomas Huth if (status & float_flag_inexact) {
713590f01eSRichard Henderson cexc |= FSR_NXC;
72fcf5ef2aSThomas Huth }
73fcf5ef2aSThomas Huth
743590f01eSRichard Henderson if (cexc & (env->fsr >> FSR_TEM_SHIFT)) {
753590f01eSRichard Henderson /* Unmasked exception, generate an IEEE trap. */
763590f01eSRichard Henderson env->fsr_cexc_ftt = cexc | FSR_FTT_IEEE_EXCP;
773590f01eSRichard Henderson cpu_raise_exception_ra(env, TT_FP_EXCP, ra);
783590f01eSRichard Henderson }
79fcf5ef2aSThomas Huth
80fcf5ef2aSThomas Huth /* Accumulate exceptions */
813590f01eSRichard Henderson env->fsr |= cexc << FSR_AEXC_SHIFT;
82fcf5ef2aSThomas Huth }
83fcf5ef2aSThomas Huth
843590f01eSRichard Henderson /* No trap, so FTT is cleared. */
853590f01eSRichard Henderson env->fsr_cexc_ftt = cexc;
86fcf5ef2aSThomas Huth }
87fcf5ef2aSThomas Huth
helper_fadds(CPUSPARCState * env,float32 src1,float32 src2)88db713911SRichard Henderson float32 helper_fadds(CPUSPARCState *env, float32 src1, float32 src2)
89fcf5ef2aSThomas Huth {
90db713911SRichard Henderson float32 ret = float32_add(src1, src2, &env->fp_status);
91db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
92db713911SRichard Henderson return ret;
93fcf5ef2aSThomas Huth }
94fcf5ef2aSThomas Huth
helper_fsubs(CPUSPARCState * env,float32 src1,float32 src2)95db713911SRichard Henderson float32 helper_fsubs(CPUSPARCState *env, float32 src1, float32 src2)
96db713911SRichard Henderson {
97db713911SRichard Henderson float32 ret = float32_sub(src1, src2, &env->fp_status);
98db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
99db713911SRichard Henderson return ret;
100fcf5ef2aSThomas Huth }
101fcf5ef2aSThomas Huth
helper_fmuls(CPUSPARCState * env,float32 src1,float32 src2)102db713911SRichard Henderson float32 helper_fmuls(CPUSPARCState *env, float32 src1, float32 src2)
103db713911SRichard Henderson {
104db713911SRichard Henderson float32 ret = float32_mul(src1, src2, &env->fp_status);
105db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
106db713911SRichard Henderson return ret;
107db713911SRichard Henderson }
108db713911SRichard Henderson
helper_fdivs(CPUSPARCState * env,float32 src1,float32 src2)109db713911SRichard Henderson float32 helper_fdivs(CPUSPARCState *env, float32 src1, float32 src2)
110db713911SRichard Henderson {
111db713911SRichard Henderson float32 ret = float32_div(src1, src2, &env->fp_status);
112db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
113db713911SRichard Henderson return ret;
114db713911SRichard Henderson }
115db713911SRichard Henderson
helper_faddd(CPUSPARCState * env,float64 src1,float64 src2)116db713911SRichard Henderson float64 helper_faddd(CPUSPARCState *env, float64 src1, float64 src2)
117db713911SRichard Henderson {
118db713911SRichard Henderson float64 ret = float64_add(src1, src2, &env->fp_status);
119db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
120db713911SRichard Henderson return ret;
121db713911SRichard Henderson }
122db713911SRichard Henderson
helper_fsubd(CPUSPARCState * env,float64 src1,float64 src2)123db713911SRichard Henderson float64 helper_fsubd(CPUSPARCState *env, float64 src1, float64 src2)
124db713911SRichard Henderson {
125db713911SRichard Henderson float64 ret = float64_sub(src1, src2, &env->fp_status);
126db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
127db713911SRichard Henderson return ret;
128db713911SRichard Henderson }
129db713911SRichard Henderson
helper_fmuld(CPUSPARCState * env,float64 src1,float64 src2)130db713911SRichard Henderson float64 helper_fmuld(CPUSPARCState *env, float64 src1, float64 src2)
131db713911SRichard Henderson {
132db713911SRichard Henderson float64 ret = float64_mul(src1, src2, &env->fp_status);
133db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
134db713911SRichard Henderson return ret;
135db713911SRichard Henderson }
136db713911SRichard Henderson
helper_fdivd(CPUSPARCState * env,float64 src1,float64 src2)137db713911SRichard Henderson float64 helper_fdivd(CPUSPARCState *env, float64 src1, float64 src2)
138db713911SRichard Henderson {
139db713911SRichard Henderson float64 ret = float64_div(src1, src2, &env->fp_status);
140db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
141db713911SRichard Henderson return ret;
142db713911SRichard Henderson }
143db713911SRichard Henderson
helper_faddq(CPUSPARCState * env,Int128 src1,Int128 src2)144db713911SRichard Henderson Int128 helper_faddq(CPUSPARCState *env, Int128 src1, Int128 src2)
145db713911SRichard Henderson {
146db713911SRichard Henderson float128 ret = float128_add(f128_in(src1), f128_in(src2), &env->fp_status);
147db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
148db713911SRichard Henderson return f128_ret(ret);
149db713911SRichard Henderson }
150db713911SRichard Henderson
helper_fsubq(CPUSPARCState * env,Int128 src1,Int128 src2)151db713911SRichard Henderson Int128 helper_fsubq(CPUSPARCState *env, Int128 src1, Int128 src2)
152db713911SRichard Henderson {
153db713911SRichard Henderson float128 ret = float128_sub(f128_in(src1), f128_in(src2), &env->fp_status);
154db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
155db713911SRichard Henderson return f128_ret(ret);
156db713911SRichard Henderson }
157db713911SRichard Henderson
helper_fmulq(CPUSPARCState * env,Int128 src1,Int128 src2)158db713911SRichard Henderson Int128 helper_fmulq(CPUSPARCState *env, Int128 src1, Int128 src2)
159db713911SRichard Henderson {
160db713911SRichard Henderson float128 ret = float128_mul(f128_in(src1), f128_in(src2), &env->fp_status);
161db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
162db713911SRichard Henderson return f128_ret(ret);
163db713911SRichard Henderson }
164db713911SRichard Henderson
helper_fdivq(CPUSPARCState * env,Int128 src1,Int128 src2)165db713911SRichard Henderson Int128 helper_fdivq(CPUSPARCState *env, Int128 src1, Int128 src2)
166db713911SRichard Henderson {
167db713911SRichard Henderson float128 ret = float128_div(f128_in(src1), f128_in(src2), &env->fp_status);
168db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
169db713911SRichard Henderson return f128_ret(ret);
170db713911SRichard Henderson }
171fcf5ef2aSThomas Huth
helper_fsmuld(CPUSPARCState * env,float32 src1,float32 src2)172fcf5ef2aSThomas Huth float64 helper_fsmuld(CPUSPARCState *env, float32 src1, float32 src2)
173fcf5ef2aSThomas Huth {
174db713911SRichard Henderson float64 ret = float64_mul(float32_to_float64(src1, &env->fp_status),
175fcf5ef2aSThomas Huth float32_to_float64(src2, &env->fp_status),
176fcf5ef2aSThomas Huth &env->fp_status);
177db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
178db713911SRichard Henderson return ret;
179fcf5ef2aSThomas Huth }
180fcf5ef2aSThomas Huth
helper_fdmulq(CPUSPARCState * env,float64 src1,float64 src2)181ba21dc99SRichard Henderson Int128 helper_fdmulq(CPUSPARCState *env, float64 src1, float64 src2)
182fcf5ef2aSThomas Huth {
183db713911SRichard Henderson float128 ret = float128_mul(float64_to_float128(src1, &env->fp_status),
184fcf5ef2aSThomas Huth float64_to_float128(src2, &env->fp_status),
185db713911SRichard Henderson &env->fp_status);
186db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
187db713911SRichard Henderson return f128_ret(ret);
188fcf5ef2aSThomas Huth }
189fcf5ef2aSThomas Huth
190fcf5ef2aSThomas Huth /* Integer to float conversion. */
helper_fitos(CPUSPARCState * env,int32_t src)191fcf5ef2aSThomas Huth float32 helper_fitos(CPUSPARCState *env, int32_t src)
192fcf5ef2aSThomas Huth {
193db713911SRichard Henderson float32 ret = int32_to_float32(src, &env->fp_status);
194db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
195db713911SRichard Henderson return ret;
196fcf5ef2aSThomas Huth }
197fcf5ef2aSThomas Huth
helper_fitod(CPUSPARCState * env,int32_t src)198fcf5ef2aSThomas Huth float64 helper_fitod(CPUSPARCState *env, int32_t src)
199fcf5ef2aSThomas Huth {
200db713911SRichard Henderson float64 ret = int32_to_float64(src, &env->fp_status);
201db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
202db713911SRichard Henderson return ret;
203fcf5ef2aSThomas Huth }
204fcf5ef2aSThomas Huth
helper_fitoq(CPUSPARCState * env,int32_t src)2050b2a61ccSRichard Henderson Int128 helper_fitoq(CPUSPARCState *env, int32_t src)
206fcf5ef2aSThomas Huth {
207db713911SRichard Henderson float128 ret = int32_to_float128(src, &env->fp_status);
208db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
209db713911SRichard Henderson return f128_ret(ret);
210fcf5ef2aSThomas Huth }
211fcf5ef2aSThomas Huth
212fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
helper_fxtos(CPUSPARCState * env,int64_t src)213fcf5ef2aSThomas Huth float32 helper_fxtos(CPUSPARCState *env, int64_t src)
214fcf5ef2aSThomas Huth {
215db713911SRichard Henderson float32 ret = int64_to_float32(src, &env->fp_status);
216db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
217db713911SRichard Henderson return ret;
218fcf5ef2aSThomas Huth }
219fcf5ef2aSThomas Huth
helper_fxtod(CPUSPARCState * env,int64_t src)220fcf5ef2aSThomas Huth float64 helper_fxtod(CPUSPARCState *env, int64_t src)
221fcf5ef2aSThomas Huth {
222db713911SRichard Henderson float64 ret = int64_to_float64(src, &env->fp_status);
223db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
224db713911SRichard Henderson return ret;
225fcf5ef2aSThomas Huth }
226fcf5ef2aSThomas Huth
helper_fxtoq(CPUSPARCState * env,int64_t src)227fdc50716SRichard Henderson Int128 helper_fxtoq(CPUSPARCState *env, int64_t src)
228fcf5ef2aSThomas Huth {
229db713911SRichard Henderson float128 ret = int64_to_float128(src, &env->fp_status);
230db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
231db713911SRichard Henderson return f128_ret(ret);
232fcf5ef2aSThomas Huth }
233fcf5ef2aSThomas Huth #endif
234fcf5ef2aSThomas Huth
235fcf5ef2aSThomas Huth /* floating point conversion */
helper_fdtos(CPUSPARCState * env,float64 src)236fcf5ef2aSThomas Huth float32 helper_fdtos(CPUSPARCState *env, float64 src)
237fcf5ef2aSThomas Huth {
238db713911SRichard Henderson float32 ret = float64_to_float32(src, &env->fp_status);
239db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
240db713911SRichard Henderson return ret;
241fcf5ef2aSThomas Huth }
242fcf5ef2aSThomas Huth
helper_fstod(CPUSPARCState * env,float32 src)243fcf5ef2aSThomas Huth float64 helper_fstod(CPUSPARCState *env, float32 src)
244fcf5ef2aSThomas Huth {
245db713911SRichard Henderson float64 ret = float32_to_float64(src, &env->fp_status);
246db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
247db713911SRichard Henderson return ret;
248fcf5ef2aSThomas Huth }
249fcf5ef2aSThomas Huth
helper_fqtos(CPUSPARCState * env,Int128 src)250d81e3efeSRichard Henderson float32 helper_fqtos(CPUSPARCState *env, Int128 src)
251fcf5ef2aSThomas Huth {
252db713911SRichard Henderson float32 ret = float128_to_float32(f128_in(src), &env->fp_status);
253db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
254db713911SRichard Henderson return ret;
255fcf5ef2aSThomas Huth }
256fcf5ef2aSThomas Huth
helper_fstoq(CPUSPARCState * env,float32 src)2570b2a61ccSRichard Henderson Int128 helper_fstoq(CPUSPARCState *env, float32 src)
258fcf5ef2aSThomas Huth {
259db713911SRichard Henderson float128 ret = float32_to_float128(src, &env->fp_status);
260db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
261db713911SRichard Henderson return f128_ret(ret);
262fcf5ef2aSThomas Huth }
263fcf5ef2aSThomas Huth
helper_fqtod(CPUSPARCState * env,Int128 src)26425a5769eSRichard Henderson float64 helper_fqtod(CPUSPARCState *env, Int128 src)
265fcf5ef2aSThomas Huth {
266db713911SRichard Henderson float64 ret = float128_to_float64(f128_in(src), &env->fp_status);
267db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
268db713911SRichard Henderson return ret;
269fcf5ef2aSThomas Huth }
270fcf5ef2aSThomas Huth
helper_fdtoq(CPUSPARCState * env,float64 src)271fdc50716SRichard Henderson Int128 helper_fdtoq(CPUSPARCState *env, float64 src)
272fcf5ef2aSThomas Huth {
273db713911SRichard Henderson float128 ret = float64_to_float128(src, &env->fp_status);
274db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
275db713911SRichard Henderson return f128_ret(ret);
276fcf5ef2aSThomas Huth }
277fcf5ef2aSThomas Huth
278fcf5ef2aSThomas Huth /* Float to integer conversion. */
helper_fstoi(CPUSPARCState * env,float32 src)279fcf5ef2aSThomas Huth int32_t helper_fstoi(CPUSPARCState *env, float32 src)
280fcf5ef2aSThomas Huth {
281db713911SRichard Henderson int32_t ret = float32_to_int32_round_to_zero(src, &env->fp_status);
282db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
283db713911SRichard Henderson return ret;
284fcf5ef2aSThomas Huth }
285fcf5ef2aSThomas Huth
helper_fdtoi(CPUSPARCState * env,float64 src)286fcf5ef2aSThomas Huth int32_t helper_fdtoi(CPUSPARCState *env, float64 src)
287fcf5ef2aSThomas Huth {
288db713911SRichard Henderson int32_t ret = float64_to_int32_round_to_zero(src, &env->fp_status);
289db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
290db713911SRichard Henderson return ret;
291fcf5ef2aSThomas Huth }
292fcf5ef2aSThomas Huth
helper_fqtoi(CPUSPARCState * env,Int128 src)293d81e3efeSRichard Henderson int32_t helper_fqtoi(CPUSPARCState *env, Int128 src)
294fcf5ef2aSThomas Huth {
295db713911SRichard Henderson int32_t ret = float128_to_int32_round_to_zero(f128_in(src),
296db713911SRichard Henderson &env->fp_status);
297db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
298db713911SRichard Henderson return ret;
299fcf5ef2aSThomas Huth }
300fcf5ef2aSThomas Huth
301fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
helper_fstox(CPUSPARCState * env,float32 src)302fcf5ef2aSThomas Huth int64_t helper_fstox(CPUSPARCState *env, float32 src)
303fcf5ef2aSThomas Huth {
304db713911SRichard Henderson int64_t ret = float32_to_int64_round_to_zero(src, &env->fp_status);
305db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
306db713911SRichard Henderson return ret;
307fcf5ef2aSThomas Huth }
308fcf5ef2aSThomas Huth
helper_fdtox(CPUSPARCState * env,float64 src)309fcf5ef2aSThomas Huth int64_t helper_fdtox(CPUSPARCState *env, float64 src)
310fcf5ef2aSThomas Huth {
311db713911SRichard Henderson int64_t ret = float64_to_int64_round_to_zero(src, &env->fp_status);
312db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
313db713911SRichard Henderson return ret;
314fcf5ef2aSThomas Huth }
315fcf5ef2aSThomas Huth
helper_fqtox(CPUSPARCState * env,Int128 src)31625a5769eSRichard Henderson int64_t helper_fqtox(CPUSPARCState *env, Int128 src)
317fcf5ef2aSThomas Huth {
318db713911SRichard Henderson int64_t ret = float128_to_int64_round_to_zero(f128_in(src),
319db713911SRichard Henderson &env->fp_status);
320db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
321db713911SRichard Henderson return ret;
322fcf5ef2aSThomas Huth }
323fcf5ef2aSThomas Huth #endif
324fcf5ef2aSThomas Huth
helper_fsqrts(CPUSPARCState * env,float32 src)325fcf5ef2aSThomas Huth float32 helper_fsqrts(CPUSPARCState *env, float32 src)
326fcf5ef2aSThomas Huth {
327db713911SRichard Henderson float32 ret = float32_sqrt(src, &env->fp_status);
328db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
329db713911SRichard Henderson return ret;
330fcf5ef2aSThomas Huth }
331fcf5ef2aSThomas Huth
helper_fsqrtd(CPUSPARCState * env,float64 src)332fcf5ef2aSThomas Huth float64 helper_fsqrtd(CPUSPARCState *env, float64 src)
333fcf5ef2aSThomas Huth {
334db713911SRichard Henderson float64 ret = float64_sqrt(src, &env->fp_status);
335db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
336db713911SRichard Henderson return ret;
337fcf5ef2aSThomas Huth }
338fcf5ef2aSThomas Huth
helper_fsqrtq(CPUSPARCState * env,Int128 src)339e41716beSRichard Henderson Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src)
340fcf5ef2aSThomas Huth {
341db713911SRichard Henderson float128 ret = float128_sqrt(f128_in(src), &env->fp_status);
342db713911SRichard Henderson check_ieee_exceptions(env, GETPC());
343db713911SRichard Henderson return f128_ret(ret);
344fcf5ef2aSThomas Huth }
345fcf5ef2aSThomas Huth
helper_fmadds(CPUSPARCState * env,float32 s1,float32 s2,float32 s3,uint32_t op)3464fd71d19SRichard Henderson float32 helper_fmadds(CPUSPARCState *env, float32 s1,
3474fd71d19SRichard Henderson float32 s2, float32 s3, uint32_t op)
3484fd71d19SRichard Henderson {
3494fd71d19SRichard Henderson float32 ret = float32_muladd(s1, s2, s3, op, &env->fp_status);
3504fd71d19SRichard Henderson check_ieee_exceptions(env, GETPC());
3514fd71d19SRichard Henderson return ret;
3524fd71d19SRichard Henderson }
3534fd71d19SRichard Henderson
helper_fmaddd(CPUSPARCState * env,float64 s1,float64 s2,float64 s3,uint32_t op)3544fd71d19SRichard Henderson float64 helper_fmaddd(CPUSPARCState *env, float64 s1,
3554fd71d19SRichard Henderson float64 s2, float64 s3, uint32_t op)
3564fd71d19SRichard Henderson {
3574fd71d19SRichard Henderson float64 ret = float64_muladd(s1, s2, s3, op, &env->fp_status);
3584fd71d19SRichard Henderson check_ieee_exceptions(env, GETPC());
3594fd71d19SRichard Henderson return ret;
3604fd71d19SRichard Henderson }
3614fd71d19SRichard Henderson
helper_fnadds(CPUSPARCState * env,float32 src1,float32 src2)3623d50b728SRichard Henderson float32 helper_fnadds(CPUSPARCState *env, float32 src1, float32 src2)
3633d50b728SRichard Henderson {
3643d50b728SRichard Henderson float32 ret = float32_add(src1, src2, &env->fp_status);
3653d50b728SRichard Henderson
3663d50b728SRichard Henderson /*
3673d50b728SRichard Henderson * NaN inputs or result do not get a sign change.
3683d50b728SRichard Henderson * Nor, apparently, does zero: on hardware, -(x + -x) yields +0.
3693d50b728SRichard Henderson */
3703d50b728SRichard Henderson if (!float32_is_any_nan(ret) && !float32_is_zero(ret)) {
3713d50b728SRichard Henderson ret = float32_chs(ret);
3723d50b728SRichard Henderson }
3733d50b728SRichard Henderson check_ieee_exceptions(env, GETPC());
3743d50b728SRichard Henderson return ret;
3753d50b728SRichard Henderson }
3763d50b728SRichard Henderson
helper_fnmuls(CPUSPARCState * env,float32 src1,float32 src2)3773d50b728SRichard Henderson float32 helper_fnmuls(CPUSPARCState *env, float32 src1, float32 src2)
3783d50b728SRichard Henderson {
3793d50b728SRichard Henderson float32 ret = float32_mul(src1, src2, &env->fp_status);
3803d50b728SRichard Henderson
3813d50b728SRichard Henderson /* NaN inputs or result do not get a sign change. */
3823d50b728SRichard Henderson if (!float32_is_any_nan(ret)) {
3833d50b728SRichard Henderson ret = float32_chs(ret);
3843d50b728SRichard Henderson }
3853d50b728SRichard Henderson check_ieee_exceptions(env, GETPC());
3863d50b728SRichard Henderson return ret;
3873d50b728SRichard Henderson }
3883d50b728SRichard Henderson
helper_fnaddd(CPUSPARCState * env,float64 src1,float64 src2)3893d50b728SRichard Henderson float64 helper_fnaddd(CPUSPARCState *env, float64 src1, float64 src2)
3903d50b728SRichard Henderson {
3913d50b728SRichard Henderson float64 ret = float64_add(src1, src2, &env->fp_status);
3923d50b728SRichard Henderson
3933d50b728SRichard Henderson /*
3943d50b728SRichard Henderson * NaN inputs or result do not get a sign change.
3953d50b728SRichard Henderson * Nor, apparently, does zero: on hardware, -(x + -x) yields +0.
3963d50b728SRichard Henderson */
3973d50b728SRichard Henderson if (!float64_is_any_nan(ret) && !float64_is_zero(ret)) {
3983d50b728SRichard Henderson ret = float64_chs(ret);
3993d50b728SRichard Henderson }
4003d50b728SRichard Henderson check_ieee_exceptions(env, GETPC());
4013d50b728SRichard Henderson return ret;
4023d50b728SRichard Henderson }
4033d50b728SRichard Henderson
helper_fnmuld(CPUSPARCState * env,float64 src1,float64 src2)4043d50b728SRichard Henderson float64 helper_fnmuld(CPUSPARCState *env, float64 src1, float64 src2)
4053d50b728SRichard Henderson {
4063d50b728SRichard Henderson float64 ret = float64_mul(src1, src2, &env->fp_status);
4073d50b728SRichard Henderson
4083d50b728SRichard Henderson /* NaN inputs or result do not get a sign change. */
4093d50b728SRichard Henderson if (!float64_is_any_nan(ret)) {
4103d50b728SRichard Henderson ret = float64_chs(ret);
4113d50b728SRichard Henderson }
4123d50b728SRichard Henderson check_ieee_exceptions(env, GETPC());
4133d50b728SRichard Henderson return ret;
4143d50b728SRichard Henderson }
4153d50b728SRichard Henderson
helper_fnsmuld(CPUSPARCState * env,float32 src1,float32 src2)4163d50b728SRichard Henderson float64 helper_fnsmuld(CPUSPARCState *env, float32 src1, float32 src2)
4173d50b728SRichard Henderson {
4183d50b728SRichard Henderson float64 ret = float64_mul(float32_to_float64(src1, &env->fp_status),
4193d50b728SRichard Henderson float32_to_float64(src2, &env->fp_status),
4203d50b728SRichard Henderson &env->fp_status);
4213d50b728SRichard Henderson
4223d50b728SRichard Henderson /* NaN inputs or result do not get a sign change. */
4233d50b728SRichard Henderson if (!float64_is_any_nan(ret)) {
4243d50b728SRichard Henderson ret = float64_chs(ret);
4253d50b728SRichard Henderson }
4263d50b728SRichard Henderson check_ieee_exceptions(env, GETPC());
4273d50b728SRichard Henderson return ret;
4283d50b728SRichard Henderson }
4293d50b728SRichard Henderson
finish_fcmp(CPUSPARCState * env,FloatRelation r,uintptr_t ra)430d8c5b92fSRichard Henderson static uint32_t finish_fcmp(CPUSPARCState *env, FloatRelation r, uintptr_t ra)
431d8c5b92fSRichard Henderson {
432d8c5b92fSRichard Henderson check_ieee_exceptions(env, ra);
433d8c5b92fSRichard Henderson
434d8c5b92fSRichard Henderson /*
435d8c5b92fSRichard Henderson * FCC values:
436d8c5b92fSRichard Henderson * 0 =
437d8c5b92fSRichard Henderson * 1 <
438d8c5b92fSRichard Henderson * 2 >
439d8c5b92fSRichard Henderson * 3 unordered
440d8c5b92fSRichard Henderson */
441d8c5b92fSRichard Henderson switch (r) {
442d8c5b92fSRichard Henderson case float_relation_equal:
443d8c5b92fSRichard Henderson return 0;
444d8c5b92fSRichard Henderson case float_relation_less:
445d8c5b92fSRichard Henderson return 1;
446d8c5b92fSRichard Henderson case float_relation_greater:
447d8c5b92fSRichard Henderson return 2;
448d8c5b92fSRichard Henderson case float_relation_unordered:
449d8c5b92fSRichard Henderson env->fsr |= FSR_NVA;
450d8c5b92fSRichard Henderson return 3;
451fcf5ef2aSThomas Huth }
452d8c5b92fSRichard Henderson g_assert_not_reached();
453fcf5ef2aSThomas Huth }
454fcf5ef2aSThomas Huth
helper_fcmps(CPUSPARCState * env,float32 src1,float32 src2)455d8c5b92fSRichard Henderson uint32_t helper_fcmps(CPUSPARCState *env, float32 src1, float32 src2)
456d8c5b92fSRichard Henderson {
457d8c5b92fSRichard Henderson FloatRelation r = float32_compare_quiet(src1, src2, &env->fp_status);
458d8c5b92fSRichard Henderson return finish_fcmp(env, r, GETPC());
459d8c5b92fSRichard Henderson }
460fcf5ef2aSThomas Huth
helper_fcmpes(CPUSPARCState * env,float32 src1,float32 src2)461d8c5b92fSRichard Henderson uint32_t helper_fcmpes(CPUSPARCState *env, float32 src1, float32 src2)
462d8c5b92fSRichard Henderson {
463d8c5b92fSRichard Henderson FloatRelation r = float32_compare(src1, src2, &env->fp_status);
464d8c5b92fSRichard Henderson return finish_fcmp(env, r, GETPC());
465d8c5b92fSRichard Henderson }
466fcf5ef2aSThomas Huth
helper_fcmpd(CPUSPARCState * env,float64 src1,float64 src2)467d8c5b92fSRichard Henderson uint32_t helper_fcmpd(CPUSPARCState *env, float64 src1, float64 src2)
468d8c5b92fSRichard Henderson {
469d8c5b92fSRichard Henderson FloatRelation r = float64_compare_quiet(src1, src2, &env->fp_status);
470d8c5b92fSRichard Henderson return finish_fcmp(env, r, GETPC());
471d8c5b92fSRichard Henderson }
472fcf5ef2aSThomas Huth
helper_fcmped(CPUSPARCState * env,float64 src1,float64 src2)473d8c5b92fSRichard Henderson uint32_t helper_fcmped(CPUSPARCState *env, float64 src1, float64 src2)
474d8c5b92fSRichard Henderson {
475d8c5b92fSRichard Henderson FloatRelation r = float64_compare(src1, src2, &env->fp_status);
476d8c5b92fSRichard Henderson return finish_fcmp(env, r, GETPC());
477d8c5b92fSRichard Henderson }
478fcf5ef2aSThomas Huth
helper_fcmpq(CPUSPARCState * env,Int128 src1,Int128 src2)479d8c5b92fSRichard Henderson uint32_t helper_fcmpq(CPUSPARCState *env, Int128 src1, Int128 src2)
480d8c5b92fSRichard Henderson {
481d8c5b92fSRichard Henderson FloatRelation r = float128_compare_quiet(f128_in(src1), f128_in(src2),
482d8c5b92fSRichard Henderson &env->fp_status);
483d8c5b92fSRichard Henderson return finish_fcmp(env, r, GETPC());
484d8c5b92fSRichard Henderson }
485fcf5ef2aSThomas Huth
helper_fcmpeq(CPUSPARCState * env,Int128 src1,Int128 src2)486d8c5b92fSRichard Henderson uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
487d8c5b92fSRichard Henderson {
488d8c5b92fSRichard Henderson FloatRelation r = float128_compare(f128_in(src1), f128_in(src2),
489d8c5b92fSRichard Henderson &env->fp_status);
490d8c5b92fSRichard Henderson return finish_fcmp(env, r, GETPC());
491d8c5b92fSRichard Henderson }
492fcf5ef2aSThomas Huth
helper_flcmps(float32 src1,float32 src2)4931d3ed3d7SRichard Henderson uint32_t helper_flcmps(float32 src1, float32 src2)
4941d3ed3d7SRichard Henderson {
4951d3ed3d7SRichard Henderson /*
4961d3ed3d7SRichard Henderson * FLCMP never raises an exception nor modifies any FSR fields.
4971d3ed3d7SRichard Henderson * Perform the comparison with a dummy fp environment.
4981d3ed3d7SRichard Henderson */
4991d3ed3d7SRichard Henderson float_status discard = { };
500*4482f32dSPeter Maydell FloatRelation r;
501*4482f32dSPeter Maydell
502*4482f32dSPeter Maydell set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
503*4482f32dSPeter Maydell r = float32_compare_quiet(src1, src2, &discard);
5041d3ed3d7SRichard Henderson
5051d3ed3d7SRichard Henderson switch (r) {
5061d3ed3d7SRichard Henderson case float_relation_equal:
5071d3ed3d7SRichard Henderson if (src2 == float32_zero && src1 != float32_zero) {
5081d3ed3d7SRichard Henderson return 1; /* -0.0 < +0.0 */
5091d3ed3d7SRichard Henderson }
5101d3ed3d7SRichard Henderson return 0;
5111d3ed3d7SRichard Henderson case float_relation_less:
5121d3ed3d7SRichard Henderson return 1;
5131d3ed3d7SRichard Henderson case float_relation_greater:
5141d3ed3d7SRichard Henderson return 0;
5151d3ed3d7SRichard Henderson case float_relation_unordered:
5161d3ed3d7SRichard Henderson return float32_is_any_nan(src2) ? 3 : 2;
5171d3ed3d7SRichard Henderson }
5181d3ed3d7SRichard Henderson g_assert_not_reached();
5191d3ed3d7SRichard Henderson }
5201d3ed3d7SRichard Henderson
helper_flcmpd(float64 src1,float64 src2)5211d3ed3d7SRichard Henderson uint32_t helper_flcmpd(float64 src1, float64 src2)
5221d3ed3d7SRichard Henderson {
5231d3ed3d7SRichard Henderson float_status discard = { };
524*4482f32dSPeter Maydell FloatRelation r;
525*4482f32dSPeter Maydell
526*4482f32dSPeter Maydell set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
527*4482f32dSPeter Maydell r = float64_compare_quiet(src1, src2, &discard);
5281d3ed3d7SRichard Henderson
5291d3ed3d7SRichard Henderson switch (r) {
5301d3ed3d7SRichard Henderson case float_relation_equal:
5311d3ed3d7SRichard Henderson if (src2 == float64_zero && src1 != float64_zero) {
5321d3ed3d7SRichard Henderson return 1; /* -0.0 < +0.0 */
5331d3ed3d7SRichard Henderson }
5341d3ed3d7SRichard Henderson return 0;
5351d3ed3d7SRichard Henderson case float_relation_less:
5361d3ed3d7SRichard Henderson return 1;
5371d3ed3d7SRichard Henderson case float_relation_greater:
5381d3ed3d7SRichard Henderson return 0;
5391d3ed3d7SRichard Henderson case float_relation_unordered:
5401d3ed3d7SRichard Henderson return float64_is_any_nan(src2) ? 3 : 2;
5411d3ed3d7SRichard Henderson }
5421d3ed3d7SRichard Henderson g_assert_not_reached();
5431d3ed3d7SRichard Henderson }
5441d3ed3d7SRichard Henderson
cpu_get_fsr(CPUSPARCState * env)5451ccd6e13SRichard Henderson target_ulong cpu_get_fsr(CPUSPARCState *env)
5461ccd6e13SRichard Henderson {
5473590f01eSRichard Henderson target_ulong fsr = env->fsr | env->fsr_cexc_ftt;
54849bb9725SRichard Henderson
549d8c5b92fSRichard Henderson fsr |= env->fcc[0] << FSR_FCC0_SHIFT;
550d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
551d8c5b92fSRichard Henderson fsr |= (uint64_t)env->fcc[1] << FSR_FCC1_SHIFT;
552d8c5b92fSRichard Henderson fsr |= (uint64_t)env->fcc[2] << FSR_FCC2_SHIFT;
553d8c5b92fSRichard Henderson fsr |= (uint64_t)env->fcc[3] << FSR_FCC3_SHIFT;
554e412e997SCarl Hauser #elif !defined(CONFIG_USER_ONLY)
555e412e997SCarl Hauser fsr |= env->fsr_qne;
556d8c5b92fSRichard Henderson #endif
557d8c5b92fSRichard Henderson
55849bb9725SRichard Henderson /* VER is kept completely separate until re-assembly. */
55949bb9725SRichard Henderson fsr |= env->def.fpu_version;
56049bb9725SRichard Henderson
56149bb9725SRichard Henderson return fsr;
5621ccd6e13SRichard Henderson }
5631ccd6e13SRichard Henderson
helper_get_fsr(CPUSPARCState * env)5641ccd6e13SRichard Henderson target_ulong helper_get_fsr(CPUSPARCState *env)
5651ccd6e13SRichard Henderson {
5661ccd6e13SRichard Henderson return cpu_get_fsr(env);
5671ccd6e13SRichard Henderson }
5681ccd6e13SRichard Henderson
set_fsr_nonsplit(CPUSPARCState * env,target_ulong fsr)5691ccd6e13SRichard Henderson static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr)
570fcf5ef2aSThomas Huth {
571fcf5ef2aSThomas Huth int rnd_mode;
572fcf5ef2aSThomas Huth
573d8c5b92fSRichard Henderson env->fsr = fsr & (FSR_RD_MASK | FSR_TEM_MASK | FSR_AEXC_MASK);
5741ccd6e13SRichard Henderson
575fcf5ef2aSThomas Huth switch (fsr & FSR_RD_MASK) {
576fcf5ef2aSThomas Huth case FSR_RD_NEAREST:
577fcf5ef2aSThomas Huth rnd_mode = float_round_nearest_even;
578fcf5ef2aSThomas Huth break;
579fcf5ef2aSThomas Huth default:
580fcf5ef2aSThomas Huth case FSR_RD_ZERO:
581fcf5ef2aSThomas Huth rnd_mode = float_round_to_zero;
582fcf5ef2aSThomas Huth break;
583fcf5ef2aSThomas Huth case FSR_RD_POS:
584fcf5ef2aSThomas Huth rnd_mode = float_round_up;
585fcf5ef2aSThomas Huth break;
586fcf5ef2aSThomas Huth case FSR_RD_NEG:
587fcf5ef2aSThomas Huth rnd_mode = float_round_down;
588fcf5ef2aSThomas Huth break;
589fcf5ef2aSThomas Huth }
590fcf5ef2aSThomas Huth set_float_rounding_mode(rnd_mode, &env->fp_status);
591fcf5ef2aSThomas Huth }
592fcf5ef2aSThomas Huth
cpu_put_fsr(CPUSPARCState * env,target_ulong fsr)5931ccd6e13SRichard Henderson void cpu_put_fsr(CPUSPARCState *env, target_ulong fsr)
5941ccd6e13SRichard Henderson {
5953590f01eSRichard Henderson env->fsr_cexc_ftt = fsr & (FSR_CEXC_MASK | FSR_FTT_MASK);
596d8c5b92fSRichard Henderson
597d8c5b92fSRichard Henderson env->fcc[0] = extract32(fsr, FSR_FCC0_SHIFT, 2);
598d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
599d8c5b92fSRichard Henderson env->fcc[1] = extract64(fsr, FSR_FCC1_SHIFT, 2);
600d8c5b92fSRichard Henderson env->fcc[2] = extract64(fsr, FSR_FCC2_SHIFT, 2);
601d8c5b92fSRichard Henderson env->fcc[3] = extract64(fsr, FSR_FCC3_SHIFT, 2);
602e412e997SCarl Hauser #elif !defined(CONFIG_USER_ONLY)
603e412e997SCarl Hauser env->fsr_qne = fsr & FSR_QNE;
604d8c5b92fSRichard Henderson #endif
605d8c5b92fSRichard Henderson
6061ccd6e13SRichard Henderson set_fsr_nonsplit(env, fsr);
6071ccd6e13SRichard Henderson }
6081ccd6e13SRichard Henderson
helper_set_fsr_nofcc_noftt(CPUSPARCState * env,uint32_t fsr)609d8c5b92fSRichard Henderson void helper_set_fsr_nofcc_noftt(CPUSPARCState *env, uint32_t fsr)
610fcf5ef2aSThomas Huth {
6113590f01eSRichard Henderson env->fsr_cexc_ftt &= FSR_FTT_MASK;
6123590f01eSRichard Henderson env->fsr_cexc_ftt |= fsr & FSR_CEXC_MASK;
6131ccd6e13SRichard Henderson set_fsr_nonsplit(env, fsr);
614fcf5ef2aSThomas Huth }
615298c52f7SRichard Henderson
helper_set_fsr_nofcc(CPUSPARCState * env,uint32_t fsr)616298c52f7SRichard Henderson void helper_set_fsr_nofcc(CPUSPARCState *env, uint32_t fsr)
617298c52f7SRichard Henderson {
618298c52f7SRichard Henderson env->fsr_cexc_ftt = fsr & (FSR_CEXC_MASK | FSR_FTT_MASK);
619298c52f7SRichard Henderson set_fsr_nonsplit(env, fsr);
620298c52f7SRichard Henderson }
621