Statistics
| Branch: | Revision:

root / target-alpha / op_helper.c @ bf1b03fe

History | View | Annotate | Download (30.3 kB)

1 4c9649a9 j_mayer
/*
2 4c9649a9 j_mayer
 *  Alpha emulation cpu micro-operations helpers for qemu.
3 5fafdf24 ths
 *
4 4c9649a9 j_mayer
 *  Copyright (c) 2007 Jocelyn Mayer
5 4c9649a9 j_mayer
 *
6 4c9649a9 j_mayer
 * This library is free software; you can redistribute it and/or
7 4c9649a9 j_mayer
 * modify it under the terms of the GNU Lesser General Public
8 4c9649a9 j_mayer
 * License as published by the Free Software Foundation; either
9 4c9649a9 j_mayer
 * version 2 of the License, or (at your option) any later version.
10 4c9649a9 j_mayer
 *
11 4c9649a9 j_mayer
 * This library is distributed in the hope that it will be useful,
12 4c9649a9 j_mayer
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 4c9649a9 j_mayer
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 4c9649a9 j_mayer
 * Lesser General Public License for more details.
15 4c9649a9 j_mayer
 *
16 4c9649a9 j_mayer
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 4c9649a9 j_mayer
 */
19 4c9649a9 j_mayer
20 4c9649a9 j_mayer
#include "exec.h"
21 603fccce j_mayer
#include "host-utils.h"
22 4c9649a9 j_mayer
#include "softfloat.h"
23 a7812ae4 pbrook
#include "helper.h"
24 18f8e2c0 Richard Henderson
#include "qemu-timer.h"
25 4c9649a9 j_mayer
26 4c9649a9 j_mayer
/*****************************************************************************/
27 4c9649a9 j_mayer
/* Exceptions processing helpers */
28 c2c789cf Richard Henderson
void QEMU_NORETURN helper_excp (int excp, int error)
29 4c9649a9 j_mayer
{
30 4c9649a9 j_mayer
    env->exception_index = excp;
31 4c9649a9 j_mayer
    env->error_code = error;
32 4c9649a9 j_mayer
    cpu_loop_exit();
33 4c9649a9 j_mayer
}
34 4c9649a9 j_mayer
35 6ad02592 aurel32
uint64_t helper_load_pcc (void)
36 4c9649a9 j_mayer
{
37 18f8e2c0 Richard Henderson
    /* ??? This isn't a timer for which we have any rate info.  */
38 18f8e2c0 Richard Henderson
    return (uint32_t)cpu_get_real_ticks();
39 4c9649a9 j_mayer
}
40 4c9649a9 j_mayer
41 f18cd223 aurel32
uint64_t helper_load_fpcr (void)
42 4c9649a9 j_mayer
{
43 ba0e276d Richard Henderson
    return cpu_alpha_load_fpcr (env);
44 4c9649a9 j_mayer
}
45 4c9649a9 j_mayer
46 f18cd223 aurel32
void helper_store_fpcr (uint64_t val)
47 4c9649a9 j_mayer
{
48 ba0e276d Richard Henderson
    cpu_alpha_store_fpcr (env, val);
49 4c9649a9 j_mayer
}
50 4c9649a9 j_mayer
51 04acd307 aurel32
uint64_t helper_addqv (uint64_t op1, uint64_t op2)
52 4c9649a9 j_mayer
{
53 04acd307 aurel32
    uint64_t tmp = op1;
54 04acd307 aurel32
    op1 += op2;
55 04acd307 aurel32
    if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
56 866be65d Richard Henderson
        helper_excp(EXCP_ARITH, EXC_M_IOV);
57 4c9649a9 j_mayer
    }
58 04acd307 aurel32
    return op1;
59 4c9649a9 j_mayer
}
60 4c9649a9 j_mayer
61 04acd307 aurel32
uint64_t helper_addlv (uint64_t op1, uint64_t op2)
62 4c9649a9 j_mayer
{
63 04acd307 aurel32
    uint64_t tmp = op1;
64 04acd307 aurel32
    op1 = (uint32_t)(op1 + op2);
65 04acd307 aurel32
    if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
66 866be65d Richard Henderson
        helper_excp(EXCP_ARITH, EXC_M_IOV);
67 4c9649a9 j_mayer
    }
68 04acd307 aurel32
    return op1;
69 4c9649a9 j_mayer
}
70 4c9649a9 j_mayer
71 04acd307 aurel32
uint64_t helper_subqv (uint64_t op1, uint64_t op2)
72 4c9649a9 j_mayer
{
73 ecbb5ea1 aurel32
    uint64_t res;
74 ecbb5ea1 aurel32
    res = op1 - op2;
75 ecbb5ea1 aurel32
    if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
76 866be65d Richard Henderson
        helper_excp(EXCP_ARITH, EXC_M_IOV);
77 4c9649a9 j_mayer
    }
78 ecbb5ea1 aurel32
    return res;
79 4c9649a9 j_mayer
}
80 4c9649a9 j_mayer
81 04acd307 aurel32
uint64_t helper_sublv (uint64_t op1, uint64_t op2)
82 4c9649a9 j_mayer
{
83 ecbb5ea1 aurel32
    uint32_t res;
84 ecbb5ea1 aurel32
    res = op1 - op2;
85 ecbb5ea1 aurel32
    if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
86 866be65d Richard Henderson
        helper_excp(EXCP_ARITH, EXC_M_IOV);
87 4c9649a9 j_mayer
    }
88 ecbb5ea1 aurel32
    return res;
