Statistics
| Branch: | Revision:

root / target-openrisc / fpu_helper.c @ 45724d6d

History | View | Annotate | Download (14.5 kB)

1
/*
2
 * OpenRISC float helper routines
3
 *
4
 * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5
 *                         Feng Gao <gf91597@gmail.com>
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
 */
20

    
21
#include "cpu.h"
22
#include "helper.h"
23
#include "exception.h"
24

    
25
static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp)
26
{
27
    int ret = 0;
28
    if (fexcp) {
29
        if (fexcp & float_flag_invalid) {
30
            cpu->env.fpcsr |= FPCSR_IVF;
31
            ret = 1;
32
        }
33
        if (fexcp & float_flag_overflow) {
34
            cpu->env.fpcsr |= FPCSR_OVF;
35
            ret = 1;
36
        }
37
        if (fexcp & float_flag_underflow) {
38
            cpu->env.fpcsr |= FPCSR_UNF;
39
            ret = 1;
40
        }
41
        if (fexcp & float_flag_divbyzero) {
42
            cpu->env.fpcsr |= FPCSR_DZF;
43
            ret = 1;
44
        }
45
        if (fexcp & float_flag_inexact) {
46
            cpu->env.fpcsr |= FPCSR_IXF;
47
            ret = 1;
48
        }
49
    }
50

    
51
    return ret;
52
}
53

    
54
static inline void update_fpcsr(OpenRISCCPU *cpu)
55
{
56
    int tmp = ieee_ex_to_openrisc(cpu,
57
                              get_float_exception_flags(&cpu->env.fp_status));
58

    
59
    SET_FP_CAUSE(cpu->env.fpcsr, tmp);
60
    if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) &&
61
        (cpu->env.fpcsr & FPCSR_FPEE)) {
62
        helper_exception(&cpu->env, EXCP_FPE);
63
    } else {
64
        UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp);
65
    }
66
}
67

    
68
uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val)
69
{
70
    uint64_t itofd;
71
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
72

    
73
    set_float_exception_flags(0, &cpu->env.fp_status);
74
    itofd = int32_to_float64(val, &cpu->env.fp_status);
75
    update_fpcsr(cpu);
76

    
77
    return itofd;
78
}
79

    
80
uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val)
81
{
82
    uint32_t itofs;
83
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
84

    
85
    set_float_exception_flags(0, &cpu->env.fp_status);
86
    itofs = int32_to_float32(val, &cpu->env.fp_status);
87
    update_fpcsr(cpu);
88

    
89
    return itofs;
90
}
91

    
92
uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val)
93
{
94
    uint64_t ftoid;
95
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
96

    
97
    set_float_exception_flags(0, &cpu->env.fp_status);
98
    ftoid = float32_to_int64(val, &cpu->env.fp_status);
99
    update_fpcsr(cpu);
100

    
101
    return ftoid;
102
}
103

    
104
uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val)
105
{
106
    uint32_t ftois;
107
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
108

    
109
    set_float_exception_flags(0, &cpu->env.fp_status);
110
    ftois = float32_to_int32(val, &cpu->env.fp_status);
111
    update_fpcsr(cpu);
112

    
113
    return ftois;
114
}
115

    
116
#define FLOAT_OP(name, p) void helper_float_##_##p(void)
117

    
118
#define FLOAT_CALC(name)                                                  \
119
uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
120
                                     uint64_t fdt0, uint64_t fdt1)        \
121
{                                                                         \
122
    uint64_t result;                                                      \
123
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
124
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
125
    result = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status);           \
126
    update_fpcsr(cpu);                                                    \
127
    return result;                                                        \
128
}                                                                         \
129
                                                                          \
130
uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
131
                                     uint32_t fdt0, uint32_t fdt1)        \
132
{                                                                         \
133
    uint32_t result;                                                      \
134
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
135
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
136
    result = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status);           \
137
    update_fpcsr(cpu);                                                    \
138
    return result;                                                        \
139
}                                                                         \
140

    
141
FLOAT_CALC(add)
142
FLOAT_CALC(sub)
143
FLOAT_CALC(mul)
144
FLOAT_CALC(div)
145
FLOAT_CALC(rem)
146
#undef FLOAT_CALC
147

    
148
#define FLOAT_TERNOP(name1, name2)                                        \
149
uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenRISCState *env,     \
150
                                               uint64_t fdt0,             \
151
                                               uint64_t fdt1)             \
152
{                                                                         \
153
    uint64_t result, temp, hi, lo;                                        \
154
    uint32_t val1, val2;                                                  \
155
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
156
    hi = env->fpmaddhi;                                                   \
157
    lo = env->fpmaddlo;                                                   \
158
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
159
    result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status);          \
160
    lo &= 0xffffffff;                                                     \
161
    hi &= 0xffffffff;                                                     \
162
    temp = (hi << 32) | lo;                                               \
163
    result = float64_ ## name2(result, temp, &cpu->env.fp_status);        \
164
    val1 = result >> 32;                                                  \
