Statistics
| Branch: | Revision:

root / target-alpha / op_helper.c @ 3a6fa678

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

1053 f24518b5 Richard Henderson
   The VI flag is set when overflow or inexact exceptions should be raised.  */
1054 f24518b5 Richard Henderson
1055 f24518b5 Richard Henderson
static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI)
1056 4c9649a9 j_mayer
{
1057 f24518b5 Richard Henderson
    uint64_t frac, ret = 0;
1058 f24518b5 Richard Henderson
    uint32_t exp, sign, exc = 0;
1059 f24518b5 Richard Henderson
    int shift;
1060 f24518b5 Richard Henderson
1061 f24518b5 Richard Henderson
    sign = (a >> 63);
1062 f24518b5 Richard Henderson
    exp = (uint32_t)(a >> 52) & 0x7ff;
1063 f24518b5 Richard Henderson
    frac = a & 0xfffffffffffffull;
1064 f24518b5 Richard Henderson
1065 f24518b5 Richard Henderson
    if (exp == 0) {
1066 f24518b5 Richard Henderson
        if (unlikely(frac != 0)) {
1067 f24518b5 Richard Henderson
            goto do_underflow;
1068 f24518b5 Richard Henderson
        }
1069 f24518b5 Richard Henderson
    } else if (exp == 0x7ff) {
1070 f24518b5 Richard Henderson
        exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
1071 f24518b5 Richard Henderson
    } else {
1072 f24518b5 Richard Henderson
        /* Restore implicit bit.  */
1073 f24518b5 Richard Henderson
        frac |= 0x10000000000000ull;
1074 f24518b5 Richard Henderson
1075 f24518b5 Richard Henderson
        shift = exp - 1023 - 52;
1076 f24518b5 Richard Henderson
        if (shift >= 0) {
1077 f24518b5 Richard Henderson
            /* In this case the number is so large that we must shift
1078 f24518b5 Richard Henderson
               the fraction left.  There is no rounding to do.  */
1079 f24518b5 Richard Henderson
            if (shift < 63) {
1080 f24518b5 Richard Henderson
                ret = frac << shift;
1081 f24518b5 Richard Henderson
                if (VI && (ret >> shift) != frac) {
1082 f24518b5 Richard Henderson
                    exc = float_flag_overflow;
1083 f24518b5 Richard Henderson
                }
1084 f24518b5 Richard Henderson
            }
1085 f24518b5 Richard Henderson
        } else {
1086 f24518b5 Richard Henderson
            uint64_t round;
1087 f24518b5 Richard Henderson
1088 f24518b5 Richard Henderson
            /* In this case the number is smaller than the fraction as
1089 f24518b5 Richard Henderson
               represented by the 52 bit number.  Here we must think
1090 f24518b5 Richard Henderson
               about rounding the result.  Handle this by shifting the
1091 f24518b5 Richard Henderson
               fractional part of the number into the high bits of ROUND.
1092 f24518b5 Richard Henderson
               This will let us efficiently handle round-to-nearest.  */
1093 f24518b5 Richard Henderson
            shift = -shift;
1094 f24518b5 Richard Henderson
            if (shift < 63) {
1095 f24518b5 Richard Henderson
                ret = frac >> shift;
1096 f24518b5 Richard Henderson
                round = frac << (64 - shift);
1097 f24518b5 Richard Henderson
            } else {
1098 f24518b5 Richard Henderson
                /* The exponent is so small we shift out everything.
1099 f24518b5 Richard Henderson
                   Leave a sticky bit for proper rounding below.  */
1100 f24518b5 Richard Henderson
            do_underflow:
1101 f24518b5 Richard Henderson
                round = 1;
1102 f24518b5 Richard Henderson
            }
1103 f24518b5 Richard Henderson
1104 f24518b5 Richard Henderson
            if (round) {
1105 f24518b5 Richard Henderson
                exc = (VI ? float_flag_inexact : 0);
1106 f24518b5 Richard Henderson
                switch (roundmode) {
1107 f24518b5 Richard Henderson
                case float_round_nearest_even:
1108 f24518b5 Richard Henderson
                    if (round == (1ull << 63)) {
1109 f24518b5 Richard Henderson
                        /* Fraction is exactly 0.5; round to even.  */
1110 f24518b5 Richard Henderson
                        ret += (ret & 1);
1111 f24518b5 Richard Henderson
                    } else if (round > (1ull << 63)) {
1112 f24518b5 Richard Henderson
                        ret += 1;
1113 f24518b5 Richard Henderson
                    }
1114 f24518b5 Richard Henderson
                    break;
1115 f24518b5 Richard Henderson
                case float_round_to_zero:
1116 f24518b5 Richard Henderson
                    break;
1117 f24518b5 Richard Henderson
                case float_round_up:
1118 f24518b5 Richard Henderson
                    ret += 1 - sign;
1119 f24518b5 Richard Henderson
                    break;
1120 f24518b5 Richard Henderson
                case float_round_down:
1121 f24518b5 Richard Henderson
                    ret += sign;
1122 f24518b5 Richard Henderson
                    break;
1123 f24518b5 Richard Henderson
                }
1124 f24518b5 Richard Henderson
            }
1125 f24518b5 Richard Henderson
        }
1126 f24518b5 Richard Henderson
        if (sign) {
1127 f24518b5 Richard Henderson
            ret = -ret;
1128 f24518b5 Richard Henderson
        }
1129 f24518b5 Richard Henderson
    }
1130 f24518b5 Richard Henderson
    if (unlikely(exc)) {
1131 f24518b5 Richard Henderson
        float_raise(exc, &FP_STATUS);
1132 f24518b5 Richard Henderson
    }
1133 f24518b5 Richard Henderson
1134 f24518b5 Richard Henderson
    return ret;
1135 f24518b5 Richard Henderson
}
1136 f24518b5 Richard Henderson
1137 f24518b5 Richard Henderson
uint64_t helper_cvttq(uint64_t a)
1138 f24518b5 Richard Henderson
{
1139 f24518b5 Richard Henderson
    return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1);