89 4c9649a9 j_mayer
}
90 4c9649a9 j_mayer
91 04acd307 aurel32
uint64_t helper_mullv (uint64_t op1, uint64_t op2)
92 4c9649a9 j_mayer
{
93 04acd307 aurel32
    int64_t res = (int64_t)op1 * (int64_t)op2;
94 4c9649a9 j_mayer
95 4c9649a9 j_mayer
    if (unlikely((int32_t)res != res)) {
96 866be65d Richard Henderson
        helper_excp(EXCP_ARITH, EXC_M_IOV);
97 4c9649a9 j_mayer
    }
98 04acd307 aurel32
    return (int64_t)((int32_t)res);
99 4c9649a9 j_mayer
}
100 4c9649a9 j_mayer
101 04acd307 aurel32
uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
102 4c9649a9 j_mayer
{
103 e14fe0a9 j_mayer
    uint64_t tl, th;
104 e14fe0a9 j_mayer
105 04acd307 aurel32
    muls64(&tl, &th, op1, op2);
106 e14fe0a9 j_mayer
    /* If th != 0 && th != -1, then we had an overflow */
107 e14fe0a9 j_mayer
    if (unlikely((th + 1) > 1)) {
108 866be65d Richard Henderson
        helper_excp(EXCP_ARITH, EXC_M_IOV);
109 4c9649a9 j_mayer
    }
110 04acd307 aurel32
    return tl;
111 04acd307 aurel32
}
112 04acd307 aurel32
113 04acd307 aurel32
uint64_t helper_umulh (uint64_t op1, uint64_t op2)
114 04acd307 aurel32
{
115 04acd307 aurel32
    uint64_t tl, th;
116 04acd307 aurel32
117 04acd307 aurel32
    mulu64(&tl, &th, op1, op2);
118 04acd307 aurel32
    return th;
119 4c9649a9 j_mayer
}
120 4c9649a9 j_mayer
121 ae8ecd42 aurel32
uint64_t helper_ctpop (uint64_t arg)
122 4c9649a9 j_mayer
{
123 ae8ecd42 aurel32
    return ctpop64(arg);
124 4c9649a9 j_mayer
}
125 4c9649a9 j_mayer
126 ae8ecd42 aurel32
uint64_t helper_ctlz (uint64_t arg)
127 4c9649a9 j_mayer
{
128 ae8ecd42 aurel32
    return clz64(arg);
129 4c9649a9 j_mayer
}
130 4c9649a9 j_mayer
131 ae8ecd42 aurel32
uint64_t helper_cttz (uint64_t arg)
132 4c9649a9 j_mayer
{
133 ae8ecd42 aurel32
    return ctz64(arg);
134 4c9649a9 j_mayer
}
135 4c9649a9 j_mayer
136 636aa200 Blue Swirl
static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
137 4c9649a9 j_mayer
{
138 4c9649a9 j_mayer
    uint64_t mask;
139 4c9649a9 j_mayer
140 4c9649a9 j_mayer
    mask = 0;
141 4c9649a9 j_mayer
    mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
142 4c9649a9 j_mayer
    mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
143 4c9649a9 j_mayer
    mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
144 4c9649a9 j_mayer
    mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
145 4c9649a9 j_mayer
    mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
146 4c9649a9 j_mayer
    mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
147 4c9649a9 j_mayer
    mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
148 4c9649a9 j_mayer
    mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
149 4c9649a9 j_mayer
150 4c9649a9 j_mayer
    return op & ~mask;
151 4c9649a9 j_mayer
}
152 4c9649a9 j_mayer
153 b3249f63 aurel32
uint64_t helper_zap(uint64_t val, uint64_t mask)
154 4c9649a9 j_mayer
{
155 b3249f63 aurel32
    return byte_zap(val, mask);
156 4c9649a9 j_mayer
}
157 4c9649a9 j_mayer
158 b3249f63 aurel32
uint64_t helper_zapnot(uint64_t val, uint64_t mask)
159 4c9649a9 j_mayer
{
160 b3249f63 aurel32
    return byte_zap(val, ~mask);
161 4c9649a9 j_mayer
}
162 4c9649a9 j_mayer
163 04acd307 aurel32
uint64_t helper_cmpbge (uint64_t op1, uint64_t op2)
164 4c9649a9 j_mayer
{
165 4c9649a9 j_mayer
    uint8_t opa, opb, res;
166 4c9649a9 j_mayer
    int i;
167 4c9649a9 j_mayer
168 4c9649a9 j_mayer
    res = 0;
169 970d622e aurel32
    for (i = 0; i < 8; i++) {
170 04acd307 aurel32
        opa = op1 >> (i * 8);
171 04acd307 aurel32
        opb = op2 >> (i * 8);
172 4c9649a9 j_mayer
        if (opa >= opb)
173 4c9649a9 j_mayer
            res |= 1 << i;
174 4c9649a9 j_mayer
    }
175 04acd307 aurel32
    return res;
176 4c9649a9 j_mayer
}
177 4c9649a9 j_mayer
178 13e4df99 Richard Henderson
uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
179 13e4df99 Richard Henderson
{
180 13e4df99 Richard Henderson
    uint64_t res = 0;
181 13e4df99 Richard Henderson
    uint8_t opa, opb, opr;
182 13e4df99 Richard Henderson
    int i;
183 13e4df99 Richard Henderson
184 13e4df99 Richard Henderson
    for (i = 0; i < 8; ++i) {
185 13e4df99 Richard Henderson
        opa = op1 >> (i * 8);
186 13e4df99 Richard Henderson
        opb = op2 >> (i * 8);
187 13e4df99 Richard Henderson
        opr = opa < opb ? opa : opb;
188 13e4df99 Richard Henderson
        res |= (uint64_t)opr << (i * 8);
189 13e4df99 Richard Henderson
    }
190 13e4df99 Richard Henderson
    return res;
191 13e4df99 Richard Henderson
}
192 13e4df99 Richard Henderson
193 13e4df99 Richard Henderson
uint64_t helper_minsb8 (uint64_t op1, uint64_t op2)
194 13e4df99 Richard Henderson
{
195 13e4df99 Richard Henderson
    uint64_t res = 0;
196 13e4df99 Richard Henderson
    int8_t opa, opb;
197 13e4df99 Richard Henderson
    uint8_t opr;
198 13e4df99 Richard Henderson
    int i;
199 13e4df99 Richard Henderson
200 13e4df99 Richard Henderson
    for (i = 0; i < 8; ++i) {
201 13e4df99 Richard Henderson
        opa = op1 >> (i * 8);
202 13e4df99 Richard Henderson
        opb = op2 >> (i * 8);
203 13e4df99 Richard Henderson
        opr = opa < opb ? opa : opb;
204 13e4df99 Richard Henderson
        res |= (uint64_t)opr << (i * 8);
205 13e4df99 Richard Henderson
    }
206 13e4df99 Richard Henderson
    return res;
207 13e4df99 Richard Henderson
}
208 13e4df99 Richard Henderson
209 13e4df99 Richard Henderson
uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
210 13e4df99 Richard Henderson
{
211 13e4df99 Richard Henderson
    uint64_t res = 0;
212 13e4df99 Richard Henderson
    uint16_t opa, opb, opr;
213 13e4df99 Richard Henderson
    int i;
214 13e4df99 Richard Henderson
215 13e4df99 Richard Henderson
    for (i = 0; i < 4; ++i) {
216 13e4df99 Richard Henderson
        opa = op1 >> (i * 16);
217 13e4df99 Richard Henderson
        opb = op2 >> (i * 16);
218 13e4df99 Richard Henderson
        opr = opa < opb ? opa : opb;
219 13e4df99 Richard Henderson
        res |= (uint64_t)opr << (i * 16);
220 13e4df99 Richard Henderson
    }
221 13e4df99 Richard Henderson
    return res;
222 13e4df99 Richard Henderson
}
223 13e4df99 Richard Henderson
224 13e4df99 Richard Henderson
uint64_t helper_minsw4 (uint64_t op1, uint64_t op2)
225 13e4df99 Richard Henderson
{
226 13e4df99 Richard Henderson
    uint64_t res = 0;
227 13e4df99 Richard Henderson
    int16_t opa, opb;
228 13e4df99 Richard Henderson
    uint16_t opr;
229 13e4df99 Richard Henderson
    int i;
230 13e4df99 Richard Henderson
231 13e4df99 Richard Henderson
    for (i = 0; i < 4; ++i) {
232 13e4df99 Richard Henderson
        opa = op1 >> (i * 16);
233 13e4df99 Richard Henderson
        opb = op2 >> (i * 16);
234 13e4df99 Richard Henderson
        opr = opa < opb ? opa : opb;
235 13e4df99 Richard Henderson
        res |= (uint64_t)opr << (i * 16);
236 13e4df99 Richard Henderson
    }
237 13e4df99 Richard Henderson
    return res;
238 13e4df99 Richard Henderson
}
239 13e4df99 Richard Henderson
240 13e4df99 Richard Henderson
uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
241 13e4df99 Richard Henderson
{
242 13e4df99 Richard Henderson
    uint64_t res = 0;
243 13e4df99 Richard Henderson
    uint8_t opa, opb, opr;
244 13e4df99 Richard Henderson
    int i;
245 13e4df99 Richard Henderson
246 13e4df99 Richard Henderson
    for (i = 0; i < 8; ++i) {
247 13e4df99 Richard Henderson
        opa = op1 >> (i * 8);
248 13e4df99 Richard Henderson
        opb = op2 >> (i * 8);
249 13e4df99 Richard Henderson
        opr = opa > opb ? opa : opb;
250 13e4df99 Richard Henderson
        res |= (uint64_t)opr << (i * 8);
251 13e4df99 Richard Henderson
    }
252 13e4df99 Richard Henderson
    return res;
253 13e4df99 Richard Henderson
}
254 13e4df99 Richard Henderson
255 13e4df99 Richard Henderson
uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2)
256 13e4df99 Richard Henderson
{
257 13e4df99 Richard Henderson
    uint64_t res = 0;
258 13e4df99 Richard Henderson
    int8_t opa, opb;
259 13e4df99 Richard Henderson
    uint8_t opr;
260 13e4df99 Richard Henderson
    int i;
261 13e4df99 Richard Henderson
262 13e4df99 Richard Henderson
    for (i = 0; i < 8; ++i) {
263 13e4df99 Richard Henderson
        opa = op1 >> (i * 8);
264 13e4df99 Richard Henderson
        opb = op2 >> (i * 8);
265 13e4df99 Richard Henderson
        opr = opa > opb ? opa : opb;
266 13e4df99 Richard Henderson
        res |= (uint64_t)opr << (i * 8);
267 13e4df99 Richard Henderson
    }
268 13e4df99 Richard Henderson
    return res;
269 13e4df99 Richard Henderson
}
270 13e4df99 Richard Henderson
271 13e4df99 Richard Henderson
uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
272 13e4df99 Richard Henderson
{
273 13e4df99 Richard Henderson
    uint64_t res = 0;
274 13e4df99 Richard Henderson
    uint16_t opa, opb, opr;
275 13e4df99 Richard Henderson
    int i;
276 13e4df99 Richard Henderson
277 13e4df99 Richard Henderson
    for (i = 0; i < 4; ++i) {
278 13e4df99 Richard Henderson
        opa = op1 >> (i * 16);
279 13e4df99 Richard Henderson
        opb = op2 >> (i * 16);
280 13e4df99 Richard Henderson
        opr = opa > opb ? opa : opb;
281 13e4df99 Richard Henderson
        res |= (uint64_t)opr << (i * 16);
282 13e4df99 Richard Henderson
    }
283 13e4df99 Richard Henderson
    return res;
284 13e4df99 Richard Henderson
}
285 13e4df99 Richard Henderson
286 13e4df99 Richard Henderson
uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2)
287 13e4df99 Richard Henderson
{
288 13e4df99 Richard Henderson
    uint64_t res = 0;
289 13e4df99 Richard Henderson
    int16_t opa, opb;
290 13e4df99 Richard Henderson
    uint16_t opr;
291 13e4df99 Richard Henderson
    int i;
292 13e4df99 Richard Henderson
293 13e4df99 Richard Henderson
    for (i = 0; i < 4; ++i) {
294 13e4df99 Richard Henderson
        opa = op1 >> (i * 16);
295 13e4df99 Richard Henderson
        opb = op2 >> (i * 16);
296 13e4df99 Richard Henderson
        opr = opa > opb ? opa : opb;
297 13e4df99 Richard Henderson
        res |= (uint64_t)opr << (i * 16);
298 13e4df99 Richard Henderson
    }
299 13e4df99 Richard Henderson
    return res;
300 13e4df99 Richard Henderson
}
301 13e4df99 Richard Henderson
302 13e4df99 Richard Henderson
uint64_t helper_perr (uint64_t op1, uint64_t op2)
303 13e4df99 Richard Henderson
{
304 13e4df99 Richard Henderson
    uint64_t res = 0;
305 13e4df99 Richard Henderson
    uint8_t opa, opb, opr;
306 13e4df99 Richard Henderson
    int i;
307 13e4df99 Richard Henderson
308 13e4df99 Richard Henderson
    for (i = 0; i < 8; ++i) {
309 13e4df99 Richard Henderson
        opa = op1 >> (i * 8);
310 13e4df99 Richard Henderson
        opb = op2 >> (i * 8);
311 13e4df99 Richard Henderson
        if (opa >= opb)
312 13e4df99 Richard Henderson
            opr = opa - opb;
313 13e4df99 Richard Henderson
        else
314 13e4df99 Richard Henderson
            opr = opb - opa;
315 13e4df99 Richard Henderson
        res += opr;
316 13e4df99 Richard Henderson
    }
317 13e4df99 Richard Henderson
    return res;
318 13e4df99 Richard Henderson
}
319 13e4df99 Richard Henderson
320 13e4df99 Richard Henderson
uint64_t helper_pklb (uint64_t op1)
321 13e4df99 Richard Henderson
{
322 13e4df99 Richard Henderson
    return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
323 13e4df99 Richard Henderson
}
324 13e4df99 Richard Henderson
325 13e4df99 Richard Henderson
uint64_t helper_pkwb (uint64_t op1)
326 13e4df99 Richard Henderson
{
327 13e4df99 Richard Henderson
    return ((op1 & 0xff)
328 13e4df99 Richard Henderson
            | ((op1 >> 8) & 0xff00)
329 13e4df99 Richard Henderson
            | ((op1 >> 16) & 0xff0000)
330 13e4df99 Richard Henderson
            | ((op1 >> 24) & 0xff000000));
331 13e4df99 Richard Henderson
}
332 13e4df99 Richard Henderson
333 13e4df99 Richard Henderson
uint64_t helper_unpkbl (uint64_t op1)
334 13e4df99 Richard Henderson
{
335 13e4df99 Richard Henderson
    return (op1 & 0xff) | ((op1 & 0xff00) << 24);
336 13e4df99 Richard Henderson
}
337 13e4df99 Richard Henderson
338 13e4df99 Richard Henderson
uint64_t helper_unpkbw (uint64_t op1)
339 13e4df99 Richard Henderson
{
340 13e4df99 Richard Henderson
    return ((op1 & 0xff)
341 13e4df99 Richard Henderson
            | ((op1 & 0xff00) << 8)
342 13e4df99 Richard Henderson
            | ((op1 & 0xff0000) << 16)
343 13e4df99 Richard Henderson
            | ((op1 & 0xff000000) << 24));
344 13e4df99 Richard Henderson
}
345 13e4df99 Richard Henderson
346 f18cd223 aurel32
/* Floating point helpers */
347 f18cd223 aurel32
348 f24518b5 Richard Henderson
void helper_setroundmode (uint32_t val)
349 f24518b5 Richard Henderson
{
350 f24518b5 Richard Henderson
    set_float_rounding_mode(val, &FP_STATUS);
351 f24518b5 Richard Henderson
}
352 f24518b5 Richard Henderson
353 f24518b5 Richard Henderson
void helper_setflushzero (uint32_t val)
354 f24518b5 Richard Henderson
{
355 f24518b5 Richard Henderson
    set_flush_to_zero(val, &FP_STATUS);
356 f24518b5 Richard Henderson
}
357 f24518b5 Richard Henderson
358 f24518b5 Richard Henderson
void helper_fp_exc_clear (void)
359 f24518b5 Richard Henderson
{
360 f24518b5 Richard Henderson
    set_float_exception_flags(0, &FP_STATUS);
361 f24518b5 Richard Henderson
}
362 f24518b5 Richard Henderson
363 f24518b5 Richard Henderson
uint32_t helper_fp_exc_get (void)
364 f24518b5 Richard Henderson
{
365 f24518b5 Richard Henderson
    return get_float_exception_flags(&FP_STATUS);
366 f24518b5 Richard Henderson
}
367 f24518b5 Richard Henderson
368 f24518b5 Richard Henderson
/* Raise exceptions for ieee fp insns without software completion.
369 f24518b5 Richard Henderson
   In that case there are no exceptions that don't trap; the mask
370 f24518b5 Richard Henderson
   doesn't apply.  */
