1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "cpu.h"
23#include "exec/helper-proto.h"
24#include "exception.h"
25#include "fpu/softfloat.h"
26
27static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp)
28{
29 int ret = 0;
30 if (fexcp) {
31 if (fexcp & float_flag_invalid) {
32 cpu->env.fpcsr |= FPCSR_IVF;
33 ret = 1;
34 }
35 if (fexcp & float_flag_overflow) {
36 cpu->env.fpcsr |= FPCSR_OVF;
37 ret = 1;
38 }
39 if (fexcp & float_flag_underflow) {
40 cpu->env.fpcsr |= FPCSR_UNF;
41 ret = 1;
42 }
43 if (fexcp & float_flag_divbyzero) {
44 cpu->env.fpcsr |= FPCSR_DZF;
45 ret = 1;
46 }
47 if (fexcp & float_flag_inexact) {
48 cpu->env.fpcsr |= FPCSR_IXF;
49 ret = 1;
50 }
51 }
52
53 return ret;
54}
55
56static inline void update_fpcsr(OpenRISCCPU *cpu)
57{
58 int tmp = ieee_ex_to_openrisc(cpu,
59 get_float_exception_flags(&cpu->env.fp_status));
60
61 SET_FP_CAUSE(cpu->env.fpcsr, tmp);
62 if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) &&
63 (cpu->env.fpcsr & FPCSR_FPEE)) {
64 helper_exception(&cpu->env, EXCP_FPE);
65 } else {
66 UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp);
67 }
68}
69
70uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val)
71{
72 uint64_t itofd;
73 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
74
75 set_float_exception_flags(0, &cpu->env.fp_status);
76 itofd = int32_to_float64(val, &cpu->env.fp_status);
77 update_fpcsr(cpu);
78
79 return itofd;
80}
81
82uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val)
83{
84 uint32_t itofs;
85 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
86
87 set_float_exception_flags(0, &cpu->env.fp_status);
88 itofs = int32_to_float32(val, &cpu->env.fp_status);
89 update_fpcsr(cpu);
90
91 return itofs;
92}
93
94uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val)
95{
96 uint64_t ftoid;
97 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
98
99 set_float_exception_flags(0, &cpu->env.fp_status);
100 ftoid = float32_to_int64(val, &cpu->env.fp_status);
101 update_fpcsr(cpu);
102
103 return ftoid;
104}
105
106uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val)
107{
108 uint32_t ftois;
109 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
110
111 set_float_exception_flags(0, &cpu->env.fp_status);
112 ftois = float32_to_int32(val, &cpu->env.fp_status);
113 update_fpcsr(cpu);
114
115 return ftois;
116}
117
118#define FLOAT_OP(name, p) void helper_float_##_##p(void)
119
120#define FLOAT_CALC(name) \
121uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
122 uint64_t fdt0, uint64_t fdt1) \
123{ \
124 uint64_t result; \
125 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
126 set_float_exception_flags(0, &cpu->env.fp_status); \
127 result = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
128 update_fpcsr(cpu); \
129 return result; \
130} \
131 \
132uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
133 uint32_t fdt0, uint32_t fdt1) \
134{ \
135 uint32_t result; \
136 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
137 set_float_exception_flags(0, &cpu->env.fp_status); \
138 result = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
139 update_fpcsr(cpu); \
140 return result; \
141} \
142
143FLOAT_CALC(add)
144FLOAT_CALC(sub)
145FLOAT_CALC(mul)
146FLOAT_CALC(div)
147FLOAT_CALC(rem)
148#undef FLOAT_CALC
149
150
151uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a,
152 uint64_t b, uint64_t c)
153{
154 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
155 uint64_t result;
156 set_float_exception_flags(0, &cpu->env.fp_status);
157
158 result = float64_mul(b, c, &cpu->env.fp_status);
159 result = float64_add(result, a, &cpu->env.fp_status);
160 update_fpcsr(cpu);
161 return result;
162}
163
164uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a,
165 uint32_t b, uint32_t c)
166{
167 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
168 uint32_t result;
169 set_float_exception_flags(0, &cpu->env.fp_status);
170
171 result = float32_mul(b, c, &cpu->env.fp_status);
172 result = float32_add(result, a, &cpu->env.fp_status);
173 update_fpcsr(cpu);
174 return result;
175}
176
177
178#define FLOAT_CMP(name) \
179uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
180 uint64_t fdt0, uint64_t fdt1) \
181{ \
182 int res; \
183 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
184 set_float_exception_flags(0, &cpu->env.fp_status); \
185 res = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
186 update_fpcsr(cpu); \
187 return res; \
188} \
189 \
190uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
191 uint32_t fdt0, uint32_t fdt1)\
192{ \
193 int res; \
194 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
195 set_float_exception_flags(0, &cpu->env.fp_status); \
196 res = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
197 update_fpcsr(cpu); \
198 return res; \
199}
200
201FLOAT_CMP(le)
202FLOAT_CMP(eq)
203FLOAT_CMP(lt)
204#undef FLOAT_CMP
205
206
207#define FLOAT_CMPNE(name) \
208uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
209 uint64_t fdt0, uint64_t fdt1) \
210{ \
211 int res; \
212 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
213 set_float_exception_flags(0, &cpu->env.fp_status); \
214 res = !float64_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \
215 update_fpcsr(cpu); \
216 return res; \
217} \
218 \
219uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
220 uint32_t fdt0, uint32_t fdt1) \
221{ \
222 int res; \
223 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
224 set_float_exception_flags(0, &cpu->env.fp_status); \
225 res = !float32_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \
226 update_fpcsr(cpu); \
227 return res; \
228}
229
230FLOAT_CMPNE(ne)
231#undef FLOAT_CMPNE
232
233#define FLOAT_CMPGT(name) \
234uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
235 uint64_t fdt0, uint64_t fdt1) \
236{ \
237 int res; \
238 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
239 set_float_exception_flags(0, &cpu->env.fp_status); \
240 res = !float64_le(fdt0, fdt1, &cpu->env.fp_status); \
241 update_fpcsr(cpu); \
242 return res; \
243} \
244 \
245uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
246 uint32_t fdt0, uint32_t fdt1) \
247{ \
248 int res; \
249 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
250 set_float_exception_flags(0, &cpu->env.fp_status); \
251 res = !float32_le(fdt0, fdt1, &cpu->env.fp_status); \
252 update_fpcsr(cpu); \
253 return res; \
254}
255FLOAT_CMPGT(gt)
256#undef FLOAT_CMPGT
257
258#define FLOAT_CMPGE(name) \
259uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
260 uint64_t fdt0, uint64_t fdt1) \
261{ \
262 int res; \
263 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
264 set_float_exception_flags(0, &cpu->env.fp_status); \
265 res = !float64_lt(fdt0, fdt1, &cpu->env.fp_status); \
266 update_fpcsr(cpu); \
267 return res; \
268} \
269 \
270uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
271 uint32_t fdt0, uint32_t fdt1) \
272{ \
273 int res; \
274 OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
275 set_float_exception_flags(0, &cpu->env.fp_status); \
276 res = !float32_lt(fdt0, fdt1, &cpu->env.fp_status); \
277 update_fpcsr(cpu); \
278 return res; \
279}
280
281FLOAT_CMPGE(ge)
282#undef FLOAT_CMPGE
283