1140 f24518b5 Richard Henderson
}
1141 f24518b5 Richard Henderson
1142 f24518b5 Richard Henderson
uint64_t helper_cvttq_c(uint64_t a)
1143 f24518b5 Richard Henderson
{
1144 f24518b5 Richard Henderson
    return helper_cvttq_internal(a, float_round_to_zero, 0);
1145 f24518b5 Richard Henderson
}
1146 f24518b5 Richard Henderson
1147 f24518b5 Richard Henderson
uint64_t helper_cvttq_svic(uint64_t a)
1148 f24518b5 Richard Henderson
{
1149 f24518b5 Richard Henderson
    return helper_cvttq_internal(a, float_round_to_zero, 1);
1150 f18cd223 aurel32
}
1151 4c9649a9 j_mayer
1152 f18cd223 aurel32
uint64_t helper_cvtqt (uint64_t a)
1153 f18cd223 aurel32
{
1154 f18cd223 aurel32
    float64 fr = int64_to_float64(a, &FP_STATUS);
1155 f18cd223 aurel32
    return float64_to_t(fr);
1156 4c9649a9 j_mayer
}
1157 4c9649a9 j_mayer
1158 f18cd223 aurel32
uint64_t helper_cvtqf (uint64_t a)
1159 4c9649a9 j_mayer
{
1160 f18cd223 aurel32
    float32 fr = int64_to_float32(a, &FP_STATUS);
1161 f18cd223 aurel32
    return float32_to_f(fr);
1162 4c9649a9 j_mayer
}
1163 4c9649a9 j_mayer
1164 f18cd223 aurel32
uint64_t helper_cvtgf (uint64_t a)
1165 4c9649a9 j_mayer
{
1166 f18cd223 aurel32
    float64 fa;
1167 f18cd223 aurel32
    float32 fr;
1168 f18cd223 aurel32
1169 f18cd223 aurel32
    fa = g_to_float64(a);
1170 f18cd223 aurel32
    fr = float64_to_float32(fa, &FP_STATUS);
1171 f18cd223 aurel32
    return float32_to_f(fr);
1172 4c9649a9 j_mayer
}
1173 4c9649a9 j_mayer
1174 f18cd223 aurel32
uint64_t helper_cvtgq (uint64_t a)
1175 4c9649a9 j_mayer
{
1176 f18cd223 aurel32
    float64 fa = g_to_float64(a);
1177 f18cd223 aurel32
    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
1178 4c9649a9 j_mayer
}
1179 4c9649a9 j_mayer
1180 f18cd223 aurel32
uint64_t helper_cvtqg (uint64_t a)
1181 4c9649a9 j_mayer
{
1182 f18cd223 aurel32
    float64 fr;
1183 f18cd223 aurel32
    fr = int64_to_float64(a, &FP_STATUS);
1184 f18cd223 aurel32
    return float64_to_g(fr);
1185 4c9649a9 j_mayer
}
1186 4c9649a9 j_mayer
1187 8bb6e981 aurel32
/* PALcode support special instructions */
1188 4c9649a9 j_mayer
#if !defined (CONFIG_USER_ONLY)
1189 8bb6e981 aurel32
void helper_hw_ret (uint64_t a)
1190 8bb6e981 aurel32
{
1191 8bb6e981 aurel32
    env->pc = a & ~3;
1192 129d8aa5 Richard Henderson
    env->pal_mode = a & 1;
1193 ac316ca4 Richard Henderson
    env->intr_flag = 0;
1194 6910b8f6 Richard Henderson
    env->lock_addr = -1;
1195 8bb6e981 aurel32
}
1196 4c9649a9 j_mayer
#endif
1197 4c9649a9 j_mayer
1198 4c9649a9 j_mayer
/*****************************************************************************/
1199 4c9649a9 j_mayer
/* Softmmu support */
1200 4c9649a9 j_mayer
#if !defined (CONFIG_USER_ONLY)
1201 2374e73e Richard Henderson
uint64_t helper_ldl_phys(uint64_t p)
1202 8bb6e981 aurel32
{
1203 2374e73e Richard Henderson
    return (int32_t)ldl_phys(p);
1204 8bb6e981 aurel32
}
1205 8bb6e981 aurel32
1206 2374e73e Richard Henderson
uint64_t helper_ldq_phys(uint64_t p)
1207 8bb6e981 aurel32
{
1208 2374e73e Richard Henderson
    return ldq_phys(p);
1209 8bb6e981 aurel32
}
1210 8bb6e981 aurel32
1211 2374e73e Richard Henderson
uint64_t helper_ldl_l_phys(uint64_t p)
1212 8bb6e981 aurel32
{
1213 2374e73e Richard Henderson
    env->lock_addr = p;
1214 2374e73e Richard Henderson
    return env->lock_value = (int32_t)ldl_phys(p);
1215 8bb6e981 aurel32
}
1216 8bb6e981 aurel32
1217 2374e73e Richard Henderson
uint64_t helper_ldq_l_phys(uint64_t p)
1218 8bb6e981 aurel32
{
1219 2374e73e Richard Henderson
    env->lock_addr = p;
1220 2374e73e Richard Henderson
    return env->lock_value = ldl_phys(p);
1221 8bb6e981 aurel32
}
1222 8bb6e981 aurel32
1223 2374e73e Richard Henderson
void helper_stl_phys(uint64_t p, uint64_t v)
1224 8bb6e981 aurel32
{
1225 2374e73e Richard Henderson
    stl_phys(p, v);
1226 8bb6e981 aurel32
}
1227 8bb6e981 aurel32
1228 2374e73e Richard Henderson
void helper_stq_phys(uint64_t p, uint64_t v)
1229 8bb6e981 aurel32
{
1230 2374e73e Richard Henderson
    stq_phys(p, v);
1231 8bb6e981 aurel32
}
1232 8bb6e981 aurel32
1233 2374e73e Richard Henderson
uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
1234 8bb6e981 aurel32
{
1235 2374e73e Richard Henderson
    uint64_t ret = 0;
1236 8bb6e981 aurel32
1237 2374e73e Richard Henderson
    if (p == env->lock_addr) {
1238 2374e73e Richard Henderson
        int32_t old = ldl_phys(p);
1239 2374e73e Richard Henderson
        if (old == (int32_t)env->lock_value) {
1240 2374e73e Richard Henderson
            stl_phys(p, v);
1241 2374e73e Richard Henderson
            ret = 1;
1242 2374e73e Richard Henderson
        }
1243 2374e73e Richard Henderson
    }
1244 2374e73e Richard Henderson
    env->lock_addr = -1;
1245 8bb6e981 aurel32
1246 8bb6e981 aurel32
    return ret;
1247 8bb6e981 aurel32
}
1248 8bb6e981 aurel32
1249 2374e73e Richard Henderson
uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
1250 8bb6e981 aurel32
{
1251 2374e73e Richard Henderson
    uint64_t ret = 0;
1252 8bb6e981 aurel32
1253 2374e73e Richard Henderson
    if (p == env->lock_addr) {
1254 2374e73e Richard Henderson
        uint64_t old = ldq_phys(p);
1255 2374e73e Richard Henderson
        if (old == env->lock_value) {
1256 2374e73e Richard Henderson
            stq_phys(p, v);
1257 2374e73e Richard Henderson
            ret = 1;
1258 2374e73e Richard Henderson
        }
1259 2374e73e Richard Henderson
    }
1260 2374e73e Richard Henderson
    env->lock_addr = -1;
1261 8bb6e981 aurel32
1262 8bb6e981 aurel32
    return ret;
1263 4c9649a9 j_mayer
}
1264 4c9649a9 j_mayer
1265 4c9649a9 j_mayer
#define MMUSUFFIX _mmu
1266 4c9649a9 j_mayer
1267 4c9649a9 j_mayer
#define SHIFT 0
1268 4c9649a9 j_mayer
#include "softmmu_template.h"
1269 4c9649a9 j_mayer
1270 4c9649a9 j_mayer
#define SHIFT 1
1271 4c9649a9 j_mayer
#include "softmmu_template.h"
1272 4c9649a9 j_mayer
1273 4c9649a9 j_mayer
#define SHIFT 2
1274 4c9649a9 j_mayer
#include "softmmu_template.h"
1275 4c9649a9 j_mayer
1276 4c9649a9 j_mayer
#define SHIFT 3
1277 4c9649a9 j_mayer
#include "softmmu_template.h"
1278 4c9649a9 j_mayer
1279 4c9649a9 j_mayer
/* try to fill the TLB and return an exception if error. If retaddr is
1280 4c9649a9 j_mayer
   NULL, it means that the function was called in C code (i.e. not
1281 4c9649a9 j_mayer
   from generated code or from helper.c) */
1282 4c9649a9 j_mayer
/* XXX: fix it to restore all registers */
1283 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1284 4c9649a9 j_mayer
{
1285 4c9649a9 j_mayer
    CPUState *saved_env;
1286 4c9649a9 j_mayer
    int ret;
1287 4c9649a9 j_mayer
1288 4c9649a9 j_mayer
    /* XXX: hack to restore env in all cases, even if not called from
1289 4c9649a9 j_mayer
       generated code */
1290 4c9649a9 j_mayer
    saved_env = env;
1291 4c9649a9 j_mayer
    env = cpu_single_env;
1292 6ebbf390 j_mayer
    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1293 2d9671d3 Richard Henderson
    if (unlikely(ret != 0)) {
1294 2d9671d3 Richard Henderson
        do_restore_state(retaddr);
1295 4c9649a9 j_mayer
        /* Exception index and error code are already set */
1296 4c9649a9 j_mayer
        cpu_loop_exit();
1297 4c9649a9 j_mayer
    }
1298 4c9649a9 j_mayer
    env = saved_env;
1299 4c9649a9 j_mayer
}
1300 4c9649a9 j_mayer
1301 4c9649a9 j_mayer
#endif