371 f24518b5 Richard Henderson
void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
372 f24518b5 Richard Henderson
{
373 f24518b5 Richard Henderson
    if (exc) {
374 f24518b5 Richard Henderson
        uint32_t hw_exc = 0;
375 f24518b5 Richard Henderson
376 f24518b5 Richard Henderson
        env->ipr[IPR_EXC_MASK] |= 1ull << regno;
377 f24518b5 Richard Henderson
378 f24518b5 Richard Henderson
        if (exc & float_flag_invalid) {
379 f24518b5 Richard Henderson
            hw_exc |= EXC_M_INV;
380 f24518b5 Richard Henderson
        }
381 f24518b5 Richard Henderson
        if (exc & float_flag_divbyzero) {
382 f24518b5 Richard Henderson
            hw_exc |= EXC_M_DZE;
383 f24518b5 Richard Henderson
        }
384 f24518b5 Richard Henderson
        if (exc & float_flag_overflow) {
385 f24518b5 Richard Henderson
            hw_exc |= EXC_M_FOV;
386 f24518b5 Richard Henderson
        }
387 f24518b5 Richard Henderson
        if (exc & float_flag_underflow) {
388 f24518b5 Richard Henderson
            hw_exc |= EXC_M_UNF;
389 f24518b5 Richard Henderson
        }
390 f24518b5 Richard Henderson
        if (exc & float_flag_inexact) {
391 f24518b5 Richard Henderson
            hw_exc |= EXC_M_INE;
392 f24518b5 Richard Henderson
        }
393 f24518b5 Richard Henderson
        helper_excp(EXCP_ARITH, hw_exc);
394 f24518b5 Richard Henderson
    }
395 f24518b5 Richard Henderson
}
396 f24518b5 Richard Henderson
397 f24518b5 Richard Henderson
/* Raise exceptions for ieee fp insns with software completion.  */
398 f24518b5 Richard Henderson
void helper_fp_exc_raise_s(uint32_t exc, uint32_t regno)
399 f24518b5 Richard Henderson
{
400 f24518b5 Richard Henderson
    if (exc) {
401 f24518b5 Richard Henderson
        env->fpcr_exc_status |= exc;
402 f24518b5 Richard Henderson
403 f24518b5 Richard Henderson
        exc &= ~env->fpcr_exc_mask;
404 f24518b5 Richard Henderson
        if (exc) {
405 f24518b5 Richard Henderson
            helper_fp_exc_raise(exc, regno);
406 f24518b5 Richard Henderson
        }
407 f24518b5 Richard Henderson
    }
408 f24518b5 Richard Henderson
}
409 f24518b5 Richard Henderson
410 f24518b5 Richard Henderson
/* Input remapping without software completion.  Handle denormal-map-to-zero
411 f24518b5 Richard Henderson
   and trap for all other non-finite numbers.  */
412 f24518b5 Richard Henderson
uint64_t helper_ieee_input(uint64_t val)
413 f24518b5 Richard Henderson
{
414 f24518b5 Richard Henderson
    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
415 f24518b5 Richard Henderson
    uint64_t frac = val & 0xfffffffffffffull;
416 f24518b5 Richard Henderson
417 f24518b5 Richard Henderson
    if (exp == 0) {
418 f24518b5 Richard Henderson
        if (frac != 0) {
419 f24518b5 Richard Henderson
            /* If DNZ is set flush denormals to zero on input.  */
420 f24518b5 Richard Henderson
            if (env->fpcr_dnz) {
421 f24518b5 Richard Henderson
                val &= 1ull << 63;
422 f24518b5 Richard Henderson
            } else {
423 f24518b5 Richard Henderson
                helper_excp(EXCP_ARITH, EXC_M_UNF);
424 f24518b5 Richard Henderson
            }
425 f24518b5 Richard Henderson
        }
426 f24518b5 Richard Henderson
    } else if (exp == 0x7ff) {
427 f24518b5 Richard Henderson
        /* Infinity or NaN.  */
428 f24518b5 Richard Henderson
        /* ??? I'm not sure these exception bit flags are correct.  I do
429 f24518b5 Richard Henderson
           know that the Linux kernel, at least, doesn't rely on them and
430 f24518b5 Richard Henderson
           just emulates the insn to figure out what exception to use.  */
431 f24518b5 Richard Henderson
        helper_excp(EXCP_ARITH, frac ? EXC_M_INV : EXC_M_FOV);
432 f24518b5 Richard Henderson
    }
433 f24518b5 Richard Henderson
    return val;
434 f24518b5 Richard Henderson
}
435 f24518b5 Richard Henderson
436 f24518b5 Richard Henderson
/* Similar, but does not trap for infinities.  Used for comparisons.  */
437 f24518b5 Richard Henderson
uint64_t helper_ieee_input_cmp(uint64_t val)
438 f24518b5 Richard Henderson
{
439 f24518b5 Richard Henderson
    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
440 f24518b5 Richard Henderson
    uint64_t frac = val & 0xfffffffffffffull;
441 f24518b5 Richard Henderson
442 f24518b5 Richard Henderson
    if (exp == 0) {
443 f24518b5 Richard Henderson
        if (frac != 0) {
444 f24518b5 Richard Henderson
            /* If DNZ is set flush denormals to zero on input.  */
445 f24518b5 Richard Henderson
            if (env->fpcr_dnz) {
446 f24518b5 Richard Henderson
                val &= 1ull << 63;
447 f24518b5 Richard Henderson
            } else {
448 f24518b5 Richard Henderson
                helper_excp(EXCP_ARITH, EXC_M_UNF);
449 f24518b5 Richard Henderson
            }
450 f24518b5 Richard Henderson
        }
451 f24518b5 Richard Henderson
    } else if (exp == 0x7ff && frac) {
452 f24518b5 Richard Henderson
        /* NaN.  */
453 f24518b5 Richard Henderson
        helper_excp(EXCP_ARITH, EXC_M_INV);
454 f24518b5 Richard Henderson
    }
455 f24518b5 Richard Henderson
    return val;
456 f24518b5 Richard Henderson
}
457 f24518b5 Richard Henderson
458 f24518b5 Richard Henderson
/* Input remapping with software completion enabled.  All we have to do
459 f24518b5 Richard Henderson
   is handle denormal-map-to-zero; all other inputs get exceptions as
460 f24518b5 Richard Henderson
   needed from the actual operation.  */
461 f24518b5 Richard Henderson
uint64_t helper_ieee_input_s(uint64_t val)
462 f24518b5 Richard Henderson
{
463 f24518b5 Richard Henderson
    if (env->fpcr_dnz) {
464 f24518b5 Richard Henderson
        uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
465 f24518b5 Richard Henderson
        if (exp == 0) {
466 f24518b5 Richard Henderson
            val &= 1ull << 63;
467 f24518b5 Richard Henderson
        }
468 f24518b5 Richard Henderson
    }
469 f24518b5 Richard Henderson
    return val;
470 f24518b5 Richard Henderson
}
471 f24518b5 Richard Henderson
472 f18cd223 aurel32
/* F floating (VAX) */
473 636aa200 Blue Swirl
static inline uint64_t float32_to_f(float32 fa)
474 4c9649a9 j_mayer
{
475 f18cd223 aurel32
    uint64_t r, exp, mant, sig;
476 e2eb2798 aurel32
    CPU_FloatU a;
477 f18cd223 aurel32
478 e2eb2798 aurel32
    a.f = fa;
479 e2eb2798 aurel32
    sig = ((uint64_t)a.l & 0x80000000) << 32;
480 e2eb2798 aurel32
    exp = (a.l >> 23) & 0xff;
481 e2eb2798 aurel32
    mant = ((uint64_t)a.l & 0x007fffff) << 29;
482 f18cd223 aurel32
483 f18cd223 aurel32
    if (exp == 255) {
484 f18cd223 aurel32
        /* NaN or infinity */
485 f18cd223 aurel32
        r = 1; /* VAX dirty zero */
486 f18cd223 aurel32
    } else if (exp == 0) {
487 f18cd223 aurel32
        if (mant == 0) {
488 f18cd223 aurel32
            /* Zero */
489 f18cd223 aurel32
            r = 0;
490 f18cd223 aurel32
        } else {
491 f18cd223 aurel32
            /* Denormalized */
492 f18cd223 aurel32
            r = sig | ((exp + 1) << 52) | mant;
493 f18cd223 aurel32
        }
494 f18cd223 aurel32
    } else {
495 f18cd223 aurel32
        if (exp >= 253) {
496 f18cd223 aurel32
            /* Overflow */
497 f18cd223 aurel32
            r = 1; /* VAX dirty zero */
498 f18cd223 aurel32
        } else {
499 f18cd223 aurel32
            r = sig | ((exp + 2) << 52);
500 f18cd223 aurel32
        }
501 f18cd223 aurel32
    }
502 f18cd223 aurel32
503 f18cd223 aurel32
    return r;
504 4c9649a9 j_mayer
}
505 4c9649a9 j_mayer
506 636aa200 Blue Swirl
static inline float32 f_to_float32(uint64_t a)
507 4c9649a9 j_mayer
{
508 e2eb2798 aurel32
    uint32_t exp, mant_sig;
509 e2eb2798 aurel32
    CPU_FloatU r;
510 f18cd223 aurel32
511 f18cd223 aurel32
    exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
512 f18cd223 aurel32
    mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
513 f18cd223 aurel32
514 f18cd223 aurel32
    if (unlikely(!exp && mant_sig)) {
515 f18cd223 aurel32
        /* Reserved operands / Dirty zero */
516 f18cd223 aurel32
        helper_excp(EXCP_OPCDEC, 0);
517 f18cd223 aurel32
    }
518 f18cd223 aurel32
519 f18cd223 aurel32
    if (exp < 3) {
520 f18cd223 aurel32
        /* Underflow */
521 e2eb2798 aurel32
        r.l = 0;
522 f18cd223 aurel32
    } else {
523 e2eb2798 aurel32
        r.l = ((exp - 2) << 23) | mant_sig;
524 f18cd223 aurel32
    }
525 f18cd223 aurel32
526 e2eb2798 aurel32
    return r.f;
527 4c9649a9 j_mayer
}
528 4c9649a9 j_mayer
529 f18cd223 aurel32
uint32_t helper_f_to_memory (uint64_t a)
530 4c9649a9 j_mayer
{
531 f18cd223 aurel32
    uint32_t r;
532 f18cd223 aurel32
    r =  (a & 0x00001fffe0000000ull) >> 13;
533 f18cd223 aurel32
    r |= (a & 0x07ffe00000000000ull) >> 45;
534 f18cd223 aurel32
    r |= (a & 0xc000000000000000ull) >> 48;
535 f18cd223 aurel32
    return r;
536 f18cd223 aurel32
}
537 4c9649a9 j_mayer
538 f18cd223 aurel32
uint64_t helper_memory_to_f (uint32_t a)
539 f18cd223 aurel32
{
540 f18cd223 aurel32
    uint64_t r;
541 f18cd223 aurel32
    r =  ((uint64_t)(a & 0x0000c000)) << 48;
542 f18cd223 aurel32
    r |= ((uint64_t)(a & 0x003fffff)) << 45;
543 f18cd223 aurel32
    r |= ((uint64_t)(a & 0xffff0000)) << 13;
544 f18cd223 aurel32
    if (!(a & 0x00004000))
545 f18cd223 aurel32
        r |= 0x7ll << 59;
546 f18cd223 aurel32
    return r;
547 4c9649a9 j_mayer
}
548 4c9649a9 j_mayer
549 f24518b5 Richard Henderson
/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong.  We should
550 f24518b5 Richard Henderson
   either implement VAX arithmetic properly or just signal invalid opcode.  */
