Statistics
| Branch: | Revision:

root / target-alpha / op_helper.c @ 060718c1

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

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