Statistics
| Branch: | Revision:

root / target-alpha / op_helper.c @ 18569871

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 18569871 Peter Maydell
    if (float64_is_quiet_nan(fa) || float64_is_quiet_nan(fb))
908 f18cd223 aurel32
        return 0x4000000000000000ULL;
909 f18cd223 aurel32
    else
910 f18cd223 aurel32
        return 0;
911 4c9649a9 j_mayer
}
912 4c9649a9 j_mayer
913 f18cd223 aurel32
uint64_t helper_cmpteq(uint64_t a, uint64_t b)
914 4c9649a9 j_mayer
{
915 f18cd223 aurel32
    float64 fa, fb;
916 4c9649a9 j_mayer
917 f18cd223 aurel32
    fa = t_to_float64(a);
918 f18cd223 aurel32
    fb = t_to_float64(b);
919 f18cd223 aurel32
920 f18cd223 aurel32
    if (float64_eq(fa, fb, &FP_STATUS))
921 f18cd223 aurel32
        return 0x4000000000000000ULL;
922 f18cd223 aurel32
    else
923 f18cd223 aurel32
        return 0;
924 4c9649a9 j_mayer
}
925 4c9649a9 j_mayer
926 f18cd223 aurel32
uint64_t helper_cmptle(uint64_t a, uint64_t b)
927 4c9649a9 j_mayer
{
928 f18cd223 aurel32
    float64 fa, fb;
929 4c9649a9 j_mayer
930 f18cd223 aurel32
    fa = t_to_float64(a);
931 f18cd223 aurel32
    fb = t_to_float64(b);
932 f18cd223 aurel32
933 f18cd223 aurel32
    if (float64_le(fa, fb, &FP_STATUS))
934 f18cd223 aurel32
        return 0x4000000000000000ULL;
935 f18cd223 aurel32
    else
936 f18cd223 aurel32
        return 0;
937 4c9649a9 j_mayer
}
938 4c9649a9 j_mayer
939 f18cd223 aurel32
uint64_t helper_cmptlt(uint64_t a, uint64_t b)
940 4c9649a9 j_mayer
{
941 f18cd223 aurel32
    float64 fa, fb;
942 4c9649a9 j_mayer
943 f18cd223 aurel32
    fa = t_to_float64(a);
944 f18cd223 aurel32
    fb = t_to_float64(b);
945 f18cd223 aurel32
946 f18cd223 aurel32
    if (float64_lt(fa, fb, &FP_STATUS))
947 f18cd223 aurel32
        return 0x4000000000000000ULL;
948 f18cd223 aurel32
    else
949 f18cd223 aurel32
        return 0;
950 4c9649a9 j_mayer
}
951 4c9649a9 j_mayer
952 f18cd223 aurel32
uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
953 4c9649a9 j_mayer
{
954 f18cd223 aurel32
    float64 fa, fb;
955 4c9649a9 j_mayer
956 f18cd223 aurel32
    fa = g_to_float64(a);
957 f18cd223 aurel32
    fb = g_to_float64(b);
958 f18cd223 aurel32
959 f18cd223 aurel32
    if (float64_eq(fa, fb, &FP_STATUS))
960 f18cd223 aurel32
        return 0x4000000000000000ULL;
961 f18cd223 aurel32
    else
962 f18cd223 aurel32
        return 0;
963 4c9649a9 j_mayer
}
964 4c9649a9 j_mayer
965 f18cd223 aurel32
uint64_t helper_cmpgle(uint64_t a, uint64_t b)
966 4c9649a9 j_mayer
{
967 f18cd223 aurel32
    float64 fa, fb;
968 f18cd223 aurel32
969 f18cd223 aurel32
    fa = g_to_float64(a);
970 f18cd223 aurel32
    fb = g_to_float64(b);
971 4c9649a9 j_mayer
972 f18cd223 aurel32
    if (float64_le(fa, fb, &FP_STATUS))
973 f18cd223 aurel32
        return 0x4000000000000000ULL;
974 f18cd223 aurel32
    else
975 f18cd223 aurel32
        return 0;
976 4c9649a9 j_mayer
}
977 4c9649a9 j_mayer
978 f18cd223 aurel32
uint64_t helper_cmpglt(uint64_t a, uint64_t b)
979 4c9649a9 j_mayer
{
980 f18cd223 aurel32
    float64 fa, fb;
981 f18cd223 aurel32
982 f18cd223 aurel32
    fa = g_to_float64(a);
983 f18cd223 aurel32
    fb = g_to_float64(b);
984 4c9649a9 j_mayer
985 f18cd223 aurel32
    if (float64_lt(fa, fb, &FP_STATUS))
986 f18cd223 aurel32
        return 0x4000000000000000ULL;
987 f18cd223 aurel32
    else
988 f18cd223 aurel32
        return 0;
989 4c9649a9 j_mayer
}
990 4c9649a9 j_mayer
991 f18cd223 aurel32
/* Floating point format conversion */
992 f18cd223 aurel32
uint64_t helper_cvtts (uint64_t a)
993 4c9649a9 j_mayer
{
994 f18cd223 aurel32
    float64 fa;
995 f18cd223 aurel32
    float32 fr;
996 4c9649a9 j_mayer
997 f18cd223 aurel32
    fa = t_to_float64(a);
998 f18cd223 aurel32
    fr = float64_to_float32(fa, &FP_STATUS);
999 f18cd223 aurel32
    return float32_to_s(fr);
1000 4c9649a9 j_mayer
}
1001 4c9649a9 j_mayer
1002 f18cd223 aurel32
uint64_t helper_cvtst (uint64_t a)
1003 4c9649a9 j_mayer
{
1004 f18cd223 aurel32
    float32 fa;
1005 f18cd223 aurel32
    float64 fr;
1006 f18cd223 aurel32
1007 f18cd223 aurel32
    fa = s_to_float32(a);
1008 f18cd223 aurel32
    fr = float32_to_float64(fa, &FP_STATUS);
1009 f18cd223 aurel32
    return float64_to_t(fr);
1010 4c9649a9 j_mayer
}
1011 4c9649a9 j_mayer
1012 f18cd223 aurel32
uint64_t helper_cvtqs (uint64_t a)
1013 4c9649a9 j_mayer
{
1014 f18cd223 aurel32
    float32 fr = int64_to_float32(a, &FP_STATUS);
1015 f18cd223 aurel32
    return float32_to_s(fr);
1016 4c9649a9 j_mayer
}
1017 4c9649a9 j_mayer
1018 f24518b5 Richard Henderson
/* Implement float64 to uint64 conversion without saturation -- we must
1019 f24518b5 Richard Henderson
   supply the truncated result.  This behaviour is used by the compiler
1020 f24518b5 Richard Henderson
   to get unsigned conversion for free with the same instruction.
1021 f24518b5 Richard Henderson

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