551 f24518b5 Richard Henderson
552 f18cd223 aurel32
uint64_t helper_addf (uint64_t a, uint64_t b)
553 4c9649a9 j_mayer
{
554 f18cd223 aurel32
    float32 fa, fb, fr;
555 4c9649a9 j_mayer
556 f18cd223 aurel32
    fa = f_to_float32(a);
557 f18cd223 aurel32
    fb = f_to_float32(b);
558 f18cd223 aurel32
    fr = float32_add(fa, fb, &FP_STATUS);
559 f18cd223 aurel32
    return float32_to_f(fr);
560 4c9649a9 j_mayer
}
561 4c9649a9 j_mayer
562 f18cd223 aurel32
uint64_t helper_subf (uint64_t a, uint64_t b)
563 4c9649a9 j_mayer
{
564 f18cd223 aurel32
    float32 fa, fb, fr;
565 4c9649a9 j_mayer
566 f18cd223 aurel32
    fa = f_to_float32(a);
567 f18cd223 aurel32
    fb = f_to_float32(b);
568 f18cd223 aurel32
    fr = float32_sub(fa, fb, &FP_STATUS);
569 f18cd223 aurel32
    return float32_to_f(fr);
570 4c9649a9 j_mayer
}
571 4c9649a9 j_mayer
572 f18cd223 aurel32
uint64_t helper_mulf (uint64_t a, uint64_t b)
573 4c9649a9 j_mayer
{
574 f18cd223 aurel32
    float32 fa, fb, fr;
575 4c9649a9 j_mayer
576 f18cd223 aurel32
    fa = f_to_float32(a);
577 f18cd223 aurel32
    fb = f_to_float32(b);
578 f18cd223 aurel32
    fr = float32_mul(fa, fb, &FP_STATUS);
579 f18cd223 aurel32
    return float32_to_f(fr);
580 4c9649a9 j_mayer
}
581 4c9649a9 j_mayer
582 f18cd223 aurel32
uint64_t helper_divf (uint64_t a, uint64_t b)
583 4c9649a9 j_mayer
{
584 f18cd223 aurel32
    float32 fa, fb, fr;
585 4c9649a9 j_mayer
586 f18cd223 aurel32
    fa = f_to_float32(a);
587 f18cd223 aurel32
    fb = f_to_float32(b);
588 f18cd223 aurel32
    fr = float32_div(fa, fb, &FP_STATUS);
589 f18cd223 aurel32
    return float32_to_f(fr);
590 4c9649a9 j_mayer
}
591 4c9649a9 j_mayer
592 f18cd223 aurel32
uint64_t helper_sqrtf (uint64_t t)
593 4c9649a9 j_mayer
{
594 f18cd223 aurel32
    float32 ft, fr;
595 f18cd223 aurel32
596 f18cd223 aurel32
    ft = f_to_float32(t);
597 f18cd223 aurel32
    fr = float32_sqrt(ft, &FP_STATUS);
598 f18cd223 aurel32
    return float32_to_f(fr);
599 4c9649a9 j_mayer
}
600 4c9649a9 j_mayer
601 f18cd223 aurel32
602 f18cd223 aurel32
/* G floating (VAX) */
603 636aa200 Blue Swirl
static inline uint64_t float64_to_g(float64 fa)
604 4c9649a9 j_mayer
{
605 e2eb2798 aurel32
    uint64_t r, exp, mant, sig;
606 e2eb2798 aurel32
    CPU_DoubleU a;
607 4c9649a9 j_mayer
608 e2eb2798 aurel32
    a.d = fa;
609 e2eb2798 aurel32
    sig = a.ll & 0x8000000000000000ull;
610 e2eb2798 aurel32
    exp = (a.ll >> 52) & 0x7ff;
611 e2eb2798 aurel32
    mant = a.ll & 0x000fffffffffffffull;
612 f18cd223 aurel32
613 f18cd223 aurel32
    if (exp == 2047) {
614 f18cd223 aurel32
        /* NaN or infinity */
615 f18cd223 aurel32
        r = 1; /* VAX dirty zero */
616 f18cd223 aurel32
    } else if (exp == 0) {
617 f18cd223 aurel32
        if (mant == 0) {
618 f18cd223 aurel32
            /* Zero */
619 f18cd223 aurel32
            r = 0;
620 f18cd223 aurel32
        } else {
621 f18cd223 aurel32
            /* Denormalized */
622 f18cd223 aurel32
            r = sig | ((exp + 1) << 52) | mant;
623 f18cd223 aurel32
        }
624 f18cd223 aurel32
    } else {
625 f18cd223 aurel32
        if (exp >= 2045) {
626 f18cd223 aurel32
            /* Overflow */
627 f18cd223 aurel32
            r = 1; /* VAX dirty zero */
628 f18cd223 aurel32
        } else {
629 f18cd223 aurel32
            r = sig | ((exp + 2) << 52);
630 f18cd223 aurel32
        }
631 f18cd223 aurel32
    }
632 f18cd223 aurel32
633 f18cd223 aurel32
    return r;
634 4c9649a9 j_mayer
}
635 4c9649a9 j_mayer
636 636aa200 Blue Swirl
static inline float64 g_to_float64(uint64_t a)
637 4c9649a9 j_mayer
{
638 e2eb2798 aurel32
    uint64_t exp, mant_sig;
639 e2eb2798 aurel32
    CPU_DoubleU r;
640 f18cd223 aurel32
641 f18cd223 aurel32
    exp = (a >> 52) & 0x7ff;
642 f18cd223 aurel32
    mant_sig = a & 0x800fffffffffffffull;
643 f18cd223 aurel32
644 f18cd223 aurel32
    if (!exp && mant_sig) {
645 f18cd223 aurel32
        /* Reserved operands / Dirty zero */
646 f18cd223 aurel32
        helper_excp(EXCP_OPCDEC, 0);
647 f18cd223 aurel32
    }
648 4c9649a9 j_mayer
649 f18cd223 aurel32
    if (exp < 3) {
650 f18cd223 aurel32
        /* Underflow */
651 e2eb2798 aurel32
        r.ll = 0;
652 f18cd223 aurel32
    } else {
653 e2eb2798 aurel32
        r.ll = ((exp - 2) << 52) | mant_sig;
654 f18cd223 aurel32
    }
655 f18cd223 aurel32
656 e2eb2798 aurel32
    return r.d;
657 4c9649a9 j_mayer
}
658 4c9649a9 j_mayer
659 f18cd223 aurel32
uint64_t helper_g_to_memory (uint64_t a)
660 4c9649a9 j_mayer
{
661 f18cd223 aurel32
    uint64_t r;
662 f18cd223 aurel32
    r =  (a & 0x000000000000ffffull) << 48;
663 f18cd223 aurel32
    r |= (a & 0x00000000ffff0000ull) << 16;
664 f18cd223 aurel32
    r |= (a & 0x0000ffff00000000ull) >> 16;
665 f18cd223 aurel32
    r |= (a & 0xffff000000000000ull) >> 48;
666 f18cd223 aurel32
    return r;
667 f18cd223 aurel32
}
668 4c9649a9 j_mayer
669 f18cd223 aurel32
uint64_t helper_memory_to_g (uint64_t a)
670 f18cd223 aurel32
{
671 f18cd223 aurel32
    uint64_t r;
672 f18cd223 aurel32
    r =  (a & 0x000000000000ffffull) << 48;
673 f18cd223 aurel32
    r |= (a & 0x00000000ffff0000ull) << 16;
674 f18cd223 aurel32
    r |= (a & 0x0000ffff00000000ull) >> 16;
675 f18cd223 aurel32
    r |= (a & 0xffff000000000000ull) >> 48;
676 f18cd223 aurel32
    return r;
677 4c9649a9 j_mayer
}
678 4c9649a9 j_mayer
679 f18cd223 aurel32
uint64_t helper_addg (uint64_t a, uint64_t b)
680 4c9649a9 j_mayer
{
681 f18cd223 aurel32
    float64 fa, fb, fr;
682 4c9649a9 j_mayer
683 f18cd223 aurel32
    fa = g_to_float64(a);
684 f18cd223 aurel32
    fb = g_to_float64(b);
685 f18cd223 aurel32
    fr = float64_add(fa, fb, &FP_STATUS);
686 f18cd223 aurel32
    return float64_to_g(fr);
687 4c9649a9 j_mayer
}
688 4c9649a9 j_mayer
689 f18cd223 aurel32
uint64_t helper_subg (uint64_t a, uint64_t b)
690 4c9649a9 j_mayer
{
691 f18cd223 aurel32
    float64 fa, fb, fr;
692 4c9649a9 j_mayer
693 f18cd223 aurel32
    fa = g_to_float64(a);
694 f18cd223 aurel32
    fb = g_to_float64(b);
695 f18cd223 aurel32
    fr = float64_sub(fa, fb, &FP_STATUS);
696 f18cd223 aurel32
    return float64_to_g(fr);
697 4c9649a9 j_mayer
}
698 4c9649a9 j_mayer
699 f18cd223 aurel32
uint64_t helper_mulg (uint64_t a, uint64_t b)
700 4c9649a9 j_mayer
{
701 f18cd223 aurel32
    float64 fa, fb, fr;
702 4c9649a9 j_mayer
703 f18cd223 aurel32
    fa = g_to_float64(a);
704 f18cd223 aurel32
    fb = g_to_float64(b);
705 f18cd223 aurel32
    fr = float64_mul(fa, fb, &FP_STATUS);
706 f18cd223 aurel32
    return float64_to_g(fr);
707 4c9649a9 j_mayer
}
708 4c9649a9 j_mayer
709 f18cd223 aurel32
uint64_t helper_divg (uint64_t a, uint64_t b)
710 4c9649a9 j_mayer
{
711 f18cd223 aurel32
    float64 fa, fb, fr;
712 4c9649a9 j_mayer
713 f18cd223 aurel32
    fa = g_to_float64(a);
714 f18cd223 aurel32
    fb = g_to_float64(b);
715 f18cd223 aurel32
    fr = float64_div(fa, fb, &FP_STATUS);
716 f18cd223 aurel32
    return float64_to_g(fr);
717 f18cd223 aurel32
}
718 f18cd223 aurel32
719 f18cd223 aurel32
uint64_t helper_sqrtg (uint64_t a)
720 f18cd223 aurel32
{
721 f18cd223 aurel32
    float64 fa, fr;
722 4c9649a9 j_mayer
723 f18cd223 aurel32
    fa = g_to_float64(a);
724 f18cd223 aurel32
    fr = float64_sqrt(fa, &FP_STATUS);
725 f18cd223 aurel32
    return float64_to_g(fr);
726 4c9649a9 j_mayer
}
727 4c9649a9 j_mayer
728 f18cd223 aurel32
729 f18cd223 aurel32
/* S floating (single) */
730 d0af5445 Richard Henderson
731 d0af5445 Richard Henderson
/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg.  */
732 d0af5445 Richard Henderson
static inline uint64_t float32_to_s_int(uint32_t fi)
733 d0af5445 Richard Henderson
{
734 d0af5445 Richard Henderson
    uint32_t frac = fi & 0x7fffff;
735 d0af5445 Richard Henderson
    uint32_t sign = fi >> 31;
736 d0af5445 Richard Henderson
    uint32_t exp_msb = (fi >> 30) & 1;
737 d0af5445 Richard Henderson
    uint32_t exp_low = (fi >> 23) & 0x7f;
738 d0af5445 Richard Henderson
    uint32_t exp;
739 d0af5445 Richard Henderson
740 d0af5445 Richard Henderson
    exp = (exp_msb << 10) | exp_low;
741 d0af5445 Richard Henderson
    if (exp_msb) {
742 d0af5445 Richard Henderson
        if (exp_low == 0x7f)
743 d0af5445 Richard Henderson
            exp = 0x7ff;
744 d0af5445 Richard Henderson
    } else {
745 d0af5445 Richard Henderson
        if (exp_low != 0x00)
746 d0af5445 Richard Henderson
            exp |= 0x380;
747 d0af5445 Richard Henderson
    }
748 d0af5445 Richard Henderson
749 d0af5445 Richard Henderson
    return (((uint64_t)sign << 63)
750 d0af5445 Richard Henderson
            | ((uint64_t)exp << 52)
751 d0af5445 Richard Henderson
            | ((uint64_t)frac << 29));
752 d0af5445 Richard Henderson
}
753 d0af5445 Richard Henderson
754 636aa200 Blue Swirl
static inline uint64_t float32_to_s(float32 fa)
755 4c9649a9 j_mayer
{
756 e2eb2798 aurel32
    CPU_FloatU a;
757 e2eb2798 aurel32
    a.f = fa;
758 d0af5445 Richard Henderson
    return float32_to_s_int(a.l);
759 d0af5445 Richard Henderson
}
760 4c9649a9 j_mayer
761 d0af5445 Richard Henderson
static inline uint32_t s_to_float32_int(uint64_t a)
762 d0af5445 Richard Henderson
{
763 d0af5445 Richard Henderson
    return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
764 4c9649a9 j_mayer
}
765 4c9649a9 j_mayer
766 636aa200 Blue Swirl
static inline float32 s_to_float32(uint64_t a)
767 4c9649a9 j_mayer
{
768 e2eb2798 aurel32
    CPU_FloatU r;
769 d0af5445 Richard Henderson
    r.l = s_to_float32_int(a);
770 e2eb2798 aurel32
    return r.f;
771 f18cd223 aurel32
}
772 4c9649a9 j_mayer
773 f18cd223 aurel32
uint32_t helper_s_to_memory (uint64_t a)
774 f18cd223 aurel32
{
775 d0af5445 Richard Henderson
    return s_to_float32_int(a);
776 f18cd223 aurel32
}
777 4c9649a9 j_mayer
778 f18cd223 aurel32
uint64_t helper_memory_to_s (uint32_t a)
779 f18cd223 aurel32
{
780 d0af5445 Richard Henderson
    return float32_to_s_int(a);
781 4c9649a9 j_mayer
}
782 4c9649a9 j_mayer
783 f18cd223 aurel32
uint64_t helper_adds (uint64_t a, uint64_t b)
784 4c9649a9 j_mayer
{
785 f18cd223 aurel32
    float32 fa, fb, fr;
786 4c9649a9 j_mayer
787 f18cd223 aurel32
    fa = s_to_float32(a);
788 f18cd223 aurel32
    fb = s_to_float32(b);
789 f18cd223 aurel32
    fr = float32_add(fa, fb, &FP_STATUS);
790 f18cd223 aurel32
    return float32_to_s(fr);
791 4c9649a9 j_mayer
}
792 4c9649a9 j_mayer
793 f18cd223 aurel32
uint64_t helper_subs (uint64_t a, uint64_t b)
794 4c9649a9 j_mayer
{
795 f18cd223 aurel32
    float32 fa, fb, fr;
796 4c9649a9 j_mayer
797 f18cd223 aurel32
    fa = s_to_float32(a);
798 f18cd223 aurel32
    fb = s_to_float32(b);
799 f18cd223 aurel32
    fr = float32_sub(fa, fb, &FP_STATUS);
800 f18cd223 aurel32
    return float32_to_s(fr);
801 4c9649a9 j_mayer
}
802 4c9649a9 j_mayer
803 f18cd223 aurel32
uint64_t helper_muls (uint64_t a, uint64_t b)
804 4c9649a9 j_mayer
{
805 f18cd223 aurel32
    float32 fa, fb, fr;
806 4c9649a9 j_mayer
807 f18cd223 aurel32
    fa = s_to_float32(a);
808 f18cd223 aurel32
    fb = s_to_float32(b);
809 f18cd223 aurel32
    fr = float32_mul(fa, fb, &FP_STATUS);
810 f18cd223 aurel32
    return float32_to_s(fr);
811 4c9649a9 j_mayer
}
812 4c9649a9 j_mayer
813 f18cd223 aurel32
uint64_t helper_divs (uint64_t a, uint64_t b)
814 4c9649a9 j_mayer
{
815 f18cd223 aurel32
    float32 fa, fb, fr;
816 4c9649a9 j_mayer
817 f18cd223 aurel32
    fa = s_to_float32(a);
818 f18cd223 aurel32
    fb = s_to_float32(b);
819 f18cd223 aurel32
    fr = float32_div(fa, fb, &FP_STATUS);
820 f18cd223 aurel32
    return float32_to_s(fr);
821 4c9649a9 j_mayer
}
822 4c9649a9 j_mayer
823 f18cd223 aurel32
uint64_t helper_sqrts (uint64_t a)
824 4c9649a9 j_mayer
{
825 f18cd223 aurel32
    float32 fa, fr;
826 4c9649a9 j_mayer
827 f18cd223 aurel32
    fa = s_to_float32(a);
828 f18cd223 aurel32
    fr = float32_sqrt(fa, &FP_STATUS);
829 f18cd223 aurel32
    return float32_to_s(fr);
830 4c9649a9 j_mayer
}
831 4c9649a9 j_mayer
832 f18cd223 aurel32
833 f18cd223 aurel32
/* T floating (double) */
834 636aa200 Blue Swirl
static inline float64 t_to_float64(uint64_t a)
835 4c9649a9 j_mayer
{
836 f18cd223 aurel32
    /* Memory format is the same as float64 */
837 e2eb2798 aurel32
    CPU_DoubleU r;
838 e2eb2798 aurel32
    r.ll = a;
839 e2eb2798 aurel32
    return r.d;
840 4c9649a9 j_mayer
}
841 4c9649a9 j_mayer
842 636aa200 Blue Swirl
static inline uint64_t float64_to_t(float64 fa)
843 4c9649a9 j_mayer
{
844 f18cd223 aurel32
    /* Memory format is the same as float64 */
845 e2eb2798 aurel32
    CPU_DoubleU r;
846 e2eb2798 aurel32
    r.d = fa;
847 e2eb2798 aurel32
    return r.ll;
848 f18cd223 aurel32
}
849 4c9649a9 j_mayer
850 f18cd223 aurel32
uint64_t helper_addt (uint64_t a, uint64_t b)
851 f18cd223 aurel32
{
852 f18cd223 aurel32
    float64 fa, fb, fr;
853 4c9649a9 j_mayer
854 f18cd223 aurel32
    fa = t_to_float64(a);
855 f18cd223 aurel32
    fb = t_to_float64(b);
856 f18cd223 aurel32
    fr = float64_add(fa, fb, &FP_STATUS);
857 f18cd223 aurel32
    return float64_to_t(fr);
858 4c9649a9 j_mayer
}
859 4c9649a9 j_mayer
860 f18cd223 aurel32
uint64_t helper_subt (uint64_t a, uint64_t b)
861 4c9649a9 j_mayer
{
862 f18cd223 aurel32
    float64 fa, fb, fr;
863 4c9649a9 j_mayer
864 f18cd223 aurel32
    fa = t_to_float64(a);
865 f18cd223 aurel32
    fb = t_to_float64(b);
866 f18cd223 aurel32
    fr = float64_sub(fa, fb, &FP_STATUS);
867 f18cd223 aurel32
    return float64_to_t(fr);
868 4c9649a9 j_mayer
}
869 4c9649a9 j_mayer
870 f18cd223 aurel32
uint64_t helper_mult (uint64_t a, uint64_t b)
871 4c9649a9 j_mayer
{
872 f18cd223 aurel32
    float64 fa, fb, fr;
873 4c9649a9 j_mayer
874 f18cd223 aurel32
    fa = t_to_float64(a);
875 f18cd223 aurel32
    fb = t_to_float64(b);
876 f18cd223 aurel32
    fr = float64_mul(fa, fb, &FP_STATUS);
877 f18cd223 aurel32
    return float64_to_t(fr);
878 4c9649a9 j_mayer
}
879 4c9649a9 j_mayer
880 f18cd223 aurel32
uint64_t helper_divt (uint64_t a, uint64_t b)
881 4c9649a9 j_mayer
{
882 f18cd223 aurel32
    float64 fa, fb, fr;
883 4c9649a9 j_mayer
884 f18cd223 aurel32
    fa = t_to_float64(a);
885 f18cd223 aurel32
    fb = t_to_float64(b);
886 f18cd223 aurel32
    fr = float64_div(fa, fb, &FP_STATUS);
887 f18cd223 aurel32
    return float64_to_t(fr);
888 4c9649a9 j_mayer
}
889 4c9649a9 j_mayer
890 f18cd223 aurel32
uint64_t helper_sqrtt (uint64_t a)
891 4c9649a9 j_mayer
{
892 f18cd223 aurel32
    float64 fa, fr;
893 4c9649a9 j_mayer
894 f18cd223 aurel32
    fa = t_to_float64(a);
895 f18cd223 aurel32
    fr = float64_sqrt(fa, &FP_STATUS);
896 f18cd223 aurel32
    return float64_to_t(fr);
897 4c9649a9 j_mayer
}
898 4c9649a9 j_mayer
899 f18cd223 aurel32
/* Comparisons */
900 f18cd223 aurel32
uint64_t helper_cmptun (uint64_t a, uint64_t b)
901 4c9649a9 j_mayer
{
902 f18cd223 aurel32
    float64 fa, fb;
903 4c9649a9 j_mayer
904 f18cd223 aurel32
    fa = t_to_float64(a);
905 f18cd223 aurel32
    fb = t_to_float64(b);
906 f18cd223 aurel32
907 a4d2d1a0 Aurelien Jarno
    if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
908 f18cd223 aurel32
        return 0x4000000000000000ULL;
909 a4d2d1a0 Aurelien Jarno
    } else {
910 f18cd223 aurel32
        return 0;
911 a4d2d1a0 Aurelien Jarno
    }