165
    val2 = (uint32_t) (result & 0xffffffff);                              \
166
    update_fpcsr(cpu);                                                    \
167
    cpu->env.fpmaddlo = val2;                                             \
168
    cpu->env.fpmaddhi = val1;                                             \
169
    return 0;                                                             \
170
}                                                                         \
171
                                                                          \
172
uint32_t helper_float_ ## name1 ## name2 ## _s(CPUOpenRISCState *env,     \
173
                                            uint32_t fdt0, uint32_t fdt1) \
174
{                                                                         \
175
    uint64_t result, temp, hi, lo;                                        \
176
    uint32_t val1, val2;                                                  \
177
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
178
    hi = cpu->env.fpmaddhi;                                               \
179
    lo = cpu->env.fpmaddlo;                                               \
180
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
181
    result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status);          \
182
    temp = (hi << 32) | lo;                                               \
183
    result = float64_ ## name2(result, temp, &cpu->env.fp_status);        \
184
    val1 = result >> 32;                                                  \
185
    val2 = (uint32_t) (result & 0xffffffff);                              \
186
    update_fpcsr(cpu);                                                    \
187
    cpu->env.fpmaddlo = val2;                                             \
188
    cpu->env.fpmaddhi = val1;                                             \
189
    return 0;                                                             \
190
}
191

    
192
FLOAT_TERNOP(mul, add)
193
#undef FLOAT_TERNOP
194

    
195

    
196
#define FLOAT_CMP(name)                                                   \
197
uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
198
                                     uint64_t fdt0, uint64_t fdt1)        \
199
{                                                                         \
200
    int res;                                                              \
201
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
202
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
203
    res = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status);              \
204
    update_fpcsr(cpu);                                                    \
205
    return res;                                                           \
206
}                                                                         \
207
                                                                          \
208
uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
209
                                             uint32_t fdt0, uint32_t fdt1)\
210
{                                                                         \
211
    int res;                                                              \
212
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
213
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
214
    res = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status);              \
215
    update_fpcsr(cpu);                                                    \
216
    return res;                                                           \
217
}
218

    
219
FLOAT_CMP(le)
220
FLOAT_CMP(eq)
221
FLOAT_CMP(lt)
222
#undef FLOAT_CMP
223

    
224

    
225
#define FLOAT_CMPNE(name)                                                 \
226
uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
227
                                     uint64_t fdt0, uint64_t fdt1)        \
228
{                                                                         \
229
    int res;                                                              \
230
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
231
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
232
    res = !float64_eq_quiet(fdt0, fdt1, &cpu->env.fp_status);             \
233
    update_fpcsr(cpu);                                                    \
234
    return res;                                                           \
235
}                                                                         \
236
                                                                          \
237
uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
238
                                     uint32_t fdt0, uint32_t fdt1)        \
239
{                                                                         \
240
    int res;                                                              \
241
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
242
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
243
    res = !float32_eq_quiet(fdt0, fdt1, &cpu->env.fp_status);             \
244
    update_fpcsr(cpu);                                                    \
245
    return res;                                                           \
246
}
247

    
248
FLOAT_CMPNE(ne)
249
#undef FLOAT_CMPNE
250

    
251
#define FLOAT_CMPGT(name)                                                 \
252
uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
253
                                     uint64_t fdt0, uint64_t fdt1)        \
254
{                                                                         \
255
    int res;                                                              \
256
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
257
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
258
    res = !float64_le(fdt0, fdt1, &cpu->env.fp_status);                   \
259
    update_fpcsr(cpu);                                                    \
260
    return res;                                                           \
261
}                                                                         \
262
                                                                          \
263
uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
264
                                     uint32_t fdt0, uint32_t fdt1)        \
265
{                                                                         \
266
    int res;                                                              \
267
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
268
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
269
    res = !float32_le(fdt0, fdt1, &cpu->env.fp_status);                   \
270
    update_fpcsr(cpu);                                                    \
271
    return res;                                                           \
272
}
273
FLOAT_CMPGT(gt)
274
#undef FLOAT_CMPGT
275

    
276
#define FLOAT_CMPGE(name)                                                 \
277
uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
278
                                     uint64_t fdt0, uint64_t fdt1)        \
279
{                                                                         \
280
    int res;                                                              \
281
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
282
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
283
    res = !float64_lt(fdt0, fdt1, &cpu->env.fp_status);                   \
284
    update_fpcsr(cpu);                                                    \
285
    return res;                                                           \
286
}                                                                         \
287
                                                                          \
288
uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
289
                                     uint32_t fdt0, uint32_t fdt1)        \
290
{                                                                         \
291
    int res;                                                              \
292
    OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));                    \
293
    set_float_exception_flags(0, &cpu->env.fp_status);                    \
294
    res = !float32_lt(fdt0, fdt1, &cpu->env.fp_status);                   \
295
    update_fpcsr(cpu);                                                    \
296
    return res;                                                           \
297
}
298

    
299
FLOAT_CMPGE(ge)
300
#undef FLOAT_CMPGE