912 4c9649a9 j_mayer
}
913 4c9649a9 j_mayer
914 f18cd223 aurel32
uint64_t helper_cmpteq(uint64_t a, uint64_t b)
915 4c9649a9 j_mayer
{
916 f18cd223 aurel32
    float64 fa, fb;
917 4c9649a9 j_mayer
918 f18cd223 aurel32
    fa = t_to_float64(a);
919 f18cd223 aurel32
    fb = t_to_float64(b);
920 f18cd223 aurel32
921 211315fb Aurelien Jarno
    if (float64_eq_quiet(fa, fb, &FP_STATUS))
922 f18cd223 aurel32
        return 0x4000000000000000ULL;
923 f18cd223 aurel32
    else
924 f18cd223 aurel32
        return 0;
925 4c9649a9 j_mayer
}
926 4c9649a9 j_mayer
927 f18cd223 aurel32
uint64_t helper_cmptle(uint64_t a, uint64_t b)
928 4c9649a9 j_mayer
{
929 f18cd223 aurel32
    float64 fa, fb;
930 4c9649a9 j_mayer
931 f18cd223 aurel32
    fa = t_to_float64(a);
932 f18cd223 aurel32
    fb = t_to_float64(b);
933 f18cd223 aurel32
934 f18cd223 aurel32
    if (float64_le(fa, fb, &FP_STATUS))
935 f18cd223 aurel32
        return 0x4000000000000000ULL;
936 f18cd223 aurel32
    else
937 f18cd223 aurel32
        return 0;
938 4c9649a9 j_mayer
}
939 4c9649a9 j_mayer
940 f18cd223 aurel32
uint64_t helper_cmptlt(uint64_t a, uint64_t b)
941 4c9649a9 j_mayer
{
942 f18cd223 aurel32
    float64 fa, fb;
943 4c9649a9 j_mayer
944 f18cd223 aurel32
    fa = t_to_float64(a);
945 f18cd223 aurel32
    fb = t_to_float64(b);
946 f18cd223 aurel32
947 f18cd223 aurel32
    if (float64_lt(fa, fb, &FP_STATUS))
948 f18cd223 aurel32
        return 0x4000000000000000ULL;
949 f18cd223 aurel32
    else
950 f18cd223 aurel32
        return 0;
951 4c9649a9 j_mayer
}
952 4c9649a9 j_mayer
953 f18cd223 aurel32
uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
954 4c9649a9 j_mayer
{
955 f18cd223 aurel32
    float64 fa, fb;
956 4c9649a9 j_mayer
957 f18cd223 aurel32
    fa = g_to_float64(a);
958 f18cd223 aurel32
    fb = g_to_float64(b);
959 f18cd223 aurel32
960 211315fb Aurelien Jarno
    if (float64_eq_quiet(fa, fb, &FP_STATUS))
961 f18cd223 aurel32
        return 0x4000000000000000ULL;
962 f18cd223 aurel32
    else
963 f18cd223 aurel32
        return 0;
964 4c9649a9 j_mayer
}
965 4c9649a9 j_mayer
966 f18cd223 aurel32
uint64_t helper_cmpgle(uint64_t a, uint64_t b)
967 4c9649a9 j_mayer
{
968 f18cd223 aurel32
    float64 fa, fb;
969 f18cd223 aurel32
970 f18cd223 aurel32
    fa = g_to_float64(a);
971 f18cd223 aurel32
    fb = g_to_float64(b);
972 4c9649a9 j_mayer
973 f18cd223 aurel32
    if (float64_le(fa, fb, &FP_STATUS))
974 f18cd223 aurel32
        return 0x4000000000000000ULL;
975 f18cd223 aurel32
    else
976 f18cd223 aurel32
        return 0;
977 4c9649a9 j_mayer
}
978 4c9649a9 j_mayer
979 f18cd223 aurel32
uint64_t helper_cmpglt(uint64_t a, uint64_t b)
980 4c9649a9 j_mayer
{
981 f18cd223 aurel32
    float64 fa, fb;
982 f18cd223 aurel32
983 f18cd223 aurel32
    fa = g_to_float64(a);
984 f18cd223 aurel32
    fb = g_to_float64(b);
985 4c9649a9 j_mayer
986 f18cd223 aurel32
    if (float64_lt(fa, fb, &FP_STATUS))
987 f18cd223 aurel32
        return 0x4000000000000000ULL;
988 f18cd223 aurel32
    else
989 f18cd223 aurel32
        return 0;
990 4c9649a9 j_mayer
}
991 4c9649a9 j_mayer
992 f18cd223 aurel32
/* Floating point format conversion */
993 f18cd223 aurel32
uint64_t helper_cvtts (uint64_t a)
994 4c9649a9 j_mayer
{
995 f18cd223 aurel32
    float64 fa;
996 f18cd223 aurel32
    float32 fr;
997 4c9649a9 j_mayer
998 f18cd223 aurel32
    fa = t_to_float64(a);
999 f18cd223 aurel32
    fr = float64_to_float32(fa, &FP_STATUS);
1000 f18cd223 aurel32
    return float32_to_s(fr);
1001 4c9649a9 j_mayer
}
1002 4c9649a9 j_mayer
1003 f18cd223 aurel32
uint64_t helper_cvtst (uint64_t a)
1004 4c9649a9 j_mayer
{
1005 f18cd223 aurel32
    float32 fa;
1006 f18cd223 aurel32
    float64 fr;
1007 f18cd223 aurel32
1008 f18cd223 aurel32
    fa = s_to_float32(a);
1009 f18cd223 aurel32
    fr = float32_to_float64(fa, &FP_STATUS);
1010 f18cd223 aurel32
    return float64_to_t(fr);
1011 4c9649a9 j_mayer
}
1012 4c9649a9 j_mayer
1013 f18cd223 aurel32
uint64_t helper_cvtqs (uint64_t a)
1014 4c9649a9 j_mayer
{
1015 f18cd223 aurel32
    float32 fr = int64_to_float32(a, &FP_STATUS);
1016 f18cd223 aurel32
    return float32_to_s(fr);
1017 4c9649a9 j_mayer
}
1018 4c9649a9 j_mayer
1019 f24518b5 Richard Henderson
/* Implement float64 to uint64 conversion without saturation -- we must
1020 f24518b5 Richard Henderson
   supply the truncated result.  This behaviour is used by the compiler
1021 f24518b5 Richard Henderson
   to get unsigned conversion for free with the same instruction.
1022 f24518b5 Richard Henderson

1023 f24518b5 Richard Henderson
   The VI flag is set when overflow or inexact exceptions should be raised.  */
1024 f24518b5 Richard Henderson
1025 f24518b5 Richard Henderson
static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI)
1026 4c9649a9 j_mayer
{
1027 f24518b5 Richard Henderson
    uint64_t frac, ret = 0;
1028 f24518b5 Richard Henderson
    uint32_t exp, sign, exc = 0;
1029 f24518b5 Richard Henderson
    int shift;
1030 f24518b5 Richard Henderson
1031 f24518b5 Richard Henderson
    sign = (a >> 63);
1032 f24518b5 Richard Henderson
    exp = (uint32_t)(a >> 52) & 0x7ff;
1033 f24518b5 Richard Henderson
    frac = a & 0xfffffffffffffull;
1034 f24518b5 Richard Henderson
1035 f24518b5 Richard Henderson
    if (exp == 0) {
1036 f24518b5 Richard Henderson
        if (unlikely(frac != 0)) {
1037 f24518b5 Richard Henderson
            goto do_underflow;
1038 f24518b5 Richard Henderson
        }
1039 f24518b5 Richard Henderson
    } else if (exp == 0x7ff) {
1040 f24518b5 Richard Henderson
        exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
1041 f24518b5 Richard Henderson
    } else {
1042 f24518b5 Richard Henderson
        /* Restore implicit bit.  */
1043 f24518b5 Richard Henderson
        frac |= 0x10000000000000ull;
1044 f24518b5 Richard Henderson
1045 f24518b5 Richard Henderson
        shift = exp - 1023 - 52;
1046 f24518b5 Richard Henderson
        if (shift >= 0) {
1047 f24518b5 Richard Henderson
            /* In this case the number is so large that we must shift
1048 f24518b5 Richard Henderson
               the fraction left.  There is no rounding to do.  */
1049 f24518b5 Richard Henderson
            if (shift < 63) {
1050 f24518b5 Richard Henderson
                ret = frac << shift;
1051 f24518b5 Richard Henderson
                if (VI && (ret >> shift) != frac) {
1052 f24518b5 Richard Henderson
                    exc = float_flag_overflow;
1053 f24518b5 Richard Henderson
                }
1054 f24518b5 Richard Henderson
            }
1055 f24518b5 Richard Henderson
        } else {
1056 f24518b5 Richard Henderson
            uint64_t round;
1057 f24518b5 Richard Henderson
1058 f24518b5 Richard Henderson
            /* In this case the number is smaller than the fraction as
1059 f24518b5 Richard Henderson
               represented by the 52 bit number.  Here we must think
1060 f24518b5 Richard Henderson
               about rounding the result.  Handle this by shifting the
1061 f24518b5 Richard Henderson
               fractional part of the number into the high bits of ROUND.
1062 f24518b5 Richard Henderson
               This will let us efficiently handle round-to-nearest.  */
1063 f24518b5 Richard Henderson
            shift = -shift;
1064 f24518b5 Richard Henderson
            if (shift < 63) {
1065 f24518b5 Richard Henderson
                ret = frac >> shift;
1066 f24518b5 Richard Henderson
                round = frac << (64 - shift);
1067 f24518b5 Richard Henderson
            } else {
1068 f24518b5 Richard Henderson
                /* The exponent is so small we shift out everything.
1069 f24518b5 Richard Henderson
                   Leave a sticky bit for proper rounding below.  */
1070 f24518b5 Richard Henderson
            do_underflow:
1071 f24518b5 Richard Henderson
                round = 1;
1072 f24518b5 Richard Henderson
            }
1073 f24518b5 Richard Henderson
1074 f24518b5 Richard Henderson
            if (round) {
1075 f24518b5 Richard Henderson
                exc = (VI ? float_flag_inexact : 0);
1076 f24518b5 Richard Henderson
                switch (roundmode) {
1077 f24518b5 Richard Henderson
                case float_round_nearest_even:
1078 f24518b5 Richard Henderson
                    if (round == (1ull << 63)) {
1079 f24518b5 Richard Henderson
                        /* Fraction is exactly 0.5; round to even.  */
1080 f24518b5 Richard Henderson
                        ret += (ret & 1);
1081 f24518b5 Richard Henderson
                    } else if (round > (1ull << 63)) {
1082 f24518b5 Richard Henderson
                        ret += 1;
1083 f24518b5 Richard Henderson
                    }
1084 f24518b5 Richard Henderson
                    break;
1085 f24518b5 Richard Henderson
                case float_round_to_zero:
1086 f24518b5 Richard Henderson
                    break;
1087 f24518b5 Richard Henderson
                case float_round_up:
1088 f24518b5 Richard Henderson
                    ret += 1 - sign;
1089 f24518b5 Richard Henderson
                    break;
1090 f24518b5 Richard Henderson
                case float_round_down:
1091 f24518b5 Richard Henderson
                    ret += sign;
1092 f24518b5 Richard Henderson
                    break;
1093 f24518b5 Richard Henderson
                }
1094 f24518b5 Richard Henderson
            }
1095 f24518b5 Richard Henderson
        }
1096 f24518b5 Richard Henderson
        if (sign) {
1097 f24518b5 Richard Henderson
            ret = -ret;
1098 f24518b5 Richard Henderson
        }
1099 f24518b5 Richard Henderson
    }
1100 f24518b5 Richard Henderson
    if (unlikely(exc)) {
1101 f24518b5 Richard Henderson
        float_raise(exc, &FP_STATUS);
1102 f24518b5 Richard Henderson
    }
1103 f24518b5 Richard Henderson
1104 f24518b5 Richard Henderson
    return ret;
1105 f24518b5 Richard Henderson
}
1106 f24518b5 Richard Henderson
1107 f24518b5 Richard Henderson
uint64_t helper_cvttq(uint64_t a)
1108 f24518b5 Richard Henderson
{
1109 f24518b5 Richard Henderson
    return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1);
1110 f24518b5 Richard Henderson
}
1111 f24518b5 Richard Henderson
1112 f24518b5 Richard Henderson
uint64_t helper_cvttq_c(uint64_t a)
1113 f24518b5 Richard Henderson
{
1114 f24518b5 Richard Henderson
    return helper_cvttq_internal(a, float_round_to_zero, 0);
1115 f24518b5 Richard Henderson
}
1116 f24518b5 Richard Henderson
1117 f24518b5 Richard Henderson
uint64_t helper_cvttq_svic(uint64_t a)
1118 f24518b5 Richard Henderson
{
1119 f24518b5 Richard Henderson
    return helper_cvttq_internal(a, float_round_to_zero, 1);
1120 f18cd223 aurel32
}
1121 4c9649a9 j_mayer
1122 f18cd223 aurel32
uint64_t helper_cvtqt (uint64_t a)
1123 f18cd223 aurel32
{
1124 f18cd223 aurel32
    float64 fr = int64_to_float64(a, &FP_STATUS);
1125 f18cd223 aurel32
    return float64_to_t(fr);
1126 4c9649a9 j_mayer
}
1127 4c9649a9 j_mayer
1128 f18cd223 aurel32
uint64_t helper_cvtqf (uint64_t a)
1129 4c9649a9 j_mayer
{
1130 f18cd223 aurel32
    float32 fr = int64_to_float32(a, &FP_STATUS);
1131 f18cd223 aurel32
    return float32_to_f(fr);
1132 4c9649a9 j_mayer
}
1133 4c9649a9 j_mayer
1134 f18cd223 aurel32
uint64_t helper_cvtgf (uint64_t a)
1135 4c9649a9 j_mayer
{
1136 f18cd223 aurel32
    float64 fa;
1137 f18cd223 aurel32
    float32 fr;
1138 f18cd223 aurel32
1139 f18cd223 aurel32
    fa = g_to_float64(a);
1140 f18cd223 aurel32
    fr = float64_to_float32(fa, &FP_STATUS);
1141 f18cd223 aurel32
    return float32_to_f(fr);
1142 4c9649a9 j_mayer
}
1143 4c9649a9 j_mayer
1144 f18cd223 aurel32
uint64_t helper_cvtgq (uint64_t a)
1145 4c9649a9 j_mayer
{
1146 f18cd223 aurel32
    float64 fa = g_to_float64(a);
1147 f18cd223 aurel32
    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
1148 4c9649a9 j_mayer
}
1149 4c9649a9 j_mayer
1150 f18cd223 aurel32
uint64_t helper_cvtqg (uint64_t a)
1151 4c9649a9 j_mayer
{
1152 f18cd223 aurel32
    float64 fr;
1153 f18cd223 aurel32
    fr = int64_to_float64(a, &FP_STATUS);
1154 f18cd223 aurel32
    return float64_to_g(fr);
1155 4c9649a9 j_mayer
}
1156 4c9649a9 j_mayer
1157 8bb6e981 aurel32
/* PALcode support special instructions */
1158 4c9649a9 j_mayer
#if !defined (CONFIG_USER_ONLY)
1159 8bb6e981 aurel32
void helper_hw_rei (void)
1160 8bb6e981 aurel32
{
1161 8bb6e981 aurel32
    env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
1162 8bb6e981 aurel32
    env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
1163 ac316ca4 Richard Henderson
    env->intr_flag = 0;
1164 6910b8f6 Richard Henderson
    env->lock_addr = -1;
1165 8bb6e981 aurel32
    /* XXX: re-enable interrupts and memory mapping */
1166 8bb6e981 aurel32
}
1167 8bb6e981 aurel32
1168 8bb6e981 aurel32
void helper_hw_ret (uint64_t a)
1169 8bb6e981 aurel32
{
1170 8bb6e981 aurel32
    env->pc = a & ~3;
1171 8bb6e981 aurel32
    env->ipr[IPR_EXC_ADDR] = a & 1;
1172 ac316ca4 Richard Henderson
    env->intr_flag = 0;
1173 6910b8f6 Richard Henderson
    env->lock_addr = -1;
1174 8bb6e981 aurel32
    /* XXX: re-enable interrupts and memory mapping */
1175 8bb6e981 aurel32
}
1176 8bb6e981 aurel32
1177 8bb6e981 aurel32
uint64_t helper_mfpr (int iprn, uint64_t val)
1178 8bb6e981 aurel32
{
1179 8bb6e981 aurel32
    uint64_t tmp;
1180 8bb6e981 aurel32
1181 8bb6e981 aurel32
    if (cpu_alpha_mfpr(env, iprn, &tmp) == 0)
1182 8bb6e981 aurel32
        val = tmp;
1183 8bb6e981 aurel32
1184 8bb6e981 aurel32
    return val;
1185 8bb6e981 aurel32
}
1186 8bb6e981 aurel32
1187 8bb6e981 aurel32
void helper_mtpr (int iprn, uint64_t val)
1188 4c9649a9 j_mayer
{
1189 8bb6e981 aurel32
    cpu_alpha_mtpr(env, iprn, val, NULL);
1190 8bb6e981 aurel32
}
1191 4c9649a9 j_mayer
1192 8bb6e981 aurel32
void helper_set_alt_mode (void)
1193 8bb6e981 aurel32
{
1194 8bb6e981 aurel32
    env->saved_mode = env->ps & 0xC;
1195 8bb6e981 aurel32
    env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
1196 4c9649a9 j_mayer
}
1197 4c9649a9 j_mayer
1198 8bb6e981 aurel32
void helper_restore_mode (void)
1199 4c9649a9 j_mayer
{
1200 8bb6e981 aurel32
    env->ps = (env->ps & ~0xC) | env->saved_mode;
1201 4c9649a9 j_mayer
}
1202 8bb6e981 aurel32
1203 4c9649a9 j_mayer
#endif
1204 4c9649a9 j_mayer
1205 4c9649a9 j_mayer
/*****************************************************************************/
1206 4c9649a9 j_mayer
/* Softmmu support */
1207 4c9649a9 j_mayer
#if !defined (CONFIG_USER_ONLY)
1208 4c9649a9 j_mayer
1209 4c9649a9 j_mayer
/* XXX: the two following helpers are pure hacks.
1210 4c9649a9 j_mayer
 *      Hopefully, we emulate the PALcode, then we should never see
1211 4c9649a9 j_mayer
 *      HW_LD / HW_ST instructions.
1212 4c9649a9 j_mayer
 */
1213 8bb6e981 aurel32
uint64_t helper_ld_virt_to_phys (uint64_t virtaddr)
1214 4c9649a9 j_mayer
{
1215 4c9649a9 j_mayer
    uint64_t tlb_addr, physaddr;
1216 6ebbf390 j_mayer
    int index, mmu_idx;
1217 4c9649a9 j_mayer
    void *retaddr;
1218 4c9649a9 j_mayer
1219 6ebbf390 j_mayer
    mmu_idx = cpu_mmu_index(env);
1220 8bb6e981 aurel32
    index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1221 4c9649a9 j_mayer
 redo:
1222 6ebbf390 j_mayer
    tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
1223 8bb6e981 aurel32
    if ((virtaddr & TARGET_PAGE_MASK) ==
1224 4c9649a9 j_mayer
        (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1225 8bb6e981 aurel32
        physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
1226 4c9649a9 j_mayer
    } else {
1227 4c9649a9 j_mayer
        /* the page is not in the TLB : fill it */
1228 4c9649a9 j_mayer
        retaddr = GETPC();
1229 8bb6e981 aurel32
        tlb_fill(virtaddr, 0, mmu_idx, retaddr);
1230 4c9649a9 j_mayer
        goto redo;
1231 4c9649a9 j_mayer
    }
1232 8bb6e981 aurel32
    return physaddr;
1233 4c9649a9 j_mayer
}
1234 4c9649a9 j_mayer
1235 8bb6e981 aurel32
uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
1236 4c9649a9 j_mayer
{
1237 4c9649a9 j_mayer
    uint64_t tlb_addr, physaddr;
1238 6ebbf390 j_mayer
    int index, mmu_idx;
1239 4c9649a9 j_mayer
    void *retaddr;
1240 4c9649a9 j_mayer
1241 6ebbf390 j_mayer
    mmu_idx = cpu_mmu_index(env);
1242 8bb6e981 aurel32
    index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1243 4c9649a9 j_mayer
 redo:
1244 6ebbf390 j_mayer
    tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
1245 8bb6e981 aurel32
    if ((virtaddr & TARGET_PAGE_MASK) ==
1246 4c9649a9 j_mayer
        (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1247 8bb6e981 aurel32
        physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
1248 4c9649a9 j_mayer
    } else {
1249 4c9649a9 j_mayer
        /* the page is not in the TLB : fill it */
1250 4c9649a9 j_mayer
        retaddr = GETPC();
1251 8bb6e981 aurel32
        tlb_fill(virtaddr, 1, mmu_idx, retaddr);
1252 4c9649a9 j_mayer
        goto redo;
1253 4c9649a9 j_mayer
    }
1254 8bb6e981 aurel32
    return physaddr;
1255 8bb6e981 aurel32
}
1256 8bb6e981 aurel32
1257 8bb6e981 aurel32
void helper_ldl_raw(uint64_t t0, uint64_t t1)
1258 8bb6e981 aurel32
{
1259 8bb6e981 aurel32
    ldl_raw(t1, t0);
1260 8bb6e981 aurel32
}
1261 8bb6e981 aurel32
1262 8bb6e981 aurel32
void helper_ldq_raw(uint64_t t0, uint64_t t1)
1263 8bb6e981 aurel32
{
1264 8bb6e981 aurel32
    ldq_raw(t1, t0);
1265 8bb6e981 aurel32
}
1266 8bb6e981 aurel32
1267 8bb6e981 aurel32
void helper_ldl_l_raw(uint64_t t0, uint64_t t1)
1268 8bb6e981 aurel32
{
1269 8bb6e981 aurel32
    env->lock = t1;
1270 8bb6e981 aurel32
    ldl_raw(t1, t0);
1271 8bb6e981 aurel32
}
1272 8bb6e981 aurel32
1273 8bb6e981 aurel32
void helper_ldq_l_raw(uint64_t t0, uint64_t t1)
1274 8bb6e981 aurel32
{
1275 8bb6e981 aurel32
    env->lock = t1;
1276 8bb6e981 aurel32
    ldl_raw(t1, t0);
1277 8bb6e981 aurel32
}
1278 8bb6e981 aurel32
1279 8bb6e981 aurel32
void helper_ldl_kernel(uint64_t t0, uint64_t t1)
1280 8bb6e981 aurel32
{
1281 8bb6e981 aurel32
    ldl_kernel(t1, t0);
1282 8bb6e981 aurel32
}
1283 8bb6e981 aurel32
1284 8bb6e981 aurel32
void helper_ldq_kernel(uint64_t t0, uint64_t t1)
1285 8bb6e981 aurel32
{
1286 8bb6e981 aurel32
    ldq_kernel(t1, t0);
1287 8bb6e981 aurel32
}
1288 8bb6e981 aurel32
1289 8bb6e981 aurel32
void helper_ldl_data(uint64_t t0, uint64_t t1)
1290 8bb6e981 aurel32
{
1291 8bb6e981 aurel32
    ldl_data(t1, t0);
1292 8bb6e981 aurel32
}
1293 8bb6e981 aurel32
1294 8bb6e981 aurel32
void helper_ldq_data(uint64_t t0, uint64_t t1)
1295 8bb6e981 aurel32
{
1296 8bb6e981 aurel32
    ldq_data(t1, t0);
1297 8bb6e981 aurel32
}
1298 8bb6e981 aurel32
1299 8bb6e981 aurel32
void helper_stl_raw(uint64_t t0, uint64_t t1)
1300 8bb6e981 aurel32
{
1301 8bb6e981 aurel32
    stl_raw(t1, t0);
1302 8bb6e981 aurel32
}
1303 8bb6e981 aurel32
1304 8bb6e981 aurel32
void helper_stq_raw(uint64_t t0, uint64_t t1)
1305 8bb6e981 aurel32
{
1306 8bb6e981 aurel32
    stq_raw(t1, t0);
1307 8bb6e981 aurel32
}
1308 8bb6e981 aurel32
1309 8bb6e981 aurel32
uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1)
1310 8bb6e981 aurel32
{
1311 8bb6e981 aurel32
    uint64_t ret;
1312 8bb6e981 aurel32
1313 8bb6e981 aurel32
    if (t1 == env->lock) {
1314 8bb6e981 aurel32
        stl_raw(t1, t0);
1315 8bb6e981 aurel32
        ret = 0;
1316 8bb6e981 aurel32
    } else
1317 8bb6e981 aurel32
        ret = 1;
1318 8bb6e981 aurel32
1319 8bb6e981 aurel32
    env->lock = 1;
1320 8bb6e981 aurel32
1321 8bb6e981 aurel32
    return ret;
1322 8bb6e981 aurel32
}
1323 8bb6e981 aurel32
1324 8bb6e981 aurel32
uint64_t helper_stq_c_raw(uint64_t t0, uint64_t t1)
1325 8bb6e981 aurel32
{
1326 8bb6e981 aurel32
    uint64_t ret;
1327 8bb6e981 aurel32
1328 8bb6e981 aurel32
    if (t1 == env->lock) {
1329 8bb6e981 aurel32
        stq_raw(t1, t0);
1330 8bb6e981 aurel32
        ret = 0;
1331 8bb6e981 aurel32
    } else
1332 8bb6e981 aurel32
        ret = 1;
1333 8bb6e981 aurel32
1334 8bb6e981 aurel32
    env->lock = 1;
1335 8bb6e981 aurel32
1336 8bb6e981 aurel32
    return ret;
1337 4c9649a9 j_mayer
}
1338 4c9649a9 j_mayer
1339 4c9649a9 j_mayer
#define MMUSUFFIX _mmu
1340 4c9649a9 j_mayer
1341 4c9649a9 j_mayer
#define SHIFT 0
1342 4c9649a9 j_mayer
#include "softmmu_template.h"
1343 4c9649a9 j_mayer
1344 4c9649a9 j_mayer
#define SHIFT 1
1345 4c9649a9 j_mayer
#include "softmmu_template.h"
1346 4c9649a9 j_mayer
1347 4c9649a9 j_mayer
#define SHIFT 2
1348 4c9649a9 j_mayer
#include "softmmu_template.h"
1349 4c9649a9 j_mayer
1350 4c9649a9 j_mayer
#define SHIFT 3
1351 4c9649a9 j_mayer
#include "softmmu_template.h"
1352 4c9649a9 j_mayer
1353 4c9649a9 j_mayer
/* try to fill the TLB and return an exception if error. If retaddr is
1354 4c9649a9 j_mayer
   NULL, it means that the function was called in C code (i.e. not
1355 4c9649a9 j_mayer
   from generated code or from helper.c) */
1356 4c9649a9 j_mayer
/* XXX: fix it to restore all registers */
1357 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1358 4c9649a9 j_mayer
{
1359 4c9649a9 j_mayer
    TranslationBlock *tb;
1360 4c9649a9 j_mayer
    CPUState *saved_env;
1361 44f8625d bellard
    unsigned long pc;
1362 4c9649a9 j_mayer
    int ret;
1363 4c9649a9 j_mayer
1364 4c9649a9 j_mayer
    /* XXX: hack to restore env in all cases, even if not called from
1365 4c9649a9 j_mayer
       generated code */
1366 4c9649a9 j_mayer
    saved_env = env;
1367 4c9649a9 j_mayer
    env = cpu_single_env;
1368 6ebbf390 j_mayer
    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1369 4c9649a9 j_mayer
    if (!likely(ret == 0)) {
1370 4c9649a9 j_mayer
        if (likely(retaddr)) {
1371 4c9649a9 j_mayer
            /* now we have a real cpu fault */
1372 44f8625d bellard
            pc = (unsigned long)retaddr;
1373 4c9649a9 j_mayer
            tb = tb_find_pc(pc);
1374 4c9649a9 j_mayer
            if (likely(tb)) {
1375 4c9649a9 j_mayer
                /* the PC is inside the translated code. It means that we have
1376 4c9649a9 j_mayer
                   a virtual CPU fault */
1377 618ba8e6 Stefan Weil
                cpu_restore_state(tb, env, pc);
1378 4c9649a9 j_mayer
            }
1379 4c9649a9 j_mayer
        }
1380 4c9649a9 j_mayer
        /* Exception index and error code are already set */
1381 4c9649a9 j_mayer
        cpu_loop_exit();
1382 4c9649a9 j_mayer
    }
1383 4c9649a9 j_mayer
    env = saved_env;
1384 4c9649a9 j_mayer
}
1385 4c9649a9 j_mayer
1386 4c9649a9 j_mayer
#endif