Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 94909d9f

History | View | Annotate | Download (123.8 kB)

1 9a64fbe4 bellard
/*
2 3fc6c082 bellard
 *  PowerPC emulation helpers for qemu.
3 5fafdf24 ths
 *
4 76a66253 j_mayer
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5 9a64fbe4 bellard
 *
6 9a64fbe4 bellard
 * This library is free software; you can redistribute it and/or
7 9a64fbe4 bellard
 * modify it under the terms of the GNU Lesser General Public
8 9a64fbe4 bellard
 * License as published by the Free Software Foundation; either
9 9a64fbe4 bellard
 * version 2 of the License, or (at your option) any later version.
10 9a64fbe4 bellard
 *
11 9a64fbe4 bellard
 * This library is distributed in the hope that it will be useful,
12 9a64fbe4 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 9a64fbe4 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 9a64fbe4 bellard
 * Lesser General Public License for more details.
15 9a64fbe4 bellard
 *
16 9a64fbe4 bellard
 * You should have received a copy of the GNU Lesser General Public
17 9a64fbe4 bellard
 * License along with this library; if not, write to the Free Software
18 fad6cb1a aurel32
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19 9a64fbe4 bellard
 */
20 7b239bec aurel32
#include <string.h>
21 9a64fbe4 bellard
#include "exec.h"
22 603fccce j_mayer
#include "host-utils.h"
23 a7812ae4 pbrook
#include "helper.h"
24 9a64fbe4 bellard
25 0411a972 j_mayer
#include "helper_regs.h"
26 0487d6a8 j_mayer
27 fdabc366 bellard
//#define DEBUG_OP
28 fdabc366 bellard
//#define DEBUG_EXCEPTIONS
29 76a66253 j_mayer
//#define DEBUG_SOFTWARE_TLB
30 fdabc366 bellard
31 d12d51d5 aliguori
#ifdef DEBUG_SOFTWARE_TLB
32 93fcfe39 aliguori
#  define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
33 d12d51d5 aliguori
#else
34 d12d51d5 aliguori
#  define LOG_SWTLB(...) do { } while (0)
35 d12d51d5 aliguori
#endif
36 d12d51d5 aliguori
37 d12d51d5 aliguori
38 9a64fbe4 bellard
/*****************************************************************************/
39 9a64fbe4 bellard
/* Exceptions processing helpers */
40 9a64fbe4 bellard
41 64adab3f aurel32
void helper_raise_exception_err (uint32_t exception, uint32_t error_code)
42 9a64fbe4 bellard
{
43 e06fcd75 aurel32
#if 0
44 e06fcd75 aurel32
    printf("Raise exception %3x code : %d\n", exception, error_code);
45 e06fcd75 aurel32
#endif
46 e06fcd75 aurel32
    env->exception_index = exception;
47 e06fcd75 aurel32
    env->error_code = error_code;
48 e06fcd75 aurel32
    cpu_loop_exit();
49 76a66253 j_mayer
}
50 9fddaa0c bellard
51 e06fcd75 aurel32
void helper_raise_exception (uint32_t exception)
52 9fddaa0c bellard
{
53 e06fcd75 aurel32
    helper_raise_exception_err(exception, 0);
54 9a64fbe4 bellard
}
55 9a64fbe4 bellard
56 9a64fbe4 bellard
/*****************************************************************************/
57 45d827d2 aurel32
/* SPR accesses */
58 45d827d2 aurel32
void helper_load_dump_spr (uint32_t sprn)
59 a496775f j_mayer
{
60 93fcfe39 aliguori
    qemu_log("Read SPR %d %03x => " ADDRX "\n",
61 a496775f j_mayer
                sprn, sprn, env->spr[sprn]);
62 a496775f j_mayer
}
63 a496775f j_mayer
64 45d827d2 aurel32
void helper_store_dump_spr (uint32_t sprn)
65 a496775f j_mayer
{
66 93fcfe39 aliguori
    qemu_log("Write SPR %d %03x <= " ADDRX "\n",
67 45d827d2 aurel32
                sprn, sprn, env->spr[sprn]);
68 45d827d2 aurel32
}
69 45d827d2 aurel32
70 45d827d2 aurel32
target_ulong helper_load_tbl (void)
71 45d827d2 aurel32
{
72 45d827d2 aurel32
    return cpu_ppc_load_tbl(env);
73 45d827d2 aurel32
}
74 45d827d2 aurel32
75 45d827d2 aurel32
target_ulong helper_load_tbu (void)
76 45d827d2 aurel32
{
77 45d827d2 aurel32
    return cpu_ppc_load_tbu(env);
78 45d827d2 aurel32
}
79 45d827d2 aurel32
80 45d827d2 aurel32
target_ulong helper_load_atbl (void)
81 45d827d2 aurel32
{
82 45d827d2 aurel32
    return cpu_ppc_load_atbl(env);
83 45d827d2 aurel32
}
84 45d827d2 aurel32
85 45d827d2 aurel32
target_ulong helper_load_atbu (void)
86 45d827d2 aurel32
{
87 45d827d2 aurel32
    return cpu_ppc_load_atbu(env);
88 45d827d2 aurel32
}
89 45d827d2 aurel32
90 45d827d2 aurel32
target_ulong helper_load_601_rtcl (void)
91 45d827d2 aurel32
{
92 45d827d2 aurel32
    return cpu_ppc601_load_rtcl(env);
93 45d827d2 aurel32
}
94 45d827d2 aurel32
95 45d827d2 aurel32
target_ulong helper_load_601_rtcu (void)
96 45d827d2 aurel32
{
97 45d827d2 aurel32
    return cpu_ppc601_load_rtcu(env);
98 45d827d2 aurel32
}
99 45d827d2 aurel32
100 45d827d2 aurel32
#if !defined(CONFIG_USER_ONLY)
101 45d827d2 aurel32
#if defined (TARGET_PPC64)
102 45d827d2 aurel32
void helper_store_asr (target_ulong val)
103 45d827d2 aurel32
{
104 45d827d2 aurel32
    ppc_store_asr(env, val);
105 45d827d2 aurel32
}
106 45d827d2 aurel32
#endif
107 45d827d2 aurel32
108 45d827d2 aurel32
void helper_store_sdr1 (target_ulong val)
109 45d827d2 aurel32
{
110 45d827d2 aurel32
    ppc_store_sdr1(env, val);
111 45d827d2 aurel32
}
112 45d827d2 aurel32
113 45d827d2 aurel32
void helper_store_tbl (target_ulong val)
114 45d827d2 aurel32
{
115 45d827d2 aurel32
    cpu_ppc_store_tbl(env, val);
116 45d827d2 aurel32
}
117 45d827d2 aurel32
118 45d827d2 aurel32
void helper_store_tbu (target_ulong val)
119 45d827d2 aurel32
{
120 45d827d2 aurel32
    cpu_ppc_store_tbu(env, val);
121 45d827d2 aurel32
}
122 45d827d2 aurel32
123 45d827d2 aurel32
void helper_store_atbl (target_ulong val)
124 45d827d2 aurel32
{
125 45d827d2 aurel32
    cpu_ppc_store_atbl(env, val);
126 45d827d2 aurel32
}
127 45d827d2 aurel32
128 45d827d2 aurel32
void helper_store_atbu (target_ulong val)
129 45d827d2 aurel32
{
130 45d827d2 aurel32
    cpu_ppc_store_atbu(env, val);
131 45d827d2 aurel32
}
132 45d827d2 aurel32
133 45d827d2 aurel32
void helper_store_601_rtcl (target_ulong val)
134 45d827d2 aurel32
{
135 45d827d2 aurel32
    cpu_ppc601_store_rtcl(env, val);
136 45d827d2 aurel32
}
137 45d827d2 aurel32
138 45d827d2 aurel32
void helper_store_601_rtcu (target_ulong val)
139 45d827d2 aurel32
{
140 45d827d2 aurel32
    cpu_ppc601_store_rtcu(env, val);
141 45d827d2 aurel32
}
142 45d827d2 aurel32
143 45d827d2 aurel32
target_ulong helper_load_decr (void)
144 45d827d2 aurel32
{
145 45d827d2 aurel32
    return cpu_ppc_load_decr(env);
146 45d827d2 aurel32
}
147 45d827d2 aurel32
148 45d827d2 aurel32
void helper_store_decr (target_ulong val)
149 45d827d2 aurel32
{
150 45d827d2 aurel32
    cpu_ppc_store_decr(env, val);
151 45d827d2 aurel32
}
152 45d827d2 aurel32
153 45d827d2 aurel32
void helper_store_hid0_601 (target_ulong val)
154 45d827d2 aurel32
{
155 45d827d2 aurel32
    target_ulong hid0;
156 45d827d2 aurel32
157 45d827d2 aurel32
    hid0 = env->spr[SPR_HID0];
158 45d827d2 aurel32
    if ((val ^ hid0) & 0x00000008) {
159 45d827d2 aurel32
        /* Change current endianness */
160 45d827d2 aurel32
        env->hflags &= ~(1 << MSR_LE);
161 45d827d2 aurel32
        env->hflags_nmsr &= ~(1 << MSR_LE);
162 45d827d2 aurel32
        env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
163 45d827d2 aurel32
        env->hflags |= env->hflags_nmsr;
164 93fcfe39 aliguori
        qemu_log("%s: set endianness to %c => " ADDRX "\n",
165 45d827d2 aurel32
                    __func__, val & 0x8 ? 'l' : 'b', env->hflags);
166 a496775f j_mayer
    }
167 45d827d2 aurel32
    env->spr[SPR_HID0] = (uint32_t)val;
168 a496775f j_mayer
}
169 a496775f j_mayer
170 45d827d2 aurel32
void helper_store_403_pbr (uint32_t num, target_ulong value)
171 45d827d2 aurel32
{
172 45d827d2 aurel32
    if (likely(env->pb[num] != value)) {
173 45d827d2 aurel32
        env->pb[num] = value;
174 45d827d2 aurel32
        /* Should be optimized */
175 45d827d2 aurel32
        tlb_flush(env, 1);
176 45d827d2 aurel32
    }
177 45d827d2 aurel32
}
178 45d827d2 aurel32
179 45d827d2 aurel32
target_ulong helper_load_40x_pit (void)
180 45d827d2 aurel32
{
181 45d827d2 aurel32
    return load_40x_pit(env);
182 45d827d2 aurel32
}
183 45d827d2 aurel32
184 45d827d2 aurel32
void helper_store_40x_pit (target_ulong val)
185 45d827d2 aurel32
{
186 45d827d2 aurel32
    store_40x_pit(env, val);
187 45d827d2 aurel32
}
188 45d827d2 aurel32
189 45d827d2 aurel32
void helper_store_40x_dbcr0 (target_ulong val)
190 45d827d2 aurel32
{
191 45d827d2 aurel32
    store_40x_dbcr0(env, val);
192 45d827d2 aurel32
}
193 45d827d2 aurel32
194 45d827d2 aurel32
void helper_store_40x_sler (target_ulong val)
195 45d827d2 aurel32
{
196 45d827d2 aurel32
    store_40x_sler(env, val);
197 45d827d2 aurel32
}
198 45d827d2 aurel32
199 45d827d2 aurel32
void helper_store_booke_tcr (target_ulong val)
200 45d827d2 aurel32
{
201 45d827d2 aurel32
    store_booke_tcr(env, val);
202 45d827d2 aurel32
}
203 45d827d2 aurel32
204 45d827d2 aurel32
void helper_store_booke_tsr (target_ulong val)
205 45d827d2 aurel32
{
206 45d827d2 aurel32
    store_booke_tsr(env, val);
207 45d827d2 aurel32
}
208 45d827d2 aurel32
209 45d827d2 aurel32
void helper_store_ibatu (uint32_t nr, target_ulong val)
210 45d827d2 aurel32
{
211 45d827d2 aurel32
    ppc_store_ibatu(env, nr, val);
212 45d827d2 aurel32
}
213 45d827d2 aurel32
214 45d827d2 aurel32
void helper_store_ibatl (uint32_t nr, target_ulong val)
215 45d827d2 aurel32
{
216 45d827d2 aurel32
    ppc_store_ibatl(env, nr, val);
217 45d827d2 aurel32
}
218 45d827d2 aurel32
219 45d827d2 aurel32
void helper_store_dbatu (uint32_t nr, target_ulong val)
220 45d827d2 aurel32
{
221 45d827d2 aurel32
    ppc_store_dbatu(env, nr, val);
222 45d827d2 aurel32
}
223 45d827d2 aurel32
224 45d827d2 aurel32
void helper_store_dbatl (uint32_t nr, target_ulong val)
225 45d827d2 aurel32
{
226 45d827d2 aurel32
    ppc_store_dbatl(env, nr, val);
227 45d827d2 aurel32
}
228 45d827d2 aurel32
229 45d827d2 aurel32
void helper_store_601_batl (uint32_t nr, target_ulong val)
230 45d827d2 aurel32
{
231 45d827d2 aurel32
    ppc_store_ibatl_601(env, nr, val);
232 45d827d2 aurel32
}
233 45d827d2 aurel32
234 45d827d2 aurel32
void helper_store_601_batu (uint32_t nr, target_ulong val)
235 45d827d2 aurel32
{
236 45d827d2 aurel32
    ppc_store_ibatu_601(env, nr, val);
237 45d827d2 aurel32
}
238 45d827d2 aurel32
#endif
239 45d827d2 aurel32
240 76a66253 j_mayer
/*****************************************************************************/
241 ff4a62cd aurel32
/* Memory load and stores */
242 ff4a62cd aurel32
243 76db3ba4 aurel32
static always_inline target_ulong addr_add(target_ulong addr, target_long arg)
244 ff4a62cd aurel32
{
245 ff4a62cd aurel32
#if defined(TARGET_PPC64)
246 76db3ba4 aurel32
        if (!msr_sf)
247 76db3ba4 aurel32
            return (uint32_t)(addr + arg);
248 ff4a62cd aurel32
        else
249 ff4a62cd aurel32
#endif
250 76db3ba4 aurel32
            return addr + arg;
251 ff4a62cd aurel32
}
252 ff4a62cd aurel32
253 ff4a62cd aurel32
void helper_lmw (target_ulong addr, uint32_t reg)
254 ff4a62cd aurel32
{
255 76db3ba4 aurel32
    for (; reg < 32; reg++) {
256 ff4a62cd aurel32
        if (msr_le)
257 76db3ba4 aurel32
            env->gpr[reg] = bswap32(ldl(addr));
258 ff4a62cd aurel32
        else
259 76db3ba4 aurel32
            env->gpr[reg] = ldl(addr);
260 76db3ba4 aurel32
        addr = addr_add(addr, 4);
261 ff4a62cd aurel32
    }
262 ff4a62cd aurel32
}
263 ff4a62cd aurel32
264 ff4a62cd aurel32
void helper_stmw (target_ulong addr, uint32_t reg)
265 ff4a62cd aurel32
{
266 76db3ba4 aurel32
    for (; reg < 32; reg++) {
267 ff4a62cd aurel32
        if (msr_le)
268 76db3ba4 aurel32
            stl(addr, bswap32((uint32_t)env->gpr[reg]));
269 ff4a62cd aurel32
        else
270 76db3ba4 aurel32
            stl(addr, (uint32_t)env->gpr[reg]);
271 76db3ba4 aurel32
        addr = addr_add(addr, 4);
272 ff4a62cd aurel32
    }
273 ff4a62cd aurel32
}
274 ff4a62cd aurel32
275 dfbc799d aurel32
void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg)
276 dfbc799d aurel32
{
277 dfbc799d aurel32
    int sh;
278 76db3ba4 aurel32
    for (; nb > 3; nb -= 4) {
279 76db3ba4 aurel32
        env->gpr[reg] = ldl(addr);
280 dfbc799d aurel32
        reg = (reg + 1) % 32;
281 76db3ba4 aurel32
        addr = addr_add(addr, 4);
282 dfbc799d aurel32
    }
283 dfbc799d aurel32
    if (unlikely(nb > 0)) {
284 dfbc799d aurel32
        env->gpr[reg] = 0;
285 76db3ba4 aurel32
        for (sh = 24; nb > 0; nb--, sh -= 8) {
286 76db3ba4 aurel32
            env->gpr[reg] |= ldub(addr) << sh;
287 76db3ba4 aurel32
            addr = addr_add(addr, 1);
288 dfbc799d aurel32
        }
289 dfbc799d aurel32
    }
290 dfbc799d aurel32
}
291 dfbc799d aurel32
/* PPC32 specification says we must generate an exception if
292 dfbc799d aurel32
 * rA is in the range of registers to be loaded.
293 dfbc799d aurel32
 * In an other hand, IBM says this is valid, but rA won't be loaded.
294 dfbc799d aurel32
 * For now, I'll follow the spec...
295 dfbc799d aurel32
 */
296 dfbc799d aurel32
void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
297 dfbc799d aurel32
{
298 dfbc799d aurel32
    if (likely(xer_bc != 0)) {
299 dfbc799d aurel32
        if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) ||
300 dfbc799d aurel32
                     (reg < rb && (reg + xer_bc) > rb))) {
301 e06fcd75 aurel32
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
302 e06fcd75 aurel32
                                       POWERPC_EXCP_INVAL |
303 e06fcd75 aurel32
                                       POWERPC_EXCP_INVAL_LSWX);
304 dfbc799d aurel32
        } else {
305 dfbc799d aurel32
            helper_lsw(addr, xer_bc, reg);
306 dfbc799d aurel32
        }
307 dfbc799d aurel32
    }
308 dfbc799d aurel32
}
309 dfbc799d aurel32
310 dfbc799d aurel32
void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg)
311 dfbc799d aurel32
{
312 dfbc799d aurel32
    int sh;
313 76db3ba4 aurel32
    for (; nb > 3; nb -= 4) {
314 76db3ba4 aurel32
        stl(addr, env->gpr[reg]);
315 dfbc799d aurel32
        reg = (reg + 1) % 32;
316 76db3ba4 aurel32
        addr = addr_add(addr, 4);
317 dfbc799d aurel32
    }
318 dfbc799d aurel32
    if (unlikely(nb > 0)) {
319 a16b45e7 aurel32
        for (sh = 24; nb > 0; nb--, sh -= 8) {
320 76db3ba4 aurel32
            stb(addr, (env->gpr[reg] >> sh) & 0xFF);
321 a16b45e7 aurel32
            addr = addr_add(addr, 1);
322 a16b45e7 aurel32
        }
323 dfbc799d aurel32
    }
324 dfbc799d aurel32
}
325 dfbc799d aurel32
326 799a8c8d aurel32
static void do_dcbz(target_ulong addr, int dcache_line_size)
327 799a8c8d aurel32
{
328 76db3ba4 aurel32
    addr &= ~(dcache_line_size - 1);
329 799a8c8d aurel32
    int i;
330 799a8c8d aurel32
    for (i = 0 ; i < dcache_line_size ; i += 4) {
331 dcc532c8 aurel32
        stl(addr + i , 0);
332 799a8c8d aurel32
    }
333 76db3ba4 aurel32
    if (env->reserve == addr)
334 799a8c8d aurel32
        env->reserve = (target_ulong)-1ULL;
335 799a8c8d aurel32
}
336 799a8c8d aurel32
337 799a8c8d aurel32
void helper_dcbz(target_ulong addr)
338 799a8c8d aurel32
{
339 799a8c8d aurel32
    do_dcbz(addr, env->dcache_line_size);
340 799a8c8d aurel32
}
341 799a8c8d aurel32
342 799a8c8d aurel32
void helper_dcbz_970(target_ulong addr)
343 799a8c8d aurel32
{
344 799a8c8d aurel32
    if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1)
345 799a8c8d aurel32
        do_dcbz(addr, 32);
346 799a8c8d aurel32
    else
347 799a8c8d aurel32
        do_dcbz(addr, env->dcache_line_size);
348 799a8c8d aurel32
}
349 799a8c8d aurel32
350 37d269df aurel32
void helper_icbi(target_ulong addr)
351 37d269df aurel32
{
352 37d269df aurel32
    uint32_t tmp;
353 37d269df aurel32
354 76db3ba4 aurel32
    addr &= ~(env->dcache_line_size - 1);
355 37d269df aurel32
    /* Invalidate one cache line :
356 37d269df aurel32
     * PowerPC specification says this is to be treated like a load
357 37d269df aurel32
     * (not a fetch) by the MMU. To be sure it will be so,
358 37d269df aurel32
     * do the load "by hand".
359 37d269df aurel32
     */
360 dcc532c8 aurel32
    tmp = ldl(addr);
361 37d269df aurel32
    tb_invalidate_page_range(addr, addr + env->icache_line_size);
362 37d269df aurel32
}
363 37d269df aurel32
364 bdb4b689 aurel32
// XXX: to be tested
365 bdb4b689 aurel32
target_ulong helper_lscbx (target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
366 bdb4b689 aurel32
{
367 bdb4b689 aurel32
    int i, c, d;
368 bdb4b689 aurel32
    d = 24;
369 bdb4b689 aurel32
    for (i = 0; i < xer_bc; i++) {
370 76db3ba4 aurel32
        c = ldub(addr);
371 76db3ba4 aurel32
        addr = addr_add(addr, 1);
372 bdb4b689 aurel32
        /* ra (if not 0) and rb are never modified */
373 bdb4b689 aurel32
        if (likely(reg != rb && (ra == 0 || reg != ra))) {
374 bdb4b689 aurel32
            env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
375 bdb4b689 aurel32
        }
376 bdb4b689 aurel32
        if (unlikely(c == xer_cmp))
377 bdb4b689 aurel32
            break;
378 bdb4b689 aurel32
        if (likely(d != 0)) {
379 bdb4b689 aurel32
            d -= 8;
380 bdb4b689 aurel32
        } else {
381 bdb4b689 aurel32
            d = 24;
382 bdb4b689 aurel32
            reg++;
383 bdb4b689 aurel32
            reg = reg & 0x1F;
384 bdb4b689 aurel32
        }
385 bdb4b689 aurel32
    }
386 bdb4b689 aurel32
    return i;
387 bdb4b689 aurel32
}
388 bdb4b689 aurel32
389 ff4a62cd aurel32
/*****************************************************************************/
390 fdabc366 bellard
/* Fixed point operations helpers */
391 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
392 d9bce9d9 j_mayer
393 74637406 aurel32
/* multiply high word */
394 74637406 aurel32
uint64_t helper_mulhd (uint64_t arg1, uint64_t arg2)
395 fdabc366 bellard
{
396 74637406 aurel32
    uint64_t tl, th;
397 fdabc366 bellard
398 74637406 aurel32
    muls64(&tl, &th, arg1, arg2);
399 74637406 aurel32
    return th;
400 d9bce9d9 j_mayer
}
401 d9bce9d9 j_mayer
402 74637406 aurel32
/* multiply high word unsigned */
403 74637406 aurel32
uint64_t helper_mulhdu (uint64_t arg1, uint64_t arg2)
404 fdabc366 bellard
{
405 74637406 aurel32
    uint64_t tl, th;
406 fdabc366 bellard
407 74637406 aurel32
    mulu64(&tl, &th, arg1, arg2);
408 74637406 aurel32
    return th;
409 fdabc366 bellard
}
410 fdabc366 bellard
411 74637406 aurel32
uint64_t helper_mulldo (uint64_t arg1, uint64_t arg2)
412 fdabc366 bellard
{
413 d9bce9d9 j_mayer
    int64_t th;
414 d9bce9d9 j_mayer
    uint64_t tl;
415 d9bce9d9 j_mayer
416 74637406 aurel32
    muls64(&tl, (uint64_t *)&th, arg1, arg2);
417 88ad920b j_mayer
    /* If th != 0 && th != -1, then we had an overflow */
418 6f2d8978 j_mayer
    if (likely((uint64_t)(th + 1) <= 1)) {
419 3d7b417e aurel32
        env->xer &= ~(1 << XER_OV);
420 fdabc366 bellard
    } else {
421 3d7b417e aurel32
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
422 fdabc366 bellard
    }
423 74637406 aurel32
    return (int64_t)tl;
424 d9bce9d9 j_mayer
}
425 d9bce9d9 j_mayer
#endif
426 d9bce9d9 j_mayer
427 26d67362 aurel32
target_ulong helper_cntlzw (target_ulong t)
428 603fccce j_mayer
{
429 26d67362 aurel32
    return clz32(t);
430 603fccce j_mayer
}
431 603fccce j_mayer
432 603fccce j_mayer
#if defined(TARGET_PPC64)
433 26d67362 aurel32
target_ulong helper_cntlzd (target_ulong t)
434 603fccce j_mayer
{
435 26d67362 aurel32
    return clz64(t);
436 603fccce j_mayer
}
437 603fccce j_mayer
#endif
438 603fccce j_mayer
439 9a64fbe4 bellard
/* shift right arithmetic helper */
440 26d67362 aurel32
target_ulong helper_sraw (target_ulong value, target_ulong shift)
441 9a64fbe4 bellard
{
442 9a64fbe4 bellard
    int32_t ret;
443 9a64fbe4 bellard
444 26d67362 aurel32
    if (likely(!(shift & 0x20))) {
445 26d67362 aurel32
        if (likely((uint32_t)shift != 0)) {
446 26d67362 aurel32
            shift &= 0x1f;
447 26d67362 aurel32
            ret = (int32_t)value >> shift;
448 26d67362 aurel32
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
449 3d7b417e aurel32
                env->xer &= ~(1 << XER_CA);
450 fdabc366 bellard
            } else {
451 3d7b417e aurel32
                env->xer |= (1 << XER_CA);
452 fdabc366 bellard
            }
453 fdabc366 bellard
        } else {
454 26d67362 aurel32
            ret = (int32_t)value;
455 3d7b417e aurel32
            env->xer &= ~(1 << XER_CA);
456 fdabc366 bellard
        }
457 fdabc366 bellard
    } else {
458 26d67362 aurel32
        ret = (int32_t)value >> 31;
459 26d67362 aurel32
        if (ret) {
460 3d7b417e aurel32
            env->xer |= (1 << XER_CA);
461 26d67362 aurel32
        } else {
462 26d67362 aurel32
            env->xer &= ~(1 << XER_CA);
463 76a66253 j_mayer
        }
464 fdabc366 bellard
    }
465 26d67362 aurel32
    return (target_long)ret;
466 9a64fbe4 bellard
}
467 9a64fbe4 bellard
468 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
469 26d67362 aurel32
target_ulong helper_srad (target_ulong value, target_ulong shift)
470 d9bce9d9 j_mayer
{
471 d9bce9d9 j_mayer
    int64_t ret;
472 d9bce9d9 j_mayer
473 26d67362 aurel32
    if (likely(!(shift & 0x40))) {
474 26d67362 aurel32
        if (likely((uint64_t)shift != 0)) {
475 26d67362 aurel32
            shift &= 0x3f;
476 26d67362 aurel32
            ret = (int64_t)value >> shift;
477 26d67362 aurel32
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
478 3d7b417e aurel32
                env->xer &= ~(1 << XER_CA);
479 d9bce9d9 j_mayer
            } else {
480 3d7b417e aurel32
                env->xer |= (1 << XER_CA);
481 d9bce9d9 j_mayer
            }
482 d9bce9d9 j_mayer
        } else {
483 26d67362 aurel32
            ret = (int64_t)value;
484 3d7b417e aurel32
            env->xer &= ~(1 << XER_CA);
485 d9bce9d9 j_mayer
        }
486 d9bce9d9 j_mayer
    } else {
487 26d67362 aurel32
        ret = (int64_t)value >> 63;
488 26d67362 aurel32
        if (ret) {
489 3d7b417e aurel32
            env->xer |= (1 << XER_CA);
490 26d67362 aurel32
        } else {
491 26d67362 aurel32
            env->xer &= ~(1 << XER_CA);
492 d9bce9d9 j_mayer
        }
493 d9bce9d9 j_mayer
    }
494 26d67362 aurel32
    return ret;
495 d9bce9d9 j_mayer
}
496 d9bce9d9 j_mayer
#endif
497 d9bce9d9 j_mayer
498 26d67362 aurel32
target_ulong helper_popcntb (target_ulong val)
499 d9bce9d9 j_mayer
{
500 6176a26d aurel32
    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
501 6176a26d aurel32
    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
502 6176a26d aurel32
    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
503 6176a26d aurel32
    return val;
504 d9bce9d9 j_mayer
}
505 d9bce9d9 j_mayer
506 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
507 26d67362 aurel32
target_ulong helper_popcntb_64 (target_ulong val)
508 d9bce9d9 j_mayer
{
509 6176a26d aurel32
    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
510 6176a26d aurel32
    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
511 6176a26d aurel32
    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
512 6176a26d aurel32
    return val;
513 d9bce9d9 j_mayer
}
514 d9bce9d9 j_mayer
#endif
515 d9bce9d9 j_mayer
516 fdabc366 bellard
/*****************************************************************************/
517 9a64fbe4 bellard
/* Floating point operations helpers */
518 a0d7d5a7 aurel32
uint64_t helper_float32_to_float64(uint32_t arg)
519 a0d7d5a7 aurel32
{
520 a0d7d5a7 aurel32
    CPU_FloatU f;
521 a0d7d5a7 aurel32
    CPU_DoubleU d;
522 a0d7d5a7 aurel32
    f.l = arg;
523 a0d7d5a7 aurel32
    d.d = float32_to_float64(f.f, &env->fp_status);
524 a0d7d5a7 aurel32
    return d.ll;
525 a0d7d5a7 aurel32
}
526 a0d7d5a7 aurel32
527 a0d7d5a7 aurel32
uint32_t helper_float64_to_float32(uint64_t arg)
528 a0d7d5a7 aurel32
{
529 a0d7d5a7 aurel32
    CPU_FloatU f;
530 a0d7d5a7 aurel32
    CPU_DoubleU d;
531 a0d7d5a7 aurel32
    d.ll = arg;
532 a0d7d5a7 aurel32
    f.f = float64_to_float32(d.d, &env->fp_status);
533 a0d7d5a7 aurel32
    return f.l;
534 a0d7d5a7 aurel32
}
535 a0d7d5a7 aurel32
536 0ca9d380 aurel32
static always_inline int isden (float64 d)
537 7c58044c j_mayer
{
538 0ca9d380 aurel32
    CPU_DoubleU u;
539 7c58044c j_mayer
540 0ca9d380 aurel32
    u.d = d;
541 7c58044c j_mayer
542 0ca9d380 aurel32
    return ((u.ll >> 52) & 0x7FF) == 0;
543 7c58044c j_mayer
}
544 7c58044c j_mayer
545 af12906f aurel32
uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
546 7c58044c j_mayer
{
547 af12906f aurel32
    CPU_DoubleU farg;
548 7c58044c j_mayer
    int isneg;
549 af12906f aurel32
    int ret;
550 af12906f aurel32
    farg.ll = arg;
551 f23c346e aurel32
    isneg = float64_is_neg(farg.d);
552 af12906f aurel32
    if (unlikely(float64_is_nan(farg.d))) {
553 af12906f aurel32
        if (float64_is_signaling_nan(farg.d)) {
554 7c58044c j_mayer
            /* Signaling NaN: flags are undefined */
555 af12906f aurel32
            ret = 0x00;
556 7c58044c j_mayer
        } else {
557 7c58044c j_mayer
            /* Quiet NaN */
558 af12906f aurel32
            ret = 0x11;
559 7c58044c j_mayer
        }
560 f23c346e aurel32
    } else if (unlikely(float64_is_infinity(farg.d))) {
561 7c58044c j_mayer
        /* +/- infinity */
562 7c58044c j_mayer
        if (isneg)
563 af12906f aurel32
            ret = 0x09;
564 7c58044c j_mayer
        else
565 af12906f aurel32
            ret = 0x05;
566 7c58044c j_mayer
    } else {
567 f23c346e aurel32
        if (float64_is_zero(farg.d)) {
568 7c58044c j_mayer
            /* +/- zero */
569 7c58044c j_mayer
            if (isneg)
570 af12906f aurel32
                ret = 0x12;
571 7c58044c j_mayer
            else
572 af12906f aurel32
                ret = 0x02;
573 7c58044c j_mayer
        } else {
574 af12906f aurel32
            if (isden(farg.d)) {
575 7c58044c j_mayer
                /* Denormalized numbers */
576 af12906f aurel32
                ret = 0x10;
577 7c58044c j_mayer
            } else {
578 7c58044c j_mayer
                /* Normalized numbers */
579 af12906f aurel32
                ret = 0x00;
580 7c58044c j_mayer
            }
581 7c58044c j_mayer
            if (isneg) {
582 af12906f aurel32
                ret |= 0x08;
583 7c58044c j_mayer
            } else {
584 af12906f aurel32
                ret |= 0x04;
585 7c58044c j_mayer
            }
586 7c58044c j_mayer
        }
587 7c58044c j_mayer
    }
588 7c58044c j_mayer
    if (set_fprf) {
589 7c58044c j_mayer
        /* We update FPSCR_FPRF */
590 7c58044c j_mayer
        env->fpscr &= ~(0x1F << FPSCR_FPRF);
591 af12906f aurel32
        env->fpscr |= ret << FPSCR_FPRF;
592 7c58044c j_mayer
    }
593 7c58044c j_mayer
    /* We just need fpcc to update Rc1 */
594 af12906f aurel32
    return ret & 0xF;
595 7c58044c j_mayer
}
596 7c58044c j_mayer
597 7c58044c j_mayer
/* Floating-point invalid operations exception */
598 af12906f aurel32
static always_inline uint64_t fload_invalid_op_excp (int op)
599 7c58044c j_mayer
{
600 af12906f aurel32
    uint64_t ret = 0;
601 7c58044c j_mayer
    int ve;
602 7c58044c j_mayer
603 7c58044c j_mayer
    ve = fpscr_ve;
604 e0147e41 aurel32
    switch (op) {
605 e0147e41 aurel32
    case POWERPC_EXCP_FP_VXSNAN:
606 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXSNAN;
607 e0147e41 aurel32
        break;
608 e0147e41 aurel32
    case POWERPC_EXCP_FP_VXSOFT:
609 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXSOFT;
610 e0147e41 aurel32
        break;
611 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXISI:
612 7c58044c j_mayer
        /* Magnitude subtraction of infinities */
613 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXISI;
614 7c58044c j_mayer
        goto update_arith;
615 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXIDI:
616 7c58044c j_mayer
        /* Division of infinity by infinity */
617 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXIDI;
618 7c58044c j_mayer
        goto update_arith;
619 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXZDZ:
620 7c58044c j_mayer
        /* Division of zero by zero */
621 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXZDZ;
622 7c58044c j_mayer
        goto update_arith;
623 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXIMZ:
624 7c58044c j_mayer
        /* Multiplication of zero by infinity */
625 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXIMZ;
626 7c58044c j_mayer
        goto update_arith;
627 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXVC:
628 7c58044c j_mayer
        /* Ordered comparison of NaN */
629 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXVC;
630 7c58044c j_mayer
        env->fpscr &= ~(0xF << FPSCR_FPCC);
631 7c58044c j_mayer
        env->fpscr |= 0x11 << FPSCR_FPCC;
632 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
633 7c58044c j_mayer
        if (ve != 0) {
634 7c58044c j_mayer
            env->exception_index = POWERPC_EXCP_PROGRAM;
635 7c58044c j_mayer
            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
636 7c58044c j_mayer
            /* Update the floating-point enabled exception summary */
637 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FEX;
638 7c58044c j_mayer
            /* Exception is differed */
639 7c58044c j_mayer
            ve = 0;
640 7c58044c j_mayer
        }
641 7c58044c j_mayer
        break;
642 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXSQRT:
643 7c58044c j_mayer
        /* Square root of a negative number */
644 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXSQRT;
645 7c58044c j_mayer
    update_arith:
646 7c58044c j_mayer
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
647 7c58044c j_mayer
        if (ve == 0) {
648 7c58044c j_mayer
            /* Set the result to quiet NaN */
649 e0147e41 aurel32
            ret = 0xFFF8000000000000ULL;
650 7c58044c j_mayer
            env->fpscr &= ~(0xF << FPSCR_FPCC);
651 7c58044c j_mayer
            env->fpscr |= 0x11 << FPSCR_FPCC;
652 7c58044c j_mayer
        }
653 7c58044c j_mayer
        break;
654 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXCVI:
655 7c58044c j_mayer
        /* Invalid conversion */
656 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXCVI;
657 7c58044c j_mayer
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
658 7c58044c j_mayer
        if (ve == 0) {
659 7c58044c j_mayer
            /* Set the result to quiet NaN */
660 e0147e41 aurel32
            ret = 0xFFF8000000000000ULL;
661 7c58044c j_mayer
            env->fpscr &= ~(0xF << FPSCR_FPCC);
662 7c58044c j_mayer
            env->fpscr |= 0x11 << FPSCR_FPCC;
663 7c58044c j_mayer
        }
664 7c58044c j_mayer
        break;
665 7c58044c j_mayer
    }
666 7c58044c j_mayer
    /* Update the floating-point invalid operation summary */
667 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_VX;
668 7c58044c j_mayer
    /* Update the floating-point exception summary */
669 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
670 7c58044c j_mayer
    if (ve != 0) {
671 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
672 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
673 7c58044c j_mayer
        if (msr_fe0 != 0 || msr_fe1 != 0)
674 e06fcd75 aurel32
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
675 7c58044c j_mayer
    }
676 af12906f aurel32
    return ret;
677 7c58044c j_mayer
}
678 7c58044c j_mayer
679 e33e94f9 aurel32
static always_inline void float_zero_divide_excp (void)
680 7c58044c j_mayer
{
681 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_ZX;
682 7c58044c j_mayer
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
683 7c58044c j_mayer
    /* Update the floating-point exception summary */
684 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
685 7c58044c j_mayer
    if (fpscr_ze != 0) {
686 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
687 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
688 7c58044c j_mayer
        if (msr_fe0 != 0 || msr_fe1 != 0) {
689 e06fcd75 aurel32
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
690 e06fcd75 aurel32
                                       POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
691 7c58044c j_mayer
        }
692 7c58044c j_mayer
    }
693 7c58044c j_mayer
}
694 7c58044c j_mayer
695 7c58044c j_mayer
static always_inline void float_overflow_excp (void)
696 7c58044c j_mayer
{
697 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_OX;
698 7c58044c j_mayer
    /* Update the floating-point exception summary */
699 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
700 7c58044c j_mayer
    if (fpscr_oe != 0) {
701 7c58044c j_mayer
        /* XXX: should adjust the result */
702 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
703 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
704 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
705 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
706 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
707 7c58044c j_mayer
    } else {
708 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_XX;
709 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FI;
710 7c58044c j_mayer
    }
711 7c58044c j_mayer
}
712 7c58044c j_mayer
713 7c58044c j_mayer
static always_inline void float_underflow_excp (void)
714 7c58044c j_mayer
{
715 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_UX;
716 7c58044c j_mayer
    /* Update the floating-point exception summary */
717 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
718 7c58044c j_mayer
    if (fpscr_ue != 0) {
719 7c58044c j_mayer
        /* XXX: should adjust the result */
720 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
721 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
722 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
723 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
724 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
725 7c58044c j_mayer
    }
726 7c58044c j_mayer
}
727 7c58044c j_mayer
728 7c58044c j_mayer
static always_inline void float_inexact_excp (void)
729 7c58044c j_mayer
{
730 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_XX;
731 7c58044c j_mayer
    /* Update the floating-point exception summary */
732 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
733 7c58044c j_mayer
    if (fpscr_xe != 0) {
734 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
735 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
736 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
737 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
738 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
739 7c58044c j_mayer
    }
740 7c58044c j_mayer
}
741 7c58044c j_mayer
742 7c58044c j_mayer
static always_inline void fpscr_set_rounding_mode (void)
743 7c58044c j_mayer
{
744 7c58044c j_mayer
    int rnd_type;
745 7c58044c j_mayer
746 7c58044c j_mayer
    /* Set rounding mode */
747 7c58044c j_mayer
    switch (fpscr_rn) {
748 7c58044c j_mayer
    case 0:
749 7c58044c j_mayer
        /* Best approximation (round to nearest) */
750 7c58044c j_mayer
        rnd_type = float_round_nearest_even;
751 7c58044c j_mayer
        break;
752 7c58044c j_mayer
    case 1:
753 7c58044c j_mayer
        /* Smaller magnitude (round toward zero) */
754 7c58044c j_mayer
        rnd_type = float_round_to_zero;
755 7c58044c j_mayer
        break;
756 7c58044c j_mayer
    case 2:
757 7c58044c j_mayer
        /* Round toward +infinite */
758 7c58044c j_mayer
        rnd_type = float_round_up;
759 7c58044c j_mayer
        break;
760 7c58044c j_mayer
    default:
761 7c58044c j_mayer
    case 3:
762 7c58044c j_mayer
        /* Round toward -infinite */
763 7c58044c j_mayer
        rnd_type = float_round_down;
764 7c58044c j_mayer
        break;
765 7c58044c j_mayer
    }
766 7c58044c j_mayer
    set_float_rounding_mode(rnd_type, &env->fp_status);
767 7c58044c j_mayer
}
768 7c58044c j_mayer
769 6e35d524 aurel32
void helper_fpscr_clrbit (uint32_t bit)
770 6e35d524 aurel32
{
771 6e35d524 aurel32
    int prev;
772 6e35d524 aurel32
773 6e35d524 aurel32
    prev = (env->fpscr >> bit) & 1;
774 6e35d524 aurel32
    env->fpscr &= ~(1 << bit);
775 6e35d524 aurel32
    if (prev == 1) {
776 6e35d524 aurel32
        switch (bit) {
777 6e35d524 aurel32
        case FPSCR_RN1:
778 6e35d524 aurel32
        case FPSCR_RN:
779 6e35d524 aurel32
            fpscr_set_rounding_mode();
780 6e35d524 aurel32
            break;
781 6e35d524 aurel32
        default:
782 6e35d524 aurel32
            break;
783 6e35d524 aurel32
        }
784 6e35d524 aurel32
    }
785 6e35d524 aurel32
}
786 6e35d524 aurel32
787 af12906f aurel32
void helper_fpscr_setbit (uint32_t bit)
788 7c58044c j_mayer
{
789 7c58044c j_mayer
    int prev;
790 7c58044c j_mayer
791 7c58044c j_mayer
    prev = (env->fpscr >> bit) & 1;
792 7c58044c j_mayer
    env->fpscr |= 1 << bit;
793 7c58044c j_mayer
    if (prev == 0) {
794 7c58044c j_mayer
        switch (bit) {
795 7c58044c j_mayer
        case FPSCR_VX:
796 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
797 7c58044c j_mayer
            if (fpscr_ve)
798 7c58044c j_mayer
                goto raise_ve;
799 7c58044c j_mayer
        case FPSCR_OX:
800 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
801 7c58044c j_mayer
            if (fpscr_oe)
802 7c58044c j_mayer
                goto raise_oe;
803 7c58044c j_mayer
            break;
804 7c58044c j_mayer
        case FPSCR_UX:
805 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
806 7c58044c j_mayer
            if (fpscr_ue)
807 7c58044c j_mayer
                goto raise_ue;
808 7c58044c j_mayer
            break;
809 7c58044c j_mayer
        case FPSCR_ZX:
810 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
811 7c58044c j_mayer
            if (fpscr_ze)
812 7c58044c j_mayer
                goto raise_ze;
813 7c58044c j_mayer
            break;
814 7c58044c j_mayer
        case FPSCR_XX:
815 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
816 7c58044c j_mayer
            if (fpscr_xe)
817 7c58044c j_mayer
                goto raise_xe;
818 7c58044c j_mayer
            break;
819 7c58044c j_mayer
        case FPSCR_VXSNAN:
820 7c58044c j_mayer
        case FPSCR_VXISI:
821 7c58044c j_mayer
        case FPSCR_VXIDI:
822 7c58044c j_mayer
        case FPSCR_VXZDZ:
823 7c58044c j_mayer
        case FPSCR_VXIMZ:
824 7c58044c j_mayer
        case FPSCR_VXVC:
825 7c58044c j_mayer
        case FPSCR_VXSOFT:
826 7c58044c j_mayer
        case FPSCR_VXSQRT:
827 7c58044c j_mayer
        case FPSCR_VXCVI:
828 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_VX;
829 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
830 7c58044c j_mayer
            if (fpscr_ve != 0)
831 7c58044c j_mayer
                goto raise_ve;
832 7c58044c j_mayer
            break;
833 7c58044c j_mayer
        case FPSCR_VE:
834 7c58044c j_mayer
            if (fpscr_vx != 0) {
835 7c58044c j_mayer
            raise_ve:
836 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP;
837 7c58044c j_mayer
                if (fpscr_vxsnan)
838 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXSNAN;
839 7c58044c j_mayer
                if (fpscr_vxisi)
840 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXISI;
841 7c58044c j_mayer
                if (fpscr_vxidi)
842 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXIDI;
843 7c58044c j_mayer
                if (fpscr_vxzdz)
844 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXZDZ;
845 7c58044c j_mayer
                if (fpscr_vximz)
846 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXIMZ;
847 7c58044c j_mayer
                if (fpscr_vxvc)
848 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXVC;
849 7c58044c j_mayer
                if (fpscr_vxsoft)
850 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXSOFT;
851 7c58044c j_mayer
                if (fpscr_vxsqrt)
852 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXSQRT;
853 7c58044c j_mayer
                if (fpscr_vxcvi)
854 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXCVI;
855 7c58044c j_mayer
                goto raise_excp;
856 7c58044c j_mayer
            }
857 7c58044c j_mayer
            break;
858 7c58044c j_mayer
        case FPSCR_OE:
859 7c58044c j_mayer
            if (fpscr_ox != 0) {
860 7c58044c j_mayer
            raise_oe:
861 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
862 7c58044c j_mayer
                goto raise_excp;
863 7c58044c j_mayer
            }
864 7c58044c j_mayer
            break;
865 7c58044c j_mayer
        case FPSCR_UE:
866 7c58044c j_mayer
            if (fpscr_ux != 0) {
867 7c58044c j_mayer
            raise_ue:
868 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
869 7c58044c j_mayer
                goto raise_excp;
870 7c58044c j_mayer
            }
871 7c58044c j_mayer
            break;
872 7c58044c j_mayer
        case FPSCR_ZE:
873 7c58044c j_mayer
            if (fpscr_zx != 0) {
874 7c58044c j_mayer
            raise_ze:
875 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
876 7c58044c j_mayer
                goto raise_excp;
877 7c58044c j_mayer
            }
878 7c58044c j_mayer
            break;
879 7c58044c j_mayer
        case FPSCR_XE:
880 7c58044c j_mayer
            if (fpscr_xx != 0) {
881 7c58044c j_mayer
            raise_xe:
882 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
883 7c58044c j_mayer
                goto raise_excp;
884 7c58044c j_mayer
            }
885 7c58044c j_mayer
            break;
886 7c58044c j_mayer
        case FPSCR_RN1:
887 7c58044c j_mayer
        case FPSCR_RN:
888 7c58044c j_mayer
            fpscr_set_rounding_mode();
889 7c58044c j_mayer
            break;
890 7c58044c j_mayer
        default:
891 7c58044c j_mayer
            break;
892 7c58044c j_mayer
        raise_excp:
893 7c58044c j_mayer
            /* Update the floating-point enabled exception summary */
894 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FEX;
895 7c58044c j_mayer
                /* We have to update Rc1 before raising the exception */
896 7c58044c j_mayer
            env->exception_index = POWERPC_EXCP_PROGRAM;
897 7c58044c j_mayer
            break;
898 7c58044c j_mayer
        }
899 7c58044c j_mayer
    }
900 7c58044c j_mayer
}
901 7c58044c j_mayer
902 af12906f aurel32
void helper_store_fpscr (uint64_t arg, uint32_t mask)
903 7c58044c j_mayer
{
904 7c58044c j_mayer
    /*
905 7c58044c j_mayer
     * We use only the 32 LSB of the incoming fpr
906 7c58044c j_mayer
     */
907 7c58044c j_mayer
    uint32_t prev, new;
908 7c58044c j_mayer
    int i;
909 7c58044c j_mayer
910 7c58044c j_mayer
    prev = env->fpscr;
911 af12906f aurel32
    new = (uint32_t)arg;
912 27ee5df0 aurel32
    new &= ~0x60000000;
913 27ee5df0 aurel32
    new |= prev & 0x60000000;
914 27ee5df0 aurel32
    for (i = 0; i < 8; i++) {
915 7c58044c j_mayer
        if (mask & (1 << i)) {
916 7c58044c j_mayer
            env->fpscr &= ~(0xF << (4 * i));
917 7c58044c j_mayer
            env->fpscr |= new & (0xF << (4 * i));
918 7c58044c j_mayer
        }
919 7c58044c j_mayer
    }
920 7c58044c j_mayer
    /* Update VX and FEX */
921 7c58044c j_mayer
    if (fpscr_ix != 0)
922 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VX;
923 5567025f aurel32
    else
924 5567025f aurel32
        env->fpscr &= ~(1 << FPSCR_VX);
925 7c58044c j_mayer
    if ((fpscr_ex & fpscr_eex) != 0) {
926 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
927 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
928 7c58044c j_mayer
        /* XXX: we should compute it properly */
929 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP;
930 7c58044c j_mayer
    }
931 5567025f aurel32
    else
932 5567025f aurel32
        env->fpscr &= ~(1 << FPSCR_FEX);
933 7c58044c j_mayer
    fpscr_set_rounding_mode();
934 7c58044c j_mayer
}
935 7c58044c j_mayer
936 af12906f aurel32
void helper_float_check_status (void)
937 7c58044c j_mayer
{
938 af12906f aurel32
#ifdef CONFIG_SOFTFLOAT
939 7c58044c j_mayer
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
940 7c58044c j_mayer
        (env->error_code & POWERPC_EXCP_FP)) {
941 7c58044c j_mayer
        /* Differred floating-point exception after target FPR update */
942 7c58044c j_mayer
        if (msr_fe0 != 0 || msr_fe1 != 0)
943 e06fcd75 aurel32
            helper_raise_exception_err(env->exception_index, env->error_code);
944 be94c952 aurel32
    } else {
945 be94c952 aurel32
        int status = get_float_exception_flags(&env->fp_status);
946 e33e94f9 aurel32
        if (status & float_flag_divbyzero) {
947 e33e94f9 aurel32
            float_zero_divide_excp();
948 e33e94f9 aurel32
        } else if (status & float_flag_overflow) {
949 be94c952 aurel32
            float_overflow_excp();
950 be94c952 aurel32
        } else if (status & float_flag_underflow) {
951 be94c952 aurel32
            float_underflow_excp();
952 be94c952 aurel32
        } else if (status & float_flag_inexact) {
953 be94c952 aurel32
            float_inexact_excp();
954 be94c952 aurel32
        }
955 7c58044c j_mayer
    }
956 af12906f aurel32
#else
957 af12906f aurel32
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
958 af12906f aurel32
        (env->error_code & POWERPC_EXCP_FP)) {
959 af12906f aurel32
        /* Differred floating-point exception after target FPR update */
960 af12906f aurel32
        if (msr_fe0 != 0 || msr_fe1 != 0)
961 e06fcd75 aurel32
            helper_raise_exception_err(env->exception_index, env->error_code);
962 af12906f aurel32
    }
963 af12906f aurel32
#endif
964 af12906f aurel32
}
965 af12906f aurel32
966 af12906f aurel32
#ifdef CONFIG_SOFTFLOAT
967 af12906f aurel32
void helper_reset_fpstatus (void)
968 af12906f aurel32
{
969 be94c952 aurel32
    set_float_exception_flags(0, &env->fp_status);
970 7c58044c j_mayer
}
971 7c58044c j_mayer
#endif
972 7c58044c j_mayer
973 af12906f aurel32
/* fadd - fadd. */
974 af12906f aurel32
uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
975 7c58044c j_mayer
{
976 af12906f aurel32
    CPU_DoubleU farg1, farg2;
977 af12906f aurel32
978 af12906f aurel32
    farg1.ll = arg1;
979 af12906f aurel32
    farg2.ll = arg2;
980 af12906f aurel32
#if USE_PRECISE_EMULATION
981 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
982 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
983 7c58044c j_mayer
        /* sNaN addition */
984 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
985 17218d1f aurel32
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
986 17218d1f aurel32
                      float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
987 7c58044c j_mayer
        /* Magnitude subtraction of infinities */
988 cf1cf21e aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
989 17218d1f aurel32
    } else {
990 17218d1f aurel32
        farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
991 7c58044c j_mayer
    }
992 af12906f aurel32
#else
993 af12906f aurel32
    farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
994 af12906f aurel32
#endif
995 af12906f aurel32
    return farg1.ll;
996 7c58044c j_mayer
}
997 7c58044c j_mayer
998 af12906f aurel32
/* fsub - fsub. */
999 af12906f aurel32
uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
1000 af12906f aurel32
{
1001 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1002 af12906f aurel32
1003 af12906f aurel32
    farg1.ll = arg1;
1004 af12906f aurel32
    farg2.ll = arg2;
1005 af12906f aurel32
#if USE_PRECISE_EMULATION
1006 7c58044c j_mayer
{
1007 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1008 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1009 7c58044c j_mayer
        /* sNaN subtraction */
1010 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1011 17218d1f aurel32
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1012 17218d1f aurel32
                      float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
1013 7c58044c j_mayer
        /* Magnitude subtraction of infinities */
1014 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1015 17218d1f aurel32
    } else {
1016 17218d1f aurel32
        farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1017 7c58044c j_mayer
    }
1018 7c58044c j_mayer
}
1019 af12906f aurel32
#else
1020 af12906f aurel32
    farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1021 af12906f aurel32
#endif
1022 af12906f aurel32
    return farg1.ll;
1023 af12906f aurel32
}
1024 7c58044c j_mayer
1025 af12906f aurel32
/* fmul - fmul. */
1026 af12906f aurel32
uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
1027 7c58044c j_mayer
{
1028 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1029 af12906f aurel32
1030 af12906f aurel32
    farg1.ll = arg1;
1031 af12906f aurel32
    farg2.ll = arg2;
1032 af12906f aurel32
#if USE_PRECISE_EMULATION
1033 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1034 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1035 7c58044c j_mayer
        /* sNaN multiplication */
1036 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1037 f23c346e aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1038 f23c346e aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1039 7c58044c j_mayer
        /* Multiplication of zero by infinity */
1040 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1041 7c58044c j_mayer
    } else {
1042 af12906f aurel32
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1043 7c58044c j_mayer
    }
1044 af12906f aurel32
#else
1045 af12906f aurel32
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1046 af12906f aurel32
#endif
1047 af12906f aurel32
    return farg1.ll;
1048 af12906f aurel32
}
1049 7c58044c j_mayer
1050 af12906f aurel32
/* fdiv - fdiv. */
1051 af12906f aurel32
uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
1052 7c58044c j_mayer
{
1053 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1054 af12906f aurel32
1055 af12906f aurel32
    farg1.ll = arg1;
1056 af12906f aurel32
    farg2.ll = arg2;
1057 af12906f aurel32
#if USE_PRECISE_EMULATION
1058 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1059 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1060 7c58044c j_mayer
        /* sNaN division */
1061 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1062 f23c346e aurel32
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
1063 7c58044c j_mayer
        /* Division of infinity by infinity */
1064 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
1065 e33e94f9 aurel32
    } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
1066 e33e94f9 aurel32
        /* Division of zero by zero */
1067 e33e94f9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
1068 7c58044c j_mayer
    } else {
1069 af12906f aurel32
        farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1070 7c58044c j_mayer
    }
1071 af12906f aurel32
#else
1072 af12906f aurel32
    farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1073 af12906f aurel32
#endif
1074 af12906f aurel32
    return farg1.ll;
1075 7c58044c j_mayer
}
1076 7c58044c j_mayer
1077 af12906f aurel32
/* fabs */
1078 af12906f aurel32
uint64_t helper_fabs (uint64_t arg)
1079 9a64fbe4 bellard
{
1080 af12906f aurel32
    CPU_DoubleU farg;
1081 9a64fbe4 bellard
1082 af12906f aurel32
    farg.ll = arg;
1083 af12906f aurel32
    farg.d = float64_abs(farg.d);
1084 af12906f aurel32
    return farg.ll;
1085 af12906f aurel32
}
1086 af12906f aurel32
1087 af12906f aurel32
/* fnabs */
1088 af12906f aurel32
uint64_t helper_fnabs (uint64_t arg)
1089 af12906f aurel32
{
1090 af12906f aurel32
    CPU_DoubleU farg;
1091 af12906f aurel32
1092 af12906f aurel32
    farg.ll = arg;
1093 af12906f aurel32
    farg.d = float64_abs(farg.d);
1094 af12906f aurel32
    farg.d = float64_chs(farg.d);
1095 af12906f aurel32
    return farg.ll;
1096 af12906f aurel32
}
1097 af12906f aurel32
1098 af12906f aurel32
/* fneg */
1099 af12906f aurel32
uint64_t helper_fneg (uint64_t arg)
1100 af12906f aurel32
{
1101 af12906f aurel32
    CPU_DoubleU farg;
1102 af12906f aurel32
1103 af12906f aurel32
    farg.ll = arg;
1104 af12906f aurel32
    farg.d = float64_chs(farg.d);
1105 af12906f aurel32
    return farg.ll;
1106 af12906f aurel32
}
1107 af12906f aurel32
1108 af12906f aurel32
/* fctiw - fctiw. */
1109 af12906f aurel32
uint64_t helper_fctiw (uint64_t arg)
1110 af12906f aurel32
{
1111 af12906f aurel32
    CPU_DoubleU farg;
1112 af12906f aurel32
    farg.ll = arg;
1113 af12906f aurel32
1114 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1115 7c58044c j_mayer
        /* sNaN conversion */
1116 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1117 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1118 7c58044c j_mayer
        /* qNan / infinity conversion */
1119 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1120 7c58044c j_mayer
    } else {
1121 af12906f aurel32
        farg.ll = float64_to_int32(farg.d, &env->fp_status);
1122 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1123 7c58044c j_mayer
        /* XXX: higher bits are not supposed to be significant.
1124 7c58044c j_mayer
         *     to make tests easier, return the same as a real PowerPC 750
1125 7c58044c j_mayer
         */
1126 af12906f aurel32
        farg.ll |= 0xFFF80000ULL << 32;
1127 e864cabd j_mayer
#endif
1128 7c58044c j_mayer
    }
1129 af12906f aurel32
    return farg.ll;
1130 9a64fbe4 bellard
}
1131 9a64fbe4 bellard
1132 af12906f aurel32
/* fctiwz - fctiwz. */
1133 af12906f aurel32
uint64_t helper_fctiwz (uint64_t arg)
1134 9a64fbe4 bellard
{
1135 af12906f aurel32
    CPU_DoubleU farg;
1136 af12906f aurel32
    farg.ll = arg;
1137 4ecc3190 bellard
1138 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1139 7c58044c j_mayer
        /* sNaN conversion */
1140 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1141 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1142 7c58044c j_mayer
        /* qNan / infinity conversion */
1143 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1144 7c58044c j_mayer
    } else {
1145 af12906f aurel32
        farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
1146 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1147 7c58044c j_mayer
        /* XXX: higher bits are not supposed to be significant.
1148 7c58044c j_mayer
         *     to make tests easier, return the same as a real PowerPC 750
1149 7c58044c j_mayer
         */
1150 af12906f aurel32
        farg.ll |= 0xFFF80000ULL << 32;
1151 e864cabd j_mayer
#endif
1152 7c58044c j_mayer
    }
1153 af12906f aurel32
    return farg.ll;
1154 9a64fbe4 bellard
}
1155 9a64fbe4 bellard
1156 426613db j_mayer
#if defined(TARGET_PPC64)
1157 af12906f aurel32
/* fcfid - fcfid. */
1158 af12906f aurel32
uint64_t helper_fcfid (uint64_t arg)
1159 426613db j_mayer
{
1160 af12906f aurel32
    CPU_DoubleU farg;
1161 af12906f aurel32
    farg.d = int64_to_float64(arg, &env->fp_status);
1162 af12906f aurel32
    return farg.ll;
1163 426613db j_mayer
}
1164 426613db j_mayer
1165 af12906f aurel32
/* fctid - fctid. */
1166 af12906f aurel32
uint64_t helper_fctid (uint64_t arg)
1167 426613db j_mayer
{
1168 af12906f aurel32
    CPU_DoubleU farg;
1169 af12906f aurel32
    farg.ll = arg;
1170 426613db j_mayer
1171 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1172 7c58044c j_mayer
        /* sNaN conversion */
1173 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1174 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1175 7c58044c j_mayer
        /* qNan / infinity conversion */
1176 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1177 7c58044c j_mayer
    } else {
1178 af12906f aurel32
        farg.ll = float64_to_int64(farg.d, &env->fp_status);
1179 7c58044c j_mayer
    }
1180 af12906f aurel32
    return farg.ll;
1181 426613db j_mayer
}
1182 426613db j_mayer
1183 af12906f aurel32
/* fctidz - fctidz. */
1184 af12906f aurel32
uint64_t helper_fctidz (uint64_t arg)
1185 426613db j_mayer
{
1186 af12906f aurel32
    CPU_DoubleU farg;
1187 af12906f aurel32
    farg.ll = arg;
1188 426613db j_mayer
1189 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1190 7c58044c j_mayer
        /* sNaN conversion */
1191 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1192 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1193 7c58044c j_mayer
        /* qNan / infinity conversion */
1194 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1195 7c58044c j_mayer
    } else {
1196 af12906f aurel32
        farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
1197 7c58044c j_mayer
    }
1198 af12906f aurel32
    return farg.ll;
1199 426613db j_mayer
}
1200 426613db j_mayer
1201 426613db j_mayer
#endif
1202 426613db j_mayer
1203 af12906f aurel32
static always_inline uint64_t do_fri (uint64_t arg, int rounding_mode)
1204 d7e4b87e j_mayer
{
1205 af12906f aurel32
    CPU_DoubleU farg;
1206 af12906f aurel32
    farg.ll = arg;
1207 af12906f aurel32
1208 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1209 7c58044c j_mayer
        /* sNaN round */
1210 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1211 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1212 7c58044c j_mayer
        /* qNan / infinity round */
1213 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1214 7c58044c j_mayer
    } else {
1215 7c58044c j_mayer
        set_float_rounding_mode(rounding_mode, &env->fp_status);
1216 af12906f aurel32
        farg.ll = float64_round_to_int(farg.d, &env->fp_status);
1217 7c58044c j_mayer
        /* Restore rounding mode from FPSCR */
1218 7c58044c j_mayer
        fpscr_set_rounding_mode();
1219 7c58044c j_mayer
    }
1220 af12906f aurel32
    return farg.ll;
1221 d7e4b87e j_mayer
}
1222 d7e4b87e j_mayer
1223 af12906f aurel32
uint64_t helper_frin (uint64_t arg)
1224 d7e4b87e j_mayer
{
1225 af12906f aurel32
    return do_fri(arg, float_round_nearest_even);
1226 d7e4b87e j_mayer
}
1227 d7e4b87e j_mayer
1228 af12906f aurel32
uint64_t helper_friz (uint64_t arg)
1229 d7e4b87e j_mayer
{
1230 af12906f aurel32
    return do_fri(arg, float_round_to_zero);
1231 d7e4b87e j_mayer
}
1232 d7e4b87e j_mayer
1233 af12906f aurel32
uint64_t helper_frip (uint64_t arg)
1234 d7e4b87e j_mayer
{
1235 af12906f aurel32
    return do_fri(arg, float_round_up);
1236 d7e4b87e j_mayer
}
1237 d7e4b87e j_mayer
1238 af12906f aurel32
uint64_t helper_frim (uint64_t arg)
1239 d7e4b87e j_mayer
{
1240 af12906f aurel32
    return do_fri(arg, float_round_down);
1241 d7e4b87e j_mayer
}
1242 d7e4b87e j_mayer
1243 af12906f aurel32
/* fmadd - fmadd. */
1244 af12906f aurel32
uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1245 e864cabd j_mayer
{
1246 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1247 af12906f aurel32
1248 af12906f aurel32
    farg1.ll = arg1;
1249 af12906f aurel32
    farg2.ll = arg2;
1250 af12906f aurel32
    farg3.ll = arg3;
1251 af12906f aurel32
#if USE_PRECISE_EMULATION
1252 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1253 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1254 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1255 7c58044c j_mayer
        /* sNaN operation */
1256 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1257 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1258 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1259 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1260 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1261 7c58044c j_mayer
    } else {
1262 e864cabd j_mayer
#ifdef FLOAT128
1263 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1264 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1265 7c58044c j_mayer
1266 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1267 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1268 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1269 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1270 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1271 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1272 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1273 da1e7ac9 aurel32
        } else {
1274 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1275 da1e7ac9 aurel32
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1276 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1277 da1e7ac9 aurel32
        }
1278 e864cabd j_mayer
#else
1279 7c58044c j_mayer
        /* This is OK on x86 hosts */
1280 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) + farg3.d;
1281 e864cabd j_mayer
#endif
1282 7c58044c j_mayer
    }
1283 af12906f aurel32
#else
1284 af12906f aurel32
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1285 af12906f aurel32
    farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1286 af12906f aurel32
#endif
1287 af12906f aurel32
    return farg1.ll;
1288 e864cabd j_mayer
}
1289 e864cabd j_mayer
1290 af12906f aurel32
/* fmsub - fmsub. */
1291 af12906f aurel32
uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1292 e864cabd j_mayer
{
1293 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1294 af12906f aurel32
1295 af12906f aurel32
    farg1.ll = arg1;
1296 af12906f aurel32
    farg2.ll = arg2;
1297 af12906f aurel32
    farg3.ll = arg3;
1298 af12906f aurel32
#if USE_PRECISE_EMULATION
1299 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1300 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1301 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1302 7c58044c j_mayer
        /* sNaN operation */
1303 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1304 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1305 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1306 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1307 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1308 7c58044c j_mayer
    } else {
1309 e864cabd j_mayer
#ifdef FLOAT128
1310 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1311 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1312 7c58044c j_mayer
1313 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1314 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1315 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1316 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1317 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1318 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1319 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1320 da1e7ac9 aurel32
        } else {
1321 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1322 da1e7ac9 aurel32
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1323 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1324 da1e7ac9 aurel32
        }
1325 e864cabd j_mayer
#else
1326 7c58044c j_mayer
        /* This is OK on x86 hosts */
1327 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) - farg3.d;
1328 e864cabd j_mayer
#endif
1329 7c58044c j_mayer
    }
1330 af12906f aurel32
#else
1331 af12906f aurel32
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1332 af12906f aurel32
    farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1333 af12906f aurel32
#endif
1334 af12906f aurel32
    return farg1.ll;
1335 e864cabd j_mayer
}
1336 e864cabd j_mayer
1337 af12906f aurel32
/* fnmadd - fnmadd. */
1338 af12906f aurel32
uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1339 4b3686fa bellard
{
1340 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1341 af12906f aurel32
1342 af12906f aurel32
    farg1.ll = arg1;
1343 af12906f aurel32
    farg2.ll = arg2;
1344 af12906f aurel32
    farg3.ll = arg3;
1345 af12906f aurel32
1346 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1347 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1348 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1349 7c58044c j_mayer
        /* sNaN operation */
1350 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1351 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1352 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1353 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1354 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1355 7c58044c j_mayer
    } else {
1356 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1357 e864cabd j_mayer
#ifdef FLOAT128
1358 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1359 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1360 7c58044c j_mayer
1361 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1362 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1363 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1364 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1365 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1366 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1367 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1368 da1e7ac9 aurel32
        } else {
1369 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1370 da1e7ac9 aurel32
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1371 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1372 da1e7ac9 aurel32
        }
1373 e864cabd j_mayer
#else
1374 7c58044c j_mayer
        /* This is OK on x86 hosts */
1375 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) + farg3.d;
1376 e864cabd j_mayer
#endif
1377 e864cabd j_mayer
#else
1378 af12906f aurel32
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1379 af12906f aurel32
        farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1380 e864cabd j_mayer
#endif
1381 a44d2ce1 aurel32
        if (likely(!float64_is_nan(farg1.d)))
1382 af12906f aurel32
            farg1.d = float64_chs(farg1.d);
1383 7c58044c j_mayer
    }
1384 af12906f aurel32
    return farg1.ll;
1385 4b3686fa bellard
}
1386 4b3686fa bellard
1387 af12906f aurel32
/* fnmsub - fnmsub. */
1388 af12906f aurel32
uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1389 4b3686fa bellard
{
1390 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1391 af12906f aurel32
1392 af12906f aurel32
    farg1.ll = arg1;
1393 af12906f aurel32
    farg2.ll = arg2;
1394 af12906f aurel32
    farg3.ll = arg3;
1395 af12906f aurel32
1396 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1397 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1398 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1399 7c58044c j_mayer
        /* sNaN operation */
1400 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1401 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1402 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1403 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1404 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1405 7c58044c j_mayer
    } else {
1406 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1407 e864cabd j_mayer
#ifdef FLOAT128
1408 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1409 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1410 7c58044c j_mayer
1411 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1412 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1413 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1414 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1415 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1416 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1417 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1418 da1e7ac9 aurel32
        } else {
1419 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1420 da1e7ac9 aurel32
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1421 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1422 da1e7ac9 aurel32
        }
1423 e864cabd j_mayer
#else
1424 7c58044c j_mayer
        /* This is OK on x86 hosts */
1425 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) - farg3.d;
1426 e864cabd j_mayer
#endif
1427 e864cabd j_mayer
#else
1428 af12906f aurel32
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1429 af12906f aurel32
        farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1430 e864cabd j_mayer
#endif
1431 a44d2ce1 aurel32
        if (likely(!float64_is_nan(farg1.d)))
1432 af12906f aurel32
            farg1.d = float64_chs(farg1.d);
1433 7c58044c j_mayer
    }
1434 af12906f aurel32
    return farg1.ll;
1435 1ef59d0a bellard
}
1436 1ef59d0a bellard
1437 af12906f aurel32
/* frsp - frsp. */
1438 af12906f aurel32
uint64_t helper_frsp (uint64_t arg)
1439 7c58044c j_mayer
{
1440 af12906f aurel32
    CPU_DoubleU farg;
1441 6ad193ed aurel32
    float32 f32;
1442 af12906f aurel32
    farg.ll = arg;
1443 af12906f aurel32
1444 af12906f aurel32
#if USE_PRECISE_EMULATION
1445 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1446 7c58044c j_mayer
        /* sNaN square root */
1447 af12906f aurel32
       farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1448 7c58044c j_mayer
    } else {
1449 6ad193ed aurel32
       f32 = float64_to_float32(farg.d, &env->fp_status);
1450 6ad193ed aurel32
       farg.d = float32_to_float64(f32, &env->fp_status);
1451 7c58044c j_mayer
    }
1452 af12906f aurel32
#else
1453 6ad193ed aurel32
    f32 = float64_to_float32(farg.d, &env->fp_status);
1454 6ad193ed aurel32
    farg.d = float32_to_float64(f32, &env->fp_status);
1455 af12906f aurel32
#endif
1456 af12906f aurel32
    return farg.ll;
1457 7c58044c j_mayer
}
1458 7c58044c j_mayer
1459 af12906f aurel32
/* fsqrt - fsqrt. */
1460 af12906f aurel32
uint64_t helper_fsqrt (uint64_t arg)
1461 9a64fbe4 bellard
{
1462 af12906f aurel32
    CPU_DoubleU farg;
1463 af12906f aurel32
    farg.ll = arg;
1464 af12906f aurel32
1465 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1466 7c58044c j_mayer
        /* sNaN square root */
1467 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1468 f23c346e aurel32
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1469 7c58044c j_mayer
        /* Square root of a negative nonzero number */
1470 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1471 7c58044c j_mayer
    } else {
1472 af12906f aurel32
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1473 7c58044c j_mayer
    }
1474 af12906f aurel32
    return farg.ll;
1475 9a64fbe4 bellard
}
1476 9a64fbe4 bellard
1477 af12906f aurel32
/* fre - fre. */
1478 af12906f aurel32
uint64_t helper_fre (uint64_t arg)
1479 d7e4b87e j_mayer
{
1480 c609b12e aurel32
    CPU_DoubleU farg;
1481 06f7332a aurel32
    farg.ll = arg;
1482 d7e4b87e j_mayer
1483 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1484 7c58044c j_mayer
        /* sNaN reciprocal */
1485 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1486 d7e4b87e j_mayer
    } else {
1487 c609b12e aurel32
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1488 d7e4b87e j_mayer
    }
1489 af12906f aurel32
    return farg.d;
1490 d7e4b87e j_mayer
}
1491 d7e4b87e j_mayer
1492 af12906f aurel32
/* fres - fres. */
1493 af12906f aurel32
uint64_t helper_fres (uint64_t arg)
1494 9a64fbe4 bellard
{
1495 06f7332a aurel32
    CPU_DoubleU farg;
1496 6c01bf6c aurel32
    float32 f32;
1497 06f7332a aurel32
    farg.ll = arg;
1498 4ecc3190 bellard
1499 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1500 7c58044c j_mayer
        /* sNaN reciprocal */
1501 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1502 4ecc3190 bellard
    } else {
1503 c609b12e aurel32
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1504 6c01bf6c aurel32
        f32 = float64_to_float32(farg.d, &env->fp_status);
1505 6c01bf6c aurel32
        farg.d = float32_to_float64(f32, &env->fp_status);
1506 4ecc3190 bellard
    }
1507 af12906f aurel32
    return farg.ll;
1508 9a64fbe4 bellard
}
1509 9a64fbe4 bellard
1510 af12906f aurel32
/* frsqrte  - frsqrte. */
1511 af12906f aurel32
uint64_t helper_frsqrte (uint64_t arg)
1512 9a64fbe4 bellard
{
1513 c609b12e aurel32
    CPU_DoubleU farg;
1514 6c01bf6c aurel32
    float32 f32;
1515 06f7332a aurel32
    farg.ll = arg;
1516 4ecc3190 bellard
1517 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1518 7c58044c j_mayer
        /* sNaN reciprocal square root */
1519 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1520 f23c346e aurel32
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1521 7c58044c j_mayer
        /* Reciprocal square root of a negative nonzero number */
1522 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1523 4ecc3190 bellard
    } else {
1524 6c01bf6c aurel32
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1525 c609b12e aurel32
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1526 6c01bf6c aurel32
        f32 = float64_to_float32(farg.d, &env->fp_status);
1527 6c01bf6c aurel32
        farg.d = float32_to_float64(f32, &env->fp_status);
1528 4ecc3190 bellard
    }
1529 af12906f aurel32
    return farg.ll;
1530 9a64fbe4 bellard
}
1531 9a64fbe4 bellard
1532 af12906f aurel32
/* fsel - fsel. */
1533 af12906f aurel32
uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1534 9a64fbe4 bellard
{
1535 6ad7365a aurel32
    CPU_DoubleU farg1;
1536 af12906f aurel32
1537 af12906f aurel32
    farg1.ll = arg1;
1538 af12906f aurel32
1539 572c8952 aurel32
    if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_nan(farg1.d))
1540 6ad7365a aurel32
        return arg2;
1541 4ecc3190 bellard
    else
1542 6ad7365a aurel32
        return arg3;
1543 9a64fbe4 bellard
}
1544 9a64fbe4 bellard
1545 9a819377 aurel32
void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1546 9a64fbe4 bellard
{
1547 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1548 e1571908 aurel32
    uint32_t ret = 0;
1549 af12906f aurel32
    farg1.ll = arg1;
1550 af12906f aurel32
    farg2.ll = arg2;
1551 e1571908 aurel32
1552 9a819377 aurel32
    if (unlikely(float64_is_nan(farg1.d) ||
1553 9a819377 aurel32
                 float64_is_nan(farg2.d))) {
1554 9a819377 aurel32
        ret = 0x01UL;
1555 9a819377 aurel32
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1556 9a819377 aurel32
        ret = 0x08UL;
1557 9a819377 aurel32
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1558 9a819377 aurel32
        ret = 0x04UL;
1559 7c58044c j_mayer
    } else {
1560 9a819377 aurel32
        ret = 0x02UL;
1561 9a64fbe4 bellard
    }
1562 9a819377 aurel32
1563 7c58044c j_mayer
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1564 e1571908 aurel32
    env->fpscr |= ret << FPSCR_FPRF;
1565 9a819377 aurel32
    env->crf[crfD] = ret;
1566 9a819377 aurel32
    if (unlikely(ret == 0x01UL
1567 9a819377 aurel32
                 && (float64_is_signaling_nan(farg1.d) ||
1568 9a819377 aurel32
                     float64_is_signaling_nan(farg2.d)))) {
1569 9a819377 aurel32
        /* sNaN comparison */
1570 9a819377 aurel32
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1571 9a819377 aurel32
    }
1572 9a64fbe4 bellard
}
1573 9a64fbe4 bellard
1574 9a819377 aurel32
void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1575 9a64fbe4 bellard
{
1576 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1577 e1571908 aurel32
    uint32_t ret = 0;
1578 af12906f aurel32
    farg1.ll = arg1;
1579 af12906f aurel32
    farg2.ll = arg2;
1580 e1571908 aurel32
1581 af12906f aurel32
    if (unlikely(float64_is_nan(farg1.d) ||
1582 af12906f aurel32
                 float64_is_nan(farg2.d))) {
1583 9a819377 aurel32
        ret = 0x01UL;
1584 9a819377 aurel32
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1585 9a819377 aurel32
        ret = 0x08UL;
1586 9a819377 aurel32
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1587 9a819377 aurel32
        ret = 0x04UL;
1588 9a819377 aurel32
    } else {
1589 9a819377 aurel32
        ret = 0x02UL;
1590 9a819377 aurel32
    }
1591 9a819377 aurel32
1592 9a819377 aurel32
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1593 9a819377 aurel32
    env->fpscr |= ret << FPSCR_FPRF;
1594 9a819377 aurel32
    env->crf[crfD] = ret;
1595 9a819377 aurel32
    if (unlikely (ret == 0x01UL)) {
1596 af12906f aurel32
        if (float64_is_signaling_nan(farg1.d) ||
1597 af12906f aurel32
            float64_is_signaling_nan(farg2.d)) {
1598 7c58044c j_mayer
            /* sNaN comparison */
1599 7c58044c j_mayer
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1600 7c58044c j_mayer
                                  POWERPC_EXCP_FP_VXVC);
1601 7c58044c j_mayer
        } else {
1602 7c58044c j_mayer
            /* qNaN comparison */
1603 7c58044c j_mayer
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1604 7c58044c j_mayer
        }
1605 9a64fbe4 bellard
    }
1606 9a64fbe4 bellard
}
1607 9a64fbe4 bellard
1608 76a66253 j_mayer
#if !defined (CONFIG_USER_ONLY)
1609 6527f6ea aurel32
void helper_store_msr (target_ulong val)
1610 0411a972 j_mayer
{
1611 6527f6ea aurel32
    val = hreg_store_msr(env, val, 0);
1612 6527f6ea aurel32
    if (val != 0) {
1613 0411a972 j_mayer
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1614 e06fcd75 aurel32
        helper_raise_exception(val);
1615 0411a972 j_mayer
    }
1616 0411a972 j_mayer
}
1617 0411a972 j_mayer
1618 d72a19f7 aurel32
static always_inline void do_rfi (target_ulong nip, target_ulong msr,
1619 0411a972 j_mayer
                                    target_ulong msrm, int keep_msrh)
1620 9a64fbe4 bellard
{
1621 426613db j_mayer
#if defined(TARGET_PPC64)
1622 0411a972 j_mayer
    if (msr & (1ULL << MSR_SF)) {
1623 0411a972 j_mayer
        nip = (uint64_t)nip;
1624 0411a972 j_mayer
        msr &= (uint64_t)msrm;
1625 a42bd6cc j_mayer
    } else {
1626 0411a972 j_mayer
        nip = (uint32_t)nip;
1627 0411a972 j_mayer
        msr = (uint32_t)(msr & msrm);
1628 0411a972 j_mayer
        if (keep_msrh)
1629 0411a972 j_mayer
            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
1630 a42bd6cc j_mayer
    }
1631 426613db j_mayer
#else
1632 0411a972 j_mayer
    nip = (uint32_t)nip;
1633 0411a972 j_mayer
    msr &= (uint32_t)msrm;
1634 426613db j_mayer
#endif
1635 0411a972 j_mayer
    /* XXX: beware: this is false if VLE is supported */
1636 0411a972 j_mayer
    env->nip = nip & ~((target_ulong)0x00000003);
1637 a4f30719 j_mayer
    hreg_store_msr(env, msr, 1);
1638 fdabc366 bellard
#if defined (DEBUG_OP)
1639 0411a972 j_mayer
    cpu_dump_rfi(env->nip, env->msr);
1640 fdabc366 bellard
#endif
1641 0411a972 j_mayer
    /* No need to raise an exception here,
1642 0411a972 j_mayer
     * as rfi is always the last insn of a TB
1643 0411a972 j_mayer
     */
1644 fdabc366 bellard
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1645 9a64fbe4 bellard
}
1646 d9bce9d9 j_mayer
1647 d72a19f7 aurel32
void helper_rfi (void)
1648 0411a972 j_mayer
{
1649 d72a19f7 aurel32
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1650 2ada0ed7 blueswir1
           ~((target_ulong)0x0), 1);
1651 0411a972 j_mayer
}
1652 0411a972 j_mayer
1653 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1654 d72a19f7 aurel32
void helper_rfid (void)
1655 426613db j_mayer
{
1656 d72a19f7 aurel32
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1657 2ada0ed7 blueswir1
           ~((target_ulong)0x0), 0);
1658 d9bce9d9 j_mayer
}
1659 7863667f j_mayer
1660 d72a19f7 aurel32
void helper_hrfid (void)
1661 be147d08 j_mayer
{
1662 d72a19f7 aurel32
    do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
1663 2ada0ed7 blueswir1
           ~((target_ulong)0x0), 0);
1664 be147d08 j_mayer
}
1665 be147d08 j_mayer
#endif
1666 76a66253 j_mayer
#endif
1667 9a64fbe4 bellard
1668 cab3bee2 aurel32
void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
1669 9a64fbe4 bellard
{
1670 cab3bee2 aurel32
    if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1671 cab3bee2 aurel32
                  ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1672 cab3bee2 aurel32
                  ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1673 cab3bee2 aurel32
                  ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1674 cab3bee2 aurel32
                  ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1675 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1676 a42bd6cc j_mayer
    }
1677 9a64fbe4 bellard
}
1678 9a64fbe4 bellard
1679 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1680 cab3bee2 aurel32
void helper_td (target_ulong arg1, target_ulong arg2, uint32_t flags)
1681 d9bce9d9 j_mayer
{
1682 cab3bee2 aurel32
    if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1683 cab3bee2 aurel32
                  ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1684 cab3bee2 aurel32
                  ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1685 cab3bee2 aurel32
                  ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1686 cab3bee2 aurel32
                  ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01)))))
1687 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1688 d9bce9d9 j_mayer
}
1689 d9bce9d9 j_mayer
#endif
1690 d9bce9d9 j_mayer
1691 fdabc366 bellard
/*****************************************************************************/
1692 76a66253 j_mayer
/* PowerPC 601 specific instructions (POWER bridge) */
1693 9a64fbe4 bellard
1694 22e0e173 aurel32
target_ulong helper_clcs (uint32_t arg)
1695 9a64fbe4 bellard
{
1696 22e0e173 aurel32
    switch (arg) {
1697 76a66253 j_mayer
    case 0x0CUL:
1698 76a66253 j_mayer
        /* Instruction cache line size */
1699 22e0e173 aurel32
        return env->icache_line_size;
1700 76a66253 j_mayer
        break;
1701 76a66253 j_mayer
    case 0x0DUL:
1702 76a66253 j_mayer
        /* Data cache line size */
1703 22e0e173 aurel32
        return env->dcache_line_size;
1704 76a66253 j_mayer
        break;
1705 76a66253 j_mayer
    case 0x0EUL:
1706 76a66253 j_mayer
        /* Minimum cache line size */
1707 22e0e173 aurel32
        return (env->icache_line_size < env->dcache_line_size) ?
1708 22e0e173 aurel32
                env->icache_line_size : env->dcache_line_size;
1709 76a66253 j_mayer
        break;
1710 76a66253 j_mayer
    case 0x0FUL:
1711 76a66253 j_mayer
        /* Maximum cache line size */
1712 22e0e173 aurel32
        return (env->icache_line_size > env->dcache_line_size) ?
1713 22e0e173 aurel32
                env->icache_line_size : env->dcache_line_size;
1714 76a66253 j_mayer
        break;
1715 76a66253 j_mayer
    default:
1716 76a66253 j_mayer
        /* Undefined */
1717 22e0e173 aurel32
        return 0;
1718 76a66253 j_mayer
        break;
1719 76a66253 j_mayer
    }
1720 76a66253 j_mayer
}
1721 76a66253 j_mayer
1722 22e0e173 aurel32
target_ulong helper_div (target_ulong arg1, target_ulong arg2)
1723 76a66253 j_mayer
{
1724 22e0e173 aurel32
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1725 76a66253 j_mayer
1726 22e0e173 aurel32
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1727 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1728 76a66253 j_mayer
        env->spr[SPR_MQ] = 0;
1729 22e0e173 aurel32
        return INT32_MIN;
1730 76a66253 j_mayer
    } else {
1731 22e0e173 aurel32
        env->spr[SPR_MQ] = tmp % arg2;
1732 22e0e173 aurel32
        return  tmp / (int32_t)arg2;
1733 76a66253 j_mayer
    }
1734 76a66253 j_mayer
}
1735 76a66253 j_mayer
1736 22e0e173 aurel32
target_ulong helper_divo (target_ulong arg1, target_ulong arg2)
1737 76a66253 j_mayer
{
1738 22e0e173 aurel32
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1739 76a66253 j_mayer
1740 22e0e173 aurel32
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1741 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1742 3d7b417e aurel32
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
1743 76a66253 j_mayer
        env->spr[SPR_MQ] = 0;
1744 22e0e173 aurel32
        return INT32_MIN;
1745 76a66253 j_mayer
    } else {
1746 22e0e173 aurel32
        env->spr[SPR_MQ] = tmp % arg2;
1747 22e0e173 aurel32
        tmp /= (int32_t)arg2;
1748 22e0e173 aurel32
        if ((int32_t)tmp != tmp) {
1749 3d7b417e aurel32
            env->xer |= (1 << XER_OV) | (1 << XER_SO);
1750 76a66253 j_mayer
        } else {
1751 3d7b417e aurel32
            env->xer &= ~(1 << XER_OV);
1752 76a66253 j_mayer
        }
1753 22e0e173 aurel32
        return tmp;
1754 76a66253 j_mayer
    }
1755 76a66253 j_mayer
}
1756 76a66253 j_mayer
1757 22e0e173 aurel32
target_ulong helper_divs (target_ulong arg1, target_ulong arg2)
1758 76a66253 j_mayer
{
1759 22e0e173 aurel32
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1760 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1761 22e0e173 aurel32
        env->spr[SPR_MQ] = 0;
1762 22e0e173 aurel32
        return INT32_MIN;
1763 76a66253 j_mayer
    } else {
1764 22e0e173 aurel32
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1765 22e0e173 aurel32
        return (int32_t)arg1 / (int32_t)arg2;
1766 76a66253 j_mayer
    }
1767 76a66253 j_mayer
}
1768 76a66253 j_mayer
1769 22e0e173 aurel32
target_ulong helper_divso (target_ulong arg1, target_ulong arg2)
1770 76a66253 j_mayer
{
1771 22e0e173 aurel32
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1772 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1773 3d7b417e aurel32
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
1774 22e0e173 aurel32
        env->spr[SPR_MQ] = 0;
1775 22e0e173 aurel32
        return INT32_MIN;
1776 76a66253 j_mayer
    } else {
1777 3d7b417e aurel32
        env->xer &= ~(1 << XER_OV);
1778 22e0e173 aurel32
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1779 22e0e173 aurel32
        return (int32_t)arg1 / (int32_t)arg2;
1780 76a66253 j_mayer
    }
1781 76a66253 j_mayer
}
1782 76a66253 j_mayer
1783 76a66253 j_mayer
#if !defined (CONFIG_USER_ONLY)
1784 22e0e173 aurel32
target_ulong helper_rac (target_ulong addr)
1785 76a66253 j_mayer
{
1786 76a66253 j_mayer
    mmu_ctx_t ctx;
1787 faadf50e j_mayer
    int nb_BATs;
1788 22e0e173 aurel32
    target_ulong ret = 0;
1789 76a66253 j_mayer
1790 76a66253 j_mayer
    /* We don't have to generate many instances of this instruction,
1791 76a66253 j_mayer
     * as rac is supervisor only.
1792 76a66253 j_mayer
     */
1793 faadf50e j_mayer
    /* XXX: FIX THIS: Pretend we have no BAT */
1794 faadf50e j_mayer
    nb_BATs = env->nb_BATs;
1795 faadf50e j_mayer
    env->nb_BATs = 0;
1796 22e0e173 aurel32
    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0)
1797 22e0e173 aurel32
        ret = ctx.raddr;
1798 faadf50e j_mayer
    env->nb_BATs = nb_BATs;
1799 22e0e173 aurel32
    return ret;
1800 76a66253 j_mayer
}
1801 76a66253 j_mayer
1802 d72a19f7 aurel32
void helper_rfsvc (void)
1803 76a66253 j_mayer
{
1804 d72a19f7 aurel32
    do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1805 76a66253 j_mayer
}
1806 76a66253 j_mayer
#endif
1807 76a66253 j_mayer
1808 76a66253 j_mayer
/*****************************************************************************/
1809 76a66253 j_mayer
/* 602 specific instructions */
1810 76a66253 j_mayer
/* mfrom is the most crazy instruction ever seen, imho ! */
1811 76a66253 j_mayer
/* Real implementation uses a ROM table. Do the same */
1812 5e9ae189 aurel32
/* Extremly decomposed:
1813 5e9ae189 aurel32
 *                      -arg / 256
1814 5e9ae189 aurel32
 * return 256 * log10(10           + 1.0) + 0.5
1815 5e9ae189 aurel32
 */
1816 db9a16a7 aurel32
#if !defined (CONFIG_USER_ONLY)
1817 cf02a65c aurel32
target_ulong helper_602_mfrom (target_ulong arg)
1818 76a66253 j_mayer
{
1819 cf02a65c aurel32
    if (likely(arg < 602)) {
1820 76a66253 j_mayer
#include "mfrom_table.c"
1821 45d827d2 aurel32
        return mfrom_ROM_table[arg];
1822 76a66253 j_mayer
    } else {
1823 cf02a65c aurel32
        return 0;
1824 76a66253 j_mayer
    }
1825 76a66253 j_mayer
}
1826 db9a16a7 aurel32
#endif
1827 76a66253 j_mayer
1828 76a66253 j_mayer
/*****************************************************************************/
1829 76a66253 j_mayer
/* Embedded PowerPC specific helpers */
1830 76a66253 j_mayer
1831 a750fc0b j_mayer
/* XXX: to be improved to check access rights when in user-mode */
1832 06dca6a7 aurel32
target_ulong helper_load_dcr (target_ulong dcrn)
1833 a750fc0b j_mayer
{
1834 06dca6a7 aurel32
    target_ulong val = 0;
1835 a750fc0b j_mayer
1836 a750fc0b j_mayer
    if (unlikely(env->dcr_env == NULL)) {
1837 93fcfe39 aliguori
        qemu_log("No DCR environment\n");
1838 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1839 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1840 06dca6a7 aurel32
    } else if (unlikely(ppc_dcr_read(env->dcr_env, dcrn, &val) != 0)) {
1841 93fcfe39 aliguori
        qemu_log("DCR read error %d %03x\n", (int)dcrn, (int)dcrn);
1842 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1843 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1844 a750fc0b j_mayer
    }
1845 06dca6a7 aurel32
    return val;
1846 a750fc0b j_mayer
}
1847 a750fc0b j_mayer
1848 06dca6a7 aurel32
void helper_store_dcr (target_ulong dcrn, target_ulong val)
1849 a750fc0b j_mayer
{
1850 a750fc0b j_mayer
    if (unlikely(env->dcr_env == NULL)) {
1851 93fcfe39 aliguori
        qemu_log("No DCR environment\n");
1852 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1853 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1854 06dca6a7 aurel32
    } else if (unlikely(ppc_dcr_write(env->dcr_env, dcrn, val) != 0)) {
1855 93fcfe39 aliguori
        qemu_log("DCR write error %d %03x\n", (int)dcrn, (int)dcrn);
1856 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1857 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1858 a750fc0b j_mayer
    }
1859 a750fc0b j_mayer
}
1860 a750fc0b j_mayer
1861 76a66253 j_mayer
#if !defined(CONFIG_USER_ONLY)
1862 d72a19f7 aurel32
void helper_40x_rfci (void)
1863 76a66253 j_mayer
{
1864 d72a19f7 aurel32
    do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1865 d72a19f7 aurel32
           ~((target_ulong)0xFFFF0000), 0);
1866 a42bd6cc j_mayer
}
1867 a42bd6cc j_mayer
1868 d72a19f7 aurel32
void helper_rfci (void)
1869 a42bd6cc j_mayer
{
1870 d72a19f7 aurel32
    do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1871 d72a19f7 aurel32
           ~((target_ulong)0x3FFF0000), 0);
1872 a42bd6cc j_mayer
}
1873 a42bd6cc j_mayer
1874 d72a19f7 aurel32
void helper_rfdi (void)
1875 a42bd6cc j_mayer
{
1876 d72a19f7 aurel32
    do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1877 d72a19f7 aurel32
           ~((target_ulong)0x3FFF0000), 0);
1878 a42bd6cc j_mayer
}
1879 a42bd6cc j_mayer
1880 d72a19f7 aurel32
void helper_rfmci (void)
1881 a42bd6cc j_mayer
{
1882 d72a19f7 aurel32
    do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1883 d72a19f7 aurel32
           ~((target_ulong)0x3FFF0000), 0);
1884 76a66253 j_mayer
}
1885 76a66253 j_mayer
#endif
1886 76a66253 j_mayer
1887 76a66253 j_mayer
/* 440 specific */
1888 ef0d51af aurel32
target_ulong helper_dlmzb (target_ulong high, target_ulong low, uint32_t update_Rc)
1889 76a66253 j_mayer
{
1890 76a66253 j_mayer
    target_ulong mask;
1891 76a66253 j_mayer
    int i;
1892 76a66253 j_mayer
1893 76a66253 j_mayer
    i = 1;
1894 76a66253 j_mayer
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1895 ef0d51af aurel32
        if ((high & mask) == 0) {
1896 ef0d51af aurel32
            if (update_Rc) {
1897 ef0d51af aurel32
                env->crf[0] = 0x4;
1898 ef0d51af aurel32
            }
1899 76a66253 j_mayer
            goto done;
1900 ef0d51af aurel32
        }
1901 76a66253 j_mayer
        i++;
1902 76a66253 j_mayer
    }
1903 76a66253 j_mayer
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1904 ef0d51af aurel32
        if ((low & mask) == 0) {
1905 ef0d51af aurel32
            if (update_Rc) {
1906 ef0d51af aurel32
                env->crf[0] = 0x8;
1907 ef0d51af aurel32
            }
1908 ef0d51af aurel32
            goto done;
1909 ef0d51af aurel32
        }
1910 76a66253 j_mayer
        i++;
1911 76a66253 j_mayer
    }
1912 ef0d51af aurel32
    if (update_Rc) {
1913 ef0d51af aurel32
        env->crf[0] = 0x2;
1914 ef0d51af aurel32
    }
1915 76a66253 j_mayer
 done:
1916 ef0d51af aurel32
    env->xer = (env->xer & ~0x7F) | i;
1917 ef0d51af aurel32
    if (update_Rc) {
1918 ef0d51af aurel32
        env->crf[0] |= xer_so;
1919 ef0d51af aurel32
    }
1920 ef0d51af aurel32
    return i;
1921 fdabc366 bellard
}
1922 fdabc366 bellard
1923 1c97856d aurel32
/*****************************************************************************/
1924 d6a46fe8 aurel32
/* Altivec extension helpers */
1925 d6a46fe8 aurel32
#if defined(WORDS_BIGENDIAN)
1926 d6a46fe8 aurel32
#define HI_IDX 0
1927 d6a46fe8 aurel32
#define LO_IDX 1
1928 d6a46fe8 aurel32
#else
1929 d6a46fe8 aurel32
#define HI_IDX 1
1930 d6a46fe8 aurel32
#define LO_IDX 0
1931 d6a46fe8 aurel32
#endif
1932 d6a46fe8 aurel32
1933 d6a46fe8 aurel32
#if defined(WORDS_BIGENDIAN)
1934 d6a46fe8 aurel32
#define VECTOR_FOR_INORDER_I(index, element)            \
1935 d6a46fe8 aurel32
    for (index = 0; index < ARRAY_SIZE(r->element); index++)
1936 d6a46fe8 aurel32
#else
1937 d6a46fe8 aurel32
#define VECTOR_FOR_INORDER_I(index, element)            \
1938 d6a46fe8 aurel32
  for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
1939 d6a46fe8 aurel32
#endif
1940 d6a46fe8 aurel32
1941 34ba2857 aurel32
/* If X is a NaN, store the corresponding QNaN into RESULT.  Otherwise,
1942 34ba2857 aurel32
 * execute the following block.  */
1943 34ba2857 aurel32
#define DO_HANDLE_NAN(result, x)                \
1944 34ba2857 aurel32
    if (float32_is_nan(x) || float32_is_signaling_nan(x)) {     \
1945 34ba2857 aurel32
        CPU_FloatU __f;                                         \
1946 34ba2857 aurel32
        __f.f = x;                                              \
1947 34ba2857 aurel32
        __f.l = __f.l | (1 << 22);  /* Set QNaN bit. */         \
1948 34ba2857 aurel32
        result = __f.f;                                         \
1949 34ba2857 aurel32
    } else
1950 34ba2857 aurel32
1951 34ba2857 aurel32
#define HANDLE_NAN1(result, x)                  \
1952 34ba2857 aurel32
    DO_HANDLE_NAN(result, x)
1953 34ba2857 aurel32
#define HANDLE_NAN2(result, x, y)               \
1954 34ba2857 aurel32
    DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y)
1955 34ba2857 aurel32
#define HANDLE_NAN3(result, x, y, z)            \
1956 34ba2857 aurel32
    DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z)
1957 34ba2857 aurel32
1958 00d3b8f5 aurel32
/* Saturating arithmetic helpers.  */
1959 00d3b8f5 aurel32
#define SATCVT(from, to, from_type, to_type, min, max, use_min, use_max) \
1960 00d3b8f5 aurel32
    static always_inline to_type cvt##from##to (from_type x, int *sat)  \
1961 00d3b8f5 aurel32
    {                                                                   \
1962 00d3b8f5 aurel32
        to_type r;                                                      \
1963 00d3b8f5 aurel32
        if (use_min && x < min) {                                       \
1964 00d3b8f5 aurel32
            r = min;                                                    \
1965 00d3b8f5 aurel32
            *sat = 1;                                                   \
1966 00d3b8f5 aurel32
        } else if (use_max && x > max) {                                \
1967 00d3b8f5 aurel32
            r = max;                                                    \
1968 00d3b8f5 aurel32
            *sat = 1;                                                   \
1969 00d3b8f5 aurel32
        } else {                                                        \
1970 00d3b8f5 aurel32
            r = x;                                                      \
1971 00d3b8f5 aurel32
        }                                                               \
1972 00d3b8f5 aurel32
        return r;                                                       \
1973 00d3b8f5 aurel32
    }
1974 00d3b8f5 aurel32
SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX, 1, 1)
1975 00d3b8f5 aurel32
SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX, 1, 1)
1976 00d3b8f5 aurel32
SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX, 1, 1)
1977 00d3b8f5 aurel32
SATCVT(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX, 0, 1)
1978 00d3b8f5 aurel32
SATCVT(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX, 0, 1)
1979 00d3b8f5 aurel32
SATCVT(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX, 0, 1)
1980 00d3b8f5 aurel32
SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX, 1, 1)
1981 00d3b8f5 aurel32
SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX, 1, 1)
1982 00d3b8f5 aurel32
SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX, 1, 1)
1983 00d3b8f5 aurel32
#undef SATCVT
1984 00d3b8f5 aurel32
1985 cbfb6ae9 aurel32
#define LVE(name, access, swap, element)                        \
1986 cbfb6ae9 aurel32
    void helper_##name (ppc_avr_t *r, target_ulong addr)        \
1987 cbfb6ae9 aurel32
    {                                                           \
1988 cbfb6ae9 aurel32
        size_t n_elems = ARRAY_SIZE(r->element);                \
1989 cbfb6ae9 aurel32
        int adjust = HI_IDX*(n_elems-1);                        \
1990 cbfb6ae9 aurel32
        int sh = sizeof(r->element[0]) >> 1;                    \
1991 cbfb6ae9 aurel32
        int index = (addr & 0xf) >> sh;                         \
1992 cbfb6ae9 aurel32
        if(msr_le) {                                            \
1993 cbfb6ae9 aurel32
            r->element[LO_IDX ? index : (adjust - index)] = swap(access(addr)); \
1994 cbfb6ae9 aurel32
        } else {                                                        \
1995 cbfb6ae9 aurel32
            r->element[LO_IDX ? index : (adjust - index)] = access(addr); \
1996 cbfb6ae9 aurel32
        }                                                               \
1997 cbfb6ae9 aurel32
    }
1998 cbfb6ae9 aurel32
#define I(x) (x)
1999 cbfb6ae9 aurel32
LVE(lvebx, ldub, I, u8)
2000 cbfb6ae9 aurel32
LVE(lvehx, lduw, bswap16, u16)
2001 cbfb6ae9 aurel32
LVE(lvewx, ldl, bswap32, u32)
2002 cbfb6ae9 aurel32
#undef I
2003 cbfb6ae9 aurel32
#undef LVE
2004 cbfb6ae9 aurel32
2005 bf8d8ded aurel32
void helper_lvsl (ppc_avr_t *r, target_ulong sh)
2006 bf8d8ded aurel32
{
2007 bf8d8ded aurel32
    int i, j = (sh & 0xf);
2008 bf8d8ded aurel32
2009 bf8d8ded aurel32
    VECTOR_FOR_INORDER_I (i, u8) {
2010 bf8d8ded aurel32
        r->u8[i] = j++;
2011 bf8d8ded aurel32
    }
2012 bf8d8ded aurel32
}
2013 bf8d8ded aurel32
2014 bf8d8ded aurel32
void helper_lvsr (ppc_avr_t *r, target_ulong sh)
2015 bf8d8ded aurel32
{
2016 bf8d8ded aurel32
    int i, j = 0x10 - (sh & 0xf);
2017 bf8d8ded aurel32
2018 bf8d8ded aurel32
    VECTOR_FOR_INORDER_I (i, u8) {
2019 bf8d8ded aurel32
        r->u8[i] = j++;
2020 bf8d8ded aurel32
    }
2021 bf8d8ded aurel32
}
2022 bf8d8ded aurel32
2023 cbfb6ae9 aurel32
#define STVE(name, access, swap, element)                       \
2024 cbfb6ae9 aurel32
    void helper_##name (ppc_avr_t *r, target_ulong addr)        \
2025 cbfb6ae9 aurel32
    {                                                           \
2026 cbfb6ae9 aurel32
        size_t n_elems = ARRAY_SIZE(r->element);                \
2027 cbfb6ae9 aurel32
        int adjust = HI_IDX*(n_elems-1);                        \
2028 cbfb6ae9 aurel32
        int sh = sizeof(r->element[0]) >> 1;                    \
2029 cbfb6ae9 aurel32
        int index = (addr & 0xf) >> sh;                         \
2030 cbfb6ae9 aurel32
        if(msr_le) {                                            \
2031 cbfb6ae9 aurel32
            access(addr, swap(r->element[LO_IDX ? index : (adjust - index)])); \
2032 cbfb6ae9 aurel32
        } else {                                                        \
2033 cbfb6ae9 aurel32
            access(addr, r->element[LO_IDX ? index : (adjust - index)]); \
2034 cbfb6ae9 aurel32
        }                                                               \
2035 cbfb6ae9 aurel32
    }
2036 cbfb6ae9 aurel32
#define I(x) (x)
2037 cbfb6ae9 aurel32
STVE(stvebx, stb, I, u8)
2038 cbfb6ae9 aurel32
STVE(stvehx, stw, bswap16, u16)
2039 cbfb6ae9 aurel32
STVE(stvewx, stl, bswap32, u32)
2040 cbfb6ae9 aurel32
#undef I
2041 cbfb6ae9 aurel32
#undef LVE
2042 cbfb6ae9 aurel32
2043 6e87b7c7 aurel32
void helper_mtvscr (ppc_avr_t *r)
2044 6e87b7c7 aurel32
{
2045 6e87b7c7 aurel32
#if defined(WORDS_BIGENDIAN)
2046 6e87b7c7 aurel32
    env->vscr = r->u32[3];
2047 6e87b7c7 aurel32
#else
2048 6e87b7c7 aurel32
    env->vscr = r->u32[0];
2049 6e87b7c7 aurel32
#endif
2050 6e87b7c7 aurel32
    set_flush_to_zero(vscr_nj, &env->vec_status);
2051 6e87b7c7 aurel32
}
2052 6e87b7c7 aurel32
2053 e343da72 aurel32
void helper_vaddcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2054 e343da72 aurel32
{
2055 e343da72 aurel32
    int i;
2056 e343da72 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2057 e343da72 aurel32
        r->u32[i] = ~a->u32[i] < b->u32[i];
2058 e343da72 aurel32
    }
2059 e343da72 aurel32
}
2060 e343da72 aurel32
2061 7872c51c aurel32
#define VARITH_DO(name, op, element)        \
2062 7872c51c aurel32
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)          \
2063 7872c51c aurel32
{                                                                       \
2064 7872c51c aurel32
    int i;                                                              \
2065 7872c51c aurel32
    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                      \
2066 7872c51c aurel32
        r->element[i] = a->element[i] op b->element[i];                 \
2067 7872c51c aurel32
    }                                                                   \
2068 7872c51c aurel32
}
2069 7872c51c aurel32
#define VARITH(suffix, element)                  \
2070 7872c51c aurel32
  VARITH_DO(add##suffix, +, element)             \
2071 7872c51c aurel32
  VARITH_DO(sub##suffix, -, element)
2072 7872c51c aurel32
VARITH(ubm, u8)
2073 7872c51c aurel32
VARITH(uhm, u16)
2074 7872c51c aurel32
VARITH(uwm, u32)
2075 7872c51c aurel32
#undef VARITH_DO
2076 7872c51c aurel32
#undef VARITH
2077 7872c51c aurel32
2078 56fdd213 aurel32
#define VARITHFP(suffix, func)                                          \
2079 56fdd213 aurel32
    void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
2080 56fdd213 aurel32
    {                                                                   \
2081 56fdd213 aurel32
        int i;                                                          \
2082 56fdd213 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2083 56fdd213 aurel32
            HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
2084 56fdd213 aurel32
                r->f[i] = func(a->f[i], b->f[i], &env->vec_status);     \
2085 56fdd213 aurel32
            }                                                           \
2086 56fdd213 aurel32
        }                                                               \
2087 56fdd213 aurel32
    }
2088 56fdd213 aurel32
VARITHFP(addfp, float32_add)
2089 56fdd213 aurel32
VARITHFP(subfp, float32_sub)
2090 56fdd213 aurel32
#undef VARITHFP
2091 56fdd213 aurel32
2092 5ab09f33 aurel32
#define VARITHSAT_CASE(type, op, cvt, element)                          \
2093 5ab09f33 aurel32
    {                                                                   \
2094 5ab09f33 aurel32
        type result = (type)a->element[i] op (type)b->element[i];       \
2095 5ab09f33 aurel32
        r->element[i] = cvt(result, &sat);                              \
2096 5ab09f33 aurel32
    }
2097 5ab09f33 aurel32
2098 5ab09f33 aurel32
#define VARITHSAT_DO(name, op, optype, cvt, element)                    \
2099 5ab09f33 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2100 5ab09f33 aurel32
    {                                                                   \
2101 5ab09f33 aurel32
        int sat = 0;                                                    \
2102 5ab09f33 aurel32
        int i;                                                          \
2103 5ab09f33 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2104 5ab09f33 aurel32
            switch (sizeof(r->element[0])) {                            \
2105 5ab09f33 aurel32
            case 1: VARITHSAT_CASE(optype, op, cvt, element); break;    \
2106 5ab09f33 aurel32
            case 2: VARITHSAT_CASE(optype, op, cvt, element); break;    \
2107 5ab09f33 aurel32
            case 4: VARITHSAT_CASE(optype, op, cvt, element); break;    \
2108 5ab09f33 aurel32
            }                                                           \
2109 5ab09f33 aurel32
        }                                                               \
2110 5ab09f33 aurel32
        if (sat) {                                                      \
2111 5ab09f33 aurel32
            env->vscr |= (1 << VSCR_SAT);                               \
2112 5ab09f33 aurel32
        }                                                               \
2113 5ab09f33 aurel32
    }
2114 5ab09f33 aurel32
#define VARITHSAT_SIGNED(suffix, element, optype, cvt)        \
2115 5ab09f33 aurel32
    VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element)    \
2116 5ab09f33 aurel32
    VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
2117 5ab09f33 aurel32
#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt)       \
2118 5ab09f33 aurel32
    VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element)     \
2119 5ab09f33 aurel32
    VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
2120 5ab09f33 aurel32
VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
2121 5ab09f33 aurel32
VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
2122 5ab09f33 aurel32
VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
2123 5ab09f33 aurel32
VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
2124 5ab09f33 aurel32
VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
2125 5ab09f33 aurel32
VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
2126 5ab09f33 aurel32
#undef VARITHSAT_CASE
2127 5ab09f33 aurel32
#undef VARITHSAT_DO
2128 5ab09f33 aurel32
#undef VARITHSAT_SIGNED
2129 5ab09f33 aurel32
#undef VARITHSAT_UNSIGNED
2130 5ab09f33 aurel32
2131 fab3cbe9 aurel32
#define VAVG_DO(name, element, etype)                                   \
2132 fab3cbe9 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2133 fab3cbe9 aurel32
    {                                                                   \
2134 fab3cbe9 aurel32
        int i;                                                          \
2135 fab3cbe9 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2136 fab3cbe9 aurel32
            etype x = (etype)a->element[i] + (etype)b->element[i] + 1;  \
2137 fab3cbe9 aurel32
            r->element[i] = x >> 1;                                     \
2138 fab3cbe9 aurel32
        }                                                               \
2139 fab3cbe9 aurel32
    }
2140 fab3cbe9 aurel32
2141 fab3cbe9 aurel32
#define VAVG(type, signed_element, signed_type, unsigned_element, unsigned_type) \
2142 fab3cbe9 aurel32
    VAVG_DO(avgs##type, signed_element, signed_type)                    \
2143 fab3cbe9 aurel32
    VAVG_DO(avgu##type, unsigned_element, unsigned_type)
2144 fab3cbe9 aurel32
VAVG(b, s8, int16_t, u8, uint16_t)
2145 fab3cbe9 aurel32
VAVG(h, s16, int32_t, u16, uint32_t)
2146 fab3cbe9 aurel32
VAVG(w, s32, int64_t, u32, uint64_t)
2147 fab3cbe9 aurel32
#undef VAVG_DO
2148 fab3cbe9 aurel32
#undef VAVG
2149 fab3cbe9 aurel32
2150 e140632e aurel32
#define VCF(suffix, cvt, element)                                       \
2151 e140632e aurel32
    void helper_vcf##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim)  \
2152 e140632e aurel32
    {                                                                   \
2153 e140632e aurel32
        int i;                                                          \
2154 e140632e aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2155 e140632e aurel32
            float32 t = cvt(b->element[i], &env->vec_status);           \
2156 e140632e aurel32
            r->f[i] = float32_scalbn (t, -uim, &env->vec_status);       \
2157 e140632e aurel32
        }                                                               \
2158 e140632e aurel32
    }
2159 e140632e aurel32
VCF(ux, uint32_to_float32, u32)
2160 e140632e aurel32
VCF(sx, int32_to_float32, s32)
2161 e140632e aurel32
#undef VCF
2162 e140632e aurel32
2163 1add6e23 aurel32
#define VCMP_DO(suffix, compare, element, record)                       \
2164 1add6e23 aurel32
    void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2165 1add6e23 aurel32
    {                                                                   \
2166 1add6e23 aurel32
        uint32_t ones = (uint32_t)-1;                                   \
2167 1add6e23 aurel32
        uint32_t all = ones;                                            \
2168 1add6e23 aurel32
        uint32_t none = 0;                                              \
2169 1add6e23 aurel32
        int i;                                                          \
2170 1add6e23 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2171 1add6e23 aurel32
            uint32_t result = (a->element[i] compare b->element[i] ? ones : 0x0); \
2172 1add6e23 aurel32
            switch (sizeof (a->element[0])) {                           \
2173 1add6e23 aurel32
            case 4: r->u32[i] = result; break;                          \
2174 1add6e23 aurel32
            case 2: r->u16[i] = result; break;                          \
2175 1add6e23 aurel32
            case 1: r->u8[i] = result; break;                           \
2176 1add6e23 aurel32
            }                                                           \
2177 1add6e23 aurel32
            all &= result;                                              \
2178 1add6e23 aurel32
            none |= result;                                             \
2179 1add6e23 aurel32
        }                                                               \
2180 1add6e23 aurel32
        if (record) {                                                   \
2181 1add6e23 aurel32
            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
2182 1add6e23 aurel32
        }                                                               \
2183 1add6e23 aurel32
    }
2184 1add6e23 aurel32
#define VCMP(suffix, compare, element)          \
2185 1add6e23 aurel32
    VCMP_DO(suffix, compare, element, 0)        \
2186 1add6e23 aurel32
    VCMP_DO(suffix##_dot, compare, element, 1)
2187 1add6e23 aurel32
VCMP(equb, ==, u8)
2188 1add6e23 aurel32
VCMP(equh, ==, u16)
2189 1add6e23 aurel32
VCMP(equw, ==, u32)
2190 1add6e23 aurel32
VCMP(gtub, >, u8)
2191 1add6e23 aurel32
VCMP(gtuh, >, u16)
2192 1add6e23 aurel32
VCMP(gtuw, >, u32)
2193 1add6e23 aurel32
VCMP(gtsb, >, s8)
2194 1add6e23 aurel32
VCMP(gtsh, >, s16)
2195 1add6e23 aurel32
VCMP(gtsw, >, s32)
2196 1add6e23 aurel32
#undef VCMP_DO
2197 1add6e23 aurel32
#undef VCMP
2198 1add6e23 aurel32
2199 819ca121 aurel32
#define VCMPFP_DO(suffix, compare, order, record)                       \
2200 819ca121 aurel32
    void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2201 819ca121 aurel32
    {                                                                   \
2202 819ca121 aurel32
        uint32_t ones = (uint32_t)-1;                                   \
2203 819ca121 aurel32
        uint32_t all = ones;                                            \
2204 819ca121 aurel32
        uint32_t none = 0;                                              \
2205 819ca121 aurel32
        int i;                                                          \
2206 819ca121 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2207 819ca121 aurel32
            uint32_t result;                                            \
2208 819ca121 aurel32
            int rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status); \
2209 819ca121 aurel32
            if (rel == float_relation_unordered) {                      \
2210 819ca121 aurel32
                result = 0;                                             \
2211 819ca121 aurel32
            } else if (rel compare order) {                             \
2212 819ca121 aurel32
                result = ones;                                          \
2213 819ca121 aurel32
            } else {                                                    \
2214 819ca121 aurel32
                result = 0;                                             \
2215 819ca121 aurel32
            }                                                           \
2216 819ca121 aurel32
            r->u32[i] = result;                                         \
2217 819ca121 aurel32
            all &= result;                                              \
2218 819ca121 aurel32
            none |= result;                                             \
2219 819ca121 aurel32
        }                                                               \
2220 819ca121 aurel32
        if (record) {                                                   \
2221 819ca121 aurel32
            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
2222 819ca121 aurel32
        }                                                               \
2223 819ca121 aurel32
    }
2224 819ca121 aurel32
#define VCMPFP(suffix, compare, order)           \
2225 819ca121 aurel32
    VCMPFP_DO(suffix, compare, order, 0)         \
2226 819ca121 aurel32
    VCMPFP_DO(suffix##_dot, compare, order, 1)
2227 819ca121 aurel32
VCMPFP(eqfp, ==, float_relation_equal)
2228 819ca121 aurel32
VCMPFP(gefp, !=, float_relation_less)
2229 819ca121 aurel32
VCMPFP(gtfp, ==, float_relation_greater)
2230 819ca121 aurel32
#undef VCMPFP_DO
2231 819ca121 aurel32
#undef VCMPFP
2232 819ca121 aurel32
2233 819ca121 aurel32
static always_inline void vcmpbfp_internal (ppc_avr_t *r, ppc_avr_t *a,
2234 819ca121 aurel32
                                            ppc_avr_t *b, int record)
2235 819ca121 aurel32
{
2236 819ca121 aurel32
    int i;
2237 819ca121 aurel32
    int all_in = 0;
2238 819ca121 aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2239 819ca121 aurel32
        int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
2240 819ca121 aurel32
        if (le_rel == float_relation_unordered) {
2241 819ca121 aurel32
            r->u32[i] = 0xc0000000;
2242 819ca121 aurel32
            /* ALL_IN does not need to be updated here.  */
2243 819ca121 aurel32
        } else {
2244 819ca121 aurel32
            float32 bneg = float32_chs(b->f[i]);
2245 819ca121 aurel32
            int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
2246 819ca121 aurel32
            int le = le_rel != float_relation_greater;
2247 819ca121 aurel32
            int ge = ge_rel != float_relation_less;
2248 819ca121 aurel32
            r->u32[i] = ((!le) << 31) | ((!ge) << 30);
2249 819ca121 aurel32
            all_in |= (!le | !ge);
2250 819ca121 aurel32
        }
2251 819ca121 aurel32
    }
2252 819ca121 aurel32
    if (record) {
2253 819ca121 aurel32
        env->crf[6] = (all_in == 0) << 1;
2254 819ca121 aurel32
    }
2255 819ca121 aurel32
}
2256 819ca121 aurel32
2257 819ca121 aurel32
void helper_vcmpbfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2258 819ca121 aurel32
{
2259 819ca121 aurel32
    vcmpbfp_internal(r, a, b, 0);
2260 819ca121 aurel32
}
2261 819ca121 aurel32
2262 819ca121 aurel32
void helper_vcmpbfp_dot (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2263 819ca121 aurel32
{
2264 819ca121 aurel32
    vcmpbfp_internal(r, a, b, 1);
2265 819ca121 aurel32
}
2266 819ca121 aurel32
2267 875b31db aurel32
#define VCT(suffix, satcvt, element)                                    \
2268 875b31db aurel32
    void helper_vct##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim)  \
2269 875b31db aurel32
    {                                                                   \
2270 875b31db aurel32
        int i;                                                          \
2271 875b31db aurel32
        int sat = 0;                                                    \
2272 875b31db aurel32
        float_status s = env->vec_status;                               \
2273 875b31db aurel32
        set_float_rounding_mode(float_round_to_zero, &s);               \
2274 875b31db aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2275 875b31db aurel32
            if (float32_is_nan(b->f[i]) ||                              \
2276 875b31db aurel32
                float32_is_signaling_nan(b->f[i])) {                    \
2277 875b31db aurel32
                r->element[i] = 0;                                      \
2278 875b31db aurel32
            } else {                                                    \
2279 875b31db aurel32
                float64 t = float32_to_float64(b->f[i], &s);            \
2280 875b31db aurel32
                int64_t j;                                              \
2281 875b31db aurel32
                t = float64_scalbn(t, uim, &s);                         \
2282 875b31db aurel32
                j = float64_to_int64(t, &s);                            \
2283 875b31db aurel32
                r->element[i] = satcvt(j, &sat);                        \
2284 875b31db aurel32
            }                                                           \
2285 875b31db aurel32
        }                                                               \
2286 875b31db aurel32
        if (sat) {                                                      \
2287 875b31db aurel32
            env->vscr |= (1 << VSCR_SAT);                               \
2288 875b31db aurel32
        }                                                               \
2289 875b31db aurel32
    }
2290 875b31db aurel32
VCT(uxs, cvtsduw, u32)
2291 875b31db aurel32
VCT(sxs, cvtsdsw, s32)
2292 875b31db aurel32
#undef VCT
2293 875b31db aurel32
2294 35cf7c7e aurel32
void helper_vmaddfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2295 35cf7c7e aurel32
{
2296 35cf7c7e aurel32
    int i;
2297 35cf7c7e aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2298 35cf7c7e aurel32
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2299 35cf7c7e aurel32
            /* Need to do the computation in higher precision and round
2300 35cf7c7e aurel32
             * once at the end.  */
2301 35cf7c7e aurel32
            float64 af, bf, cf, t;
2302 35cf7c7e aurel32
            af = float32_to_float64(a->f[i], &env->vec_status);
2303 35cf7c7e aurel32
            bf = float32_to_float64(b->f[i], &env->vec_status);
2304 35cf7c7e aurel32
            cf = float32_to_float64(c->f[i], &env->vec_status);
2305 35cf7c7e aurel32
            t = float64_mul(af, cf, &env->vec_status);
2306 35cf7c7e aurel32
            t = float64_add(t, bf, &env->vec_status);
2307 35cf7c7e aurel32
            r->f[i] = float64_to_float32(t, &env->vec_status);
2308 35cf7c7e aurel32
        }
2309 35cf7c7e aurel32
    }
2310 35cf7c7e aurel32
}
2311 35cf7c7e aurel32
2312 b161ae27 aurel32
void helper_vmhaddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2313 b161ae27 aurel32
{
2314 b161ae27 aurel32
    int sat = 0;
2315 b161ae27 aurel32
    int i;
2316 b161ae27 aurel32
2317 b161ae27 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2318 b161ae27 aurel32
        int32_t prod = a->s16[i] * b->s16[i];
2319 b161ae27 aurel32
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2320 b161ae27 aurel32
        r->s16[i] = cvtswsh (t, &sat);
2321 b161ae27 aurel32
    }
2322 b161ae27 aurel32
2323 b161ae27 aurel32
    if (sat) {
2324 b161ae27 aurel32
        env->vscr |= (1 << VSCR_SAT);
2325 b161ae27 aurel32
    }
2326 b161ae27 aurel32
}
2327 b161ae27 aurel32
2328 b161ae27 aurel32
void helper_vmhraddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2329 b161ae27 aurel32
{
2330 b161ae27 aurel32
    int sat = 0;
2331 b161ae27 aurel32
    int i;
2332 b161ae27 aurel32
2333 b161ae27 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2334 b161ae27 aurel32
        int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
2335 b161ae27 aurel32
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2336 b161ae27 aurel32
        r->s16[i] = cvtswsh (t, &sat);
2337 b161ae27 aurel32
    }
2338 b161ae27 aurel32
2339 b161ae27 aurel32
    if (sat) {
2340 b161ae27 aurel32
        env->vscr |= (1 << VSCR_SAT);
2341 b161ae27 aurel32
    }
2342 b161ae27 aurel32
}
2343 b161ae27 aurel32
2344 e4039339 aurel32
#define VMINMAX_DO(name, compare, element)                              \
2345 e4039339 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2346 e4039339 aurel32
    {                                                                   \
2347 e4039339 aurel32
        int i;                                                          \
2348 e4039339 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2349 e4039339 aurel32
            if (a->element[i] compare b->element[i]) {                  \
2350 e4039339 aurel32
                r->element[i] = b->element[i];                          \
2351 e4039339 aurel32
            } else {                                                    \
2352 e4039339 aurel32
                r->element[i] = a->element[i];                          \
2353 e4039339 aurel32
            }                                                           \
2354 e4039339 aurel32
        }                                                               \
2355 e4039339 aurel32
    }
2356 e4039339 aurel32
#define VMINMAX(suffix, element)                \
2357 e4039339 aurel32
  VMINMAX_DO(min##suffix, >, element)           \
2358 e4039339 aurel32
  VMINMAX_DO(max##suffix, <, element)
2359 e4039339 aurel32
VMINMAX(sb, s8)
2360 e4039339 aurel32
VMINMAX(sh, s16)
2361 e4039339 aurel32
VMINMAX(sw, s32)
2362 e4039339 aurel32
VMINMAX(ub, u8)
2363 e4039339 aurel32
VMINMAX(uh, u16)
2364 e4039339 aurel32
VMINMAX(uw, u32)
2365 e4039339 aurel32
#undef VMINMAX_DO
2366 e4039339 aurel32
#undef VMINMAX
2367 e4039339 aurel32
2368 1536ff64 aurel32
#define VMINMAXFP(suffix, rT, rF)                                       \
2369 1536ff64 aurel32
    void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
2370 1536ff64 aurel32
    {                                                                   \
2371 1536ff64 aurel32
        int i;                                                          \
2372 1536ff64 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2373 1536ff64 aurel32
            HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
2374 1536ff64 aurel32
                if (float32_lt_quiet(a->f[i], b->f[i], &env->vec_status)) { \
2375 1536ff64 aurel32
                    r->f[i] = rT->f[i];                                 \
2376 1536ff64 aurel32
                } else {                                                \
2377 1536ff64 aurel32
                    r->f[i] = rF->f[i];                                 \
2378 1536ff64 aurel32
                }                                                       \
2379 1536ff64 aurel32
            }                                                           \
2380 1536ff64 aurel32
        }                                                               \
2381 1536ff64 aurel32
    }
2382 1536ff64 aurel32
VMINMAXFP(minfp, a, b)
2383 1536ff64 aurel32
VMINMAXFP(maxfp, b, a)
2384 1536ff64 aurel32
#undef VMINMAXFP
2385 1536ff64 aurel32
2386 bcd2ee23 aurel32
void helper_vmladduhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2387 bcd2ee23 aurel32
{
2388 bcd2ee23 aurel32
    int i;
2389 bcd2ee23 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2390 bcd2ee23 aurel32
        int32_t prod = a->s16[i] * b->s16[i];
2391 bcd2ee23 aurel32
        r->s16[i] = (int16_t) (prod + c->s16[i]);
2392 bcd2ee23 aurel32
    }
2393 bcd2ee23 aurel32
}
2394 bcd2ee23 aurel32
2395 3b430048 aurel32
#define VMRG_DO(name, element, highp)                                   \
2396 3b430048 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2397 3b430048 aurel32
    {                                                                   \
2398 3b430048 aurel32
        ppc_avr_t result;                                               \
2399 3b430048 aurel32
        int i;                                                          \
2400 3b430048 aurel32
        size_t n_elems = ARRAY_SIZE(r->element);                        \
2401 3b430048 aurel32
        for (i = 0; i < n_elems/2; i++) {                               \
2402 3b430048 aurel32
            if (highp) {                                                \
2403 3b430048 aurel32
                result.element[i*2+HI_IDX] = a->element[i];             \
2404 3b430048 aurel32
                result.element[i*2+LO_IDX] = b->element[i];             \
2405 3b430048 aurel32
            } else {                                                    \
2406 3b430048 aurel32
                result.element[n_elems - i*2 - (1+HI_IDX)] = b->element[n_elems - i - 1]; \
2407 3b430048 aurel32
                result.element[n_elems - i*2 - (1+LO_IDX)] = a->element[n_elems - i - 1]; \
2408 3b430048 aurel32
            }                                                           \
2409 3b430048 aurel32
        }                                                               \
2410 3b430048 aurel32
        *r = result;                                                    \
2411 3b430048 aurel32
    }
2412 3b430048 aurel32
#if defined(WORDS_BIGENDIAN)
2413 3b430048 aurel32
#define MRGHI 0
2414 b392e756 aurel32
#define MRGLO 1
2415 3b430048 aurel32
#else
2416 3b430048 aurel32
#define MRGHI 1
2417 3b430048 aurel32
#define MRGLO 0
2418 3b430048 aurel32
#endif
2419 3b430048 aurel32
#define VMRG(suffix, element)                   \
2420 3b430048 aurel32
  VMRG_DO(mrgl##suffix, element, MRGHI)         \
2421 3b430048 aurel32
  VMRG_DO(mrgh##suffix, element, MRGLO)
2422 3b430048 aurel32
VMRG(b, u8)
2423 3b430048 aurel32
VMRG(h, u16)
2424 3b430048 aurel32
VMRG(w, u32)
2425 3b430048 aurel32
#undef VMRG_DO
2426 3b430048 aurel32
#undef VMRG
2427 3b430048 aurel32
#undef MRGHI
2428 3b430048 aurel32
#undef MRGLO
2429 3b430048 aurel32
2430 b04ae981 aurel32
void helper_vmsummbm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2431 b04ae981 aurel32
{
2432 b04ae981 aurel32
    int32_t prod[16];
2433 b04ae981 aurel32
    int i;
2434 b04ae981 aurel32
2435 b04ae981 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
2436 b04ae981 aurel32
        prod[i] = (int32_t)a->s8[i] * b->u8[i];
2437 b04ae981 aurel32
    }
2438 b04ae981 aurel32
2439 b04ae981 aurel32
    VECTOR_FOR_INORDER_I(i, s32) {
2440 b04ae981 aurel32
        r->s32[i] = c->s32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2441 b04ae981 aurel32
    }
2442 b04ae981 aurel32
}
2443 b04ae981 aurel32
2444 eae07261 aurel32
void helper_vmsumshm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2445 eae07261 aurel32
{
2446 eae07261 aurel32
    int32_t prod[8];
2447 eae07261 aurel32
    int i;
2448 eae07261 aurel32
2449 eae07261 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2450 eae07261 aurel32
        prod[i] = a->s16[i] * b->s16[i];
2451 eae07261 aurel32
    }
2452 eae07261 aurel32
2453 eae07261 aurel32
    VECTOR_FOR_INORDER_I(i, s32) {
2454 eae07261 aurel32
        r->s32[i] = c->s32[i] + prod[2*i] + prod[2*i+1];
2455 eae07261 aurel32
    }
2456 eae07261 aurel32
}
2457 eae07261 aurel32
2458 eae07261 aurel32
void helper_vmsumshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2459 eae07261 aurel32
{
2460 eae07261 aurel32
    int32_t prod[8];
2461 eae07261 aurel32
    int i;
2462 eae07261 aurel32
    int sat = 0;
2463 eae07261 aurel32
2464 eae07261 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2465 eae07261 aurel32
        prod[i] = (int32_t)a->s16[i] * b->s16[i];
2466 eae07261 aurel32
    }
2467 eae07261 aurel32
2468 eae07261 aurel32
    VECTOR_FOR_INORDER_I (i, s32) {
2469 eae07261 aurel32
        int64_t t = (int64_t)c->s32[i] + prod[2*i] + prod[2*i+1];
2470 eae07261 aurel32
        r->u32[i] = cvtsdsw(t, &sat);
2471 eae07261 aurel32
    }
2472 eae07261 aurel32
2473 eae07261 aurel32
    if (sat) {
2474 eae07261 aurel32
        env->vscr |= (1 << VSCR_SAT);
2475 eae07261 aurel32
    }
2476 eae07261 aurel32
}
2477 eae07261 aurel32
2478 b04ae981 aurel32
void helper_vmsumubm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2479 b04ae981 aurel32
{
2480 b04ae981 aurel32
    uint16_t prod[16];
2481 b04ae981 aurel32
    int i;
2482 b04ae981 aurel32
2483 b04ae981 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2484 b04ae981 aurel32
        prod[i] = a->u8[i] * b->u8[i];
2485 b04ae981 aurel32
    }
2486 b04ae981 aurel32
2487 b04ae981 aurel32
    VECTOR_FOR_INORDER_I(i, u32) {
2488 b04ae981 aurel32
        r->u32[i] = c->u32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2489 b04ae981 aurel32
    }
2490 b04ae981 aurel32
}
2491 b04ae981 aurel32
2492 4d9903b6 aurel32
void helper_vmsumuhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2493 4d9903b6 aurel32
{
2494 4d9903b6 aurel32
    uint32_t prod[8];
2495 4d9903b6 aurel32
    int i;
2496 4d9903b6 aurel32
2497 4d9903b6 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2498 4d9903b6 aurel32
        prod[i] = a->u16[i] * b->u16[i];
2499 4d9903b6 aurel32
    }
2500 4d9903b6 aurel32
2501 4d9903b6 aurel32
    VECTOR_FOR_INORDER_I(i, u32) {
2502 4d9903b6 aurel32
        r->u32[i] = c->u32[i] + prod[2*i] + prod[2*i+1];
2503 4d9903b6 aurel32
    }
2504 4d9903b6 aurel32
}
2505 4d9903b6 aurel32
2506 4d9903b6 aurel32
void helper_vmsumuhs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2507 4d9903b6 aurel32
{
2508 4d9903b6 aurel32
    uint32_t prod[8];
2509 4d9903b6 aurel32
    int i;
2510 4d9903b6 aurel32
    int sat = 0;
2511 4d9903b6 aurel32
2512 4d9903b6 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2513 4d9903b6 aurel32
        prod[i] = a->u16[i] * b->u16[i];
2514 4d9903b6 aurel32
    }
2515 4d9903b6 aurel32
2516 4d9903b6 aurel32
    VECTOR_FOR_INORDER_I (i, s32) {
2517 4d9903b6 aurel32
        uint64_t t = (uint64_t)c->u32[i] + prod[2*i] + prod[2*i+1];
2518 4d9903b6 aurel32
        r->u32[i] = cvtuduw(t, &sat);
2519 4d9903b6 aurel32
    }
2520 4d9903b6 aurel32
2521 4d9903b6 aurel32
    if (sat) {
2522 4d9903b6 aurel32
        env->vscr |= (1 << VSCR_SAT);
2523 4d9903b6 aurel32
    }
2524 4d9903b6 aurel32
}
2525 4d9903b6 aurel32
2526 2c277908 aurel32
#define VMUL_DO(name, mul_element, prod_element, evenp)                 \
2527 2c277908 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2528 2c277908 aurel32
    {                                                                   \
2529 2c277908 aurel32
        int i;                                                          \
2530 2c277908 aurel32
        VECTOR_FOR_INORDER_I(i, prod_element) {                         \
2531 2c277908 aurel32
            if (evenp) {                                                \
2532 2c277908 aurel32
                r->prod_element[i] = a->mul_element[i*2+HI_IDX] * b->mul_element[i*2+HI_IDX]; \
2533 2c277908 aurel32
            } else {                                                    \
2534 2c277908 aurel32
                r->prod_element[i] = a->mul_element[i*2+LO_IDX] * b->mul_element[i*2+LO_IDX]; \
2535 2c277908 aurel32
            }                                                           \
2536 2c277908 aurel32
        }                                                               \
2537 2c277908 aurel32
    }
2538 2c277908 aurel32
#define VMUL(suffix, mul_element, prod_element) \
2539 2c277908 aurel32
  VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
2540 2c277908 aurel32
  VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
2541 2c277908 aurel32
VMUL(sb, s8, s16)
2542 2c277908 aurel32
VMUL(sh, s16, s32)
2543 2c277908 aurel32
VMUL(ub, u8, u16)
2544 2c277908 aurel32
VMUL(uh, u16, u32)
2545 2c277908 aurel32
#undef VMUL_DO
2546 2c277908 aurel32
#undef VMUL
2547 2c277908 aurel32
2548 35cf7c7e aurel32
void helper_vnmsubfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2549 35cf7c7e aurel32
{
2550 35cf7c7e aurel32
    int i;
2551 35cf7c7e aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2552 35cf7c7e aurel32
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2553 35cf7c7e aurel32
            /* Need to do the computation is higher precision and round
2554 35cf7c7e aurel32
             * once at the end.  */
2555 35cf7c7e aurel32
            float64 af, bf, cf, t;
2556 35cf7c7e aurel32
            af = float32_to_float64(a->f[i], &env->vec_status);
2557 35cf7c7e aurel32
            bf = float32_to_float64(b->f[i], &env->vec_status);
2558 35cf7c7e aurel32
            cf = float32_to_float64(c->f[i], &env->vec_status);
2559 35cf7c7e aurel32
            t = float64_mul(af, cf, &env->vec_status);
2560 35cf7c7e aurel32
            t = float64_sub(t, bf, &env->vec_status);
2561 35cf7c7e aurel32
            t = float64_chs(t);
2562 35cf7c7e aurel32
            r->f[i] = float64_to_float32(t, &env->vec_status);
2563 35cf7c7e aurel32
        }
2564 35cf7c7e aurel32
    }
2565 35cf7c7e aurel32
}
2566 35cf7c7e aurel32
2567 d1258698 aurel32
void helper_vperm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2568 d1258698 aurel32
{
2569 d1258698 aurel32
    ppc_avr_t result;
2570 d1258698 aurel32
    int i;
2571 d1258698 aurel32
    VECTOR_FOR_INORDER_I (i, u8) {
2572 d1258698 aurel32
        int s = c->u8[i] & 0x1f;
2573 d1258698 aurel32
#if defined(WORDS_BIGENDIAN)
2574 d1258698 aurel32
        int index = s & 0xf;
2575 d1258698 aurel32
#else
2576 d1258698 aurel32
        int index = 15 - (s & 0xf);
2577 d1258698 aurel32
#endif
2578 d1258698 aurel32
        if (s & 0x10) {
2579 d1258698 aurel32
            result.u8[i] = b->u8[index];
2580 d1258698 aurel32
        } else {
2581 d1258698 aurel32
            result.u8[i] = a->u8[index];
2582 d1258698 aurel32
        }
2583 d1258698 aurel32
    }
2584 d1258698 aurel32
    *r = result;
2585 d1258698 aurel32
}
2586 d1258698 aurel32
2587 5335a145 aurel32
#if defined(WORDS_BIGENDIAN)
2588 5335a145 aurel32
#define PKBIG 1
2589 5335a145 aurel32
#else
2590 5335a145 aurel32
#define PKBIG 0
2591 5335a145 aurel32
#endif
2592 1dd9ffb9 aurel32
void helper_vpkpx (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2593 1dd9ffb9 aurel32
{
2594 1dd9ffb9 aurel32
    int i, j;
2595 1dd9ffb9 aurel32
    ppc_avr_t result;
2596 1dd9ffb9 aurel32
#if defined(WORDS_BIGENDIAN)
2597 1dd9ffb9 aurel32
    const ppc_avr_t *x[2] = { a, b };
2598 1dd9ffb9 aurel32
#else
2599 1dd9ffb9 aurel32
    const ppc_avr_t *x[2] = { b, a };
2600 1dd9ffb9 aurel32
#endif
2601 1dd9ffb9 aurel32
2602 1dd9ffb9 aurel32
    VECTOR_FOR_INORDER_I (i, u64) {
2603 1dd9ffb9 aurel32
        VECTOR_FOR_INORDER_I (j, u32){
2604 1dd9ffb9 aurel32
            uint32_t e = x[i]->u32[j];
2605 1dd9ffb9 aurel32
            result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
2606 1dd9ffb9 aurel32
                                 ((e >> 6) & 0x3e0) |
2607 1dd9ffb9 aurel32
                                 ((e >> 3) & 0x1f));
2608 1dd9ffb9 aurel32
        }
2609 1dd9ffb9 aurel32
    }
2610 1dd9ffb9 aurel32
    *r = result;
2611 1dd9ffb9 aurel32
}
2612 1dd9ffb9 aurel32
2613 5335a145 aurel32
#define VPK(suffix, from, to, cvt, dosat)       \
2614 5335a145 aurel32
    void helper_vpk##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2615 5335a145 aurel32
    {                                                                   \
2616 5335a145 aurel32
        int i;                                                          \
2617 5335a145 aurel32
        int sat = 0;                                                    \
2618 5335a145 aurel32
        ppc_avr_t result;                                               \
2619 5335a145 aurel32
        ppc_avr_t *a0 = PKBIG ? a : b;                                  \
2620 5335a145 aurel32
        ppc_avr_t *a1 = PKBIG ? b : a;                                  \
2621 5335a145 aurel32
        VECTOR_FOR_INORDER_I (i, from) {                                \
2622 5335a145 aurel32
            result.to[i] = cvt(a0->from[i], &sat);                      \
2623 5335a145 aurel32
            result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);  \
2624 5335a145 aurel32
        }                                                               \
2625 5335a145 aurel32
        *r = result;                                                    \
2626 5335a145 aurel32
        if (dosat && sat) {                                             \
2627 5335a145 aurel32
            env->vscr |= (1 << VSCR_SAT);                               \
2628 5335a145 aurel32
        }                                                               \
2629 5335a145 aurel32
    }
2630 5335a145 aurel32
#define I(x, y) (x)
2631 5335a145 aurel32
VPK(shss, s16, s8, cvtshsb, 1)
2632 5335a145 aurel32
VPK(shus, s16, u8, cvtshub, 1)
2633 5335a145 aurel32
VPK(swss, s32, s16, cvtswsh, 1)
2634 5335a145 aurel32
VPK(swus, s32, u16, cvtswuh, 1)
2635 5335a145 aurel32
VPK(uhus, u16, u8, cvtuhub, 1)
2636 5335a145 aurel32
VPK(uwus, u32, u16, cvtuwuh, 1)
2637 5335a145 aurel32
VPK(uhum, u16, u8, I, 0)
2638 5335a145 aurel32
VPK(uwum, u32, u16, I, 0)
2639 5335a145 aurel32
#undef I
2640 5335a145 aurel32
#undef VPK
2641 5335a145 aurel32
#undef PKBIG
2642 5335a145 aurel32
2643 bdfbac35 aurel32
void helper_vrefp (ppc_avr_t *r, ppc_avr_t *b)
2644 bdfbac35 aurel32
{
2645 bdfbac35 aurel32
    int i;
2646 bdfbac35 aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2647 bdfbac35 aurel32
        HANDLE_NAN1(r->f[i], b->f[i]) {
2648 bdfbac35 aurel32
            r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
2649 bdfbac35 aurel32
        }
2650 bdfbac35 aurel32
    }
2651 bdfbac35 aurel32
}
2652 bdfbac35 aurel32
2653 f6b19645 aurel32
#define VRFI(suffix, rounding)                                          \
2654 f6b19645 aurel32
    void helper_vrfi##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
2655 f6b19645 aurel32
    {                                                                   \
2656 f6b19645 aurel32
        int i;                                                          \
2657 f6b19645 aurel32
        float_status s = env->vec_status;                               \
2658 f6b19645 aurel32
        set_float_rounding_mode(rounding, &s);                          \
2659 f6b19645 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2660 f6b19645 aurel32
            HANDLE_NAN1(r->f[i], b->f[i]) {                             \
2661 f6b19645 aurel32
                r->f[i] = float32_round_to_int (b->f[i], &s);           \
2662 f6b19645 aurel32
            }                                                           \
2663 f6b19645 aurel32
        }                                                               \
2664 f6b19645 aurel32
    }
2665 f6b19645 aurel32
VRFI(n, float_round_nearest_even)
2666 f6b19645 aurel32
VRFI(m, float_round_down)
2667 f6b19645 aurel32
VRFI(p, float_round_up)
2668 f6b19645 aurel32
VRFI(z, float_round_to_zero)
2669 f6b19645 aurel32
#undef VRFI
2670 f6b19645 aurel32
2671 5e1d0985 aurel32
#define VROTATE(suffix, element)                                        \
2672 5e1d0985 aurel32
    void helper_vrl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2673 5e1d0985 aurel32
    {                                                                   \
2674 5e1d0985 aurel32
        int i;                                                          \
2675 5e1d0985 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2676 5e1d0985 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2677 5e1d0985 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2678 5e1d0985 aurel32
            r->element[i] = (a->element[i] << shift) | (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
2679 5e1d0985 aurel32
        }                                                               \
2680 5e1d0985 aurel32
    }
2681 5e1d0985 aurel32
VROTATE(b, u8)
2682 5e1d0985 aurel32
VROTATE(h, u16)
2683 5e1d0985 aurel32
VROTATE(w, u32)
2684 5e1d0985 aurel32
#undef VROTATE
2685 5e1d0985 aurel32
2686 071fc3b1 aurel32
void helper_vrsqrtefp (ppc_avr_t *r, ppc_avr_t *b)
2687 071fc3b1 aurel32
{
2688 071fc3b1 aurel32
    int i;
2689 071fc3b1 aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2690 071fc3b1 aurel32
        HANDLE_NAN1(r->f[i], b->f[i]) {
2691 071fc3b1 aurel32
            float32 t = float32_sqrt(b->f[i], &env->vec_status);
2692 071fc3b1 aurel32
            r->f[i] = float32_div(float32_one, t, &env->vec_status);
2693 071fc3b1 aurel32
        }
2694 071fc3b1 aurel32
    }
2695 071fc3b1 aurel32
}
2696 071fc3b1 aurel32
2697 d1258698 aurel32
void helper_vsel (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2698 d1258698 aurel32
{
2699 d1258698 aurel32
    r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
2700 d1258698 aurel32
    r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
2701 d1258698 aurel32
}
2702 d1258698 aurel32
2703 b580763f aurel32
void helper_vlogefp (ppc_avr_t *r, ppc_avr_t *b)
2704 f586ce09 aurel32
{
2705 f586ce09 aurel32
    int i;
2706 f586ce09 aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2707 f586ce09 aurel32
        HANDLE_NAN1(r->f[i], b->f[i]) {
2708 f586ce09 aurel32
            r->f[i] = float32_log2(b->f[i], &env->vec_status);
2709 f586ce09 aurel32
        }
2710 f586ce09 aurel32
    }
2711 f586ce09 aurel32
}
2712 f586ce09 aurel32
2713 d9430add aurel32
#if defined(WORDS_BIGENDIAN)
2714 d9430add aurel32
#define LEFT 0
2715 d9430add aurel32
#define RIGHT 1
2716 d9430add aurel32
#else
2717 d9430add aurel32
#define LEFT 1
2718 d9430add aurel32
#define RIGHT 0
2719 d9430add aurel32
#endif
2720 d9430add aurel32
/* The specification says that the results are undefined if all of the
2721 d9430add aurel32
 * shift counts are not identical.  We check to make sure that they are
2722 d9430add aurel32
 * to conform to what real hardware appears to do.  */
2723 d9430add aurel32
#define VSHIFT(suffix, leftp)                                           \
2724 d9430add aurel32
    void helper_vs##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
2725 d9430add aurel32
    {                                                                   \
2726 d9430add aurel32
        int shift = b->u8[LO_IDX*0x15] & 0x7;                           \
2727 d9430add aurel32
        int doit = 1;                                                   \
2728 d9430add aurel32
        int i;                                                          \
2729 d9430add aurel32
        for (i = 0; i < ARRAY_SIZE(r->u8); i++) {                       \
2730 d9430add aurel32
            doit = doit && ((b->u8[i] & 0x7) == shift);                 \
2731 d9430add aurel32
        }                                                               \
2732 d9430add aurel32
        if (doit) {                                                     \
2733 d9430add aurel32
            if (shift == 0) {                                           \
2734 d9430add aurel32
                *r = *a;                                                \
2735 d9430add aurel32
            } else if (leftp) {                                         \
2736 d9430add aurel32
                uint64_t carry = a->u64[LO_IDX] >> (64 - shift);        \
2737 d9430add aurel32
                r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry;     \
2738 d9430add aurel32
                r->u64[LO_IDX] = a->u64[LO_IDX] << shift;               \
2739 d9430add aurel32
            } else {                                                    \
2740 d9430add aurel32
                uint64_t carry = a->u64[HI_IDX] << (64 - shift);        \
2741 d9430add aurel32
                r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry;     \
2742 d9430add aurel32
                r->u64[HI_IDX] = a->u64[HI_IDX] >> shift;               \
2743 d9430add aurel32
            }                                                           \
2744 d9430add aurel32
        }                                                               \
2745 d9430add aurel32
    }
2746 d9430add aurel32
VSHIFT(l, LEFT)
2747 d9430add aurel32
VSHIFT(r, RIGHT)
2748 d9430add aurel32
#undef VSHIFT
2749 d9430add aurel32
#undef LEFT
2750 d9430add aurel32
#undef RIGHT
2751 d9430add aurel32
2752 d79f0809 aurel32
#define VSL(suffix, element)                                            \
2753 d79f0809 aurel32
    void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2754 d79f0809 aurel32
    {                                                                   \
2755 d79f0809 aurel32
        int i;                                                          \
2756 d79f0809 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2757 d79f0809 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2758 d79f0809 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2759 d79f0809 aurel32
            r->element[i] = a->element[i] << shift;                     \
2760 d79f0809 aurel32
        }                                                               \
2761 d79f0809 aurel32
    }
2762 d79f0809 aurel32
VSL(b, u8)
2763 d79f0809 aurel32
VSL(h, u16)
2764 d79f0809 aurel32
VSL(w, u32)
2765 d79f0809 aurel32
#undef VSL
2766 d79f0809 aurel32
2767 cd633b10 aurel32
void helper_vsldoi (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
2768 cd633b10 aurel32
{
2769 cd633b10 aurel32
    int sh = shift & 0xf;
2770 cd633b10 aurel32
    int i;
2771 cd633b10 aurel32
    ppc_avr_t result;
2772 cd633b10 aurel32
2773 cd633b10 aurel32
#if defined(WORDS_BIGENDIAN)
2774 cd633b10 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2775 cd633b10 aurel32
        int index = sh + i;
2776 cd633b10 aurel32
        if (index > 0xf) {
2777 cd633b10 aurel32
            result.u8[i] = b->u8[index-0x10];
2778 cd633b10 aurel32
        } else {
2779 cd633b10 aurel32
            result.u8[i] = a->u8[index];
2780 cd633b10 aurel32
        }
2781 cd633b10 aurel32
    }
2782 cd633b10 aurel32
#else
2783 cd633b10 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2784 cd633b10 aurel32
        int index = (16 - sh) + i;
2785 cd633b10 aurel32
        if (index > 0xf) {
2786 cd633b10 aurel32
            result.u8[i] = a->u8[index-0x10];
2787 cd633b10 aurel32
        } else {
2788 cd633b10 aurel32
            result.u8[i] = b->u8[index];
2789 cd633b10 aurel32
        }
2790 cd633b10 aurel32
    }
2791 cd633b10 aurel32
#endif
2792 cd633b10 aurel32
    *r = result;
2793 cd633b10 aurel32
}
2794 cd633b10 aurel32
2795 7b239bec aurel32
void helper_vslo (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2796 7b239bec aurel32
{
2797 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2798 7b239bec aurel32
2799 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2800 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2801 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2802 7b239bec aurel32
#else
2803 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2804 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2805 7b239bec aurel32
#endif
2806 7b239bec aurel32
}
2807 7b239bec aurel32
2808 e4e6bee7 aurel32
/* Experimental testing shows that hardware masks the immediate.  */
2809 e4e6bee7 aurel32
#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
2810 e4e6bee7 aurel32
#if defined(WORDS_BIGENDIAN)
2811 e4e6bee7 aurel32
#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
2812 e4e6bee7 aurel32
#else
2813 e4e6bee7 aurel32
#define SPLAT_ELEMENT(element) (ARRAY_SIZE(r->element)-1 - _SPLAT_MASKED(element))
2814 e4e6bee7 aurel32
#endif
2815 e4e6bee7 aurel32
#define VSPLT(suffix, element)                                          \
2816 e4e6bee7 aurel32
    void helper_vsplt##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
2817 e4e6bee7 aurel32
    {                                                                   \
2818 e4e6bee7 aurel32
        uint32_t s = b->element[SPLAT_ELEMENT(element)];                \
2819 e4e6bee7 aurel32
        int i;                                                          \
2820 e4e6bee7 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2821 e4e6bee7 aurel32
            r->element[i] = s;                                          \
2822 e4e6bee7 aurel32
        }                                                               \
2823 e4e6bee7 aurel32
    }
2824 e4e6bee7 aurel32
VSPLT(b, u8)
2825 e4e6bee7 aurel32
VSPLT(h, u16)
2826 e4e6bee7 aurel32
VSPLT(w, u32)
2827 e4e6bee7 aurel32
#undef VSPLT
2828 e4e6bee7 aurel32
#undef SPLAT_ELEMENT
2829 e4e6bee7 aurel32
#undef _SPLAT_MASKED
2830 e4e6bee7 aurel32
2831 c026766b aurel32
#define VSPLTI(suffix, element, splat_type)                     \
2832 c026766b aurel32
    void helper_vspltis##suffix (ppc_avr_t *r, uint32_t splat)  \
2833 c026766b aurel32
    {                                                           \
2834 c026766b aurel32
        splat_type x = (int8_t)(splat << 3) >> 3;               \
2835 c026766b aurel32
        int i;                                                  \
2836 c026766b aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {          \
2837 c026766b aurel32
            r->element[i] = x;                                  \
2838 c026766b aurel32
        }                                                       \
2839 c026766b aurel32
    }
2840 c026766b aurel32
VSPLTI(b, s8, int8_t)
2841 c026766b aurel32
VSPLTI(h, s16, int16_t)
2842 c026766b aurel32
VSPLTI(w, s32, int32_t)
2843 c026766b aurel32
#undef VSPLTI
2844 c026766b aurel32
2845 07ef34c3 aurel32
#define VSR(suffix, element)                                            \
2846 07ef34c3 aurel32
    void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2847 07ef34c3 aurel32
    {                                                                   \
2848 07ef34c3 aurel32
        int i;                                                          \
2849 07ef34c3 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2850 07ef34c3 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2851 07ef34c3 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2852 07ef34c3 aurel32
            r->element[i] = a->element[i] >> shift;                     \
2853 07ef34c3 aurel32
        }                                                               \
2854 07ef34c3 aurel32
    }
2855 07ef34c3 aurel32
VSR(ab, s8)
2856 07ef34c3 aurel32
VSR(ah, s16)
2857 07ef34c3 aurel32
VSR(aw, s32)
2858 07ef34c3 aurel32
VSR(b, u8)
2859 07ef34c3 aurel32
VSR(h, u16)
2860 07ef34c3 aurel32
VSR(w, u32)
2861 07ef34c3 aurel32
#undef VSR
2862 07ef34c3 aurel32
2863 7b239bec aurel32
void helper_vsro (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2864 7b239bec aurel32
{
2865 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2866 7b239bec aurel32
2867 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2868 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2869 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2870 7b239bec aurel32
#else
2871 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2872 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2873 7b239bec aurel32
#endif
2874 7b239bec aurel32
}
2875 7b239bec aurel32
2876 e343da72 aurel32
void helper_vsubcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2877 e343da72 aurel32
{
2878 e343da72 aurel32
    int i;
2879 e343da72 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2880 e343da72 aurel32
        r->u32[i] = a->u32[i] >= b->u32[i];
2881 e343da72 aurel32
    }
2882 e343da72 aurel32
}
2883 e343da72 aurel32
2884 8142cddd aurel32
void helper_vsumsws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2885 8142cddd aurel32
{
2886 8142cddd aurel32
    int64_t t;
2887 8142cddd aurel32
    int i, upper;
2888 8142cddd aurel32
    ppc_avr_t result;
2889 8142cddd aurel32
    int sat = 0;
2890 8142cddd aurel32
2891 8142cddd aurel32
#if defined(WORDS_BIGENDIAN)
2892 8142cddd aurel32
    upper = ARRAY_SIZE(r->s32)-1;
2893 8142cddd aurel32
#else
2894 8142cddd aurel32
    upper = 0;
2895 8142cddd aurel32
#endif
2896 8142cddd aurel32
    t = (int64_t)b->s32[upper];
2897 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2898 8142cddd aurel32
        t += a->s32[i];
2899 8142cddd aurel32
        result.s32[i] = 0;
2900 8142cddd aurel32
    }
2901 8142cddd aurel32
    result.s32[upper] = cvtsdsw(t, &sat);
2902 8142cddd aurel32
    *r = result;
2903 8142cddd aurel32
2904 8142cddd aurel32
    if (sat) {
2905 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2906 8142cddd aurel32
    }
2907 8142cddd aurel32
}
2908 8142cddd aurel32
2909 8142cddd aurel32
void helper_vsum2sws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2910 8142cddd aurel32
{
2911 8142cddd aurel32
    int i, j, upper;
2912 8142cddd aurel32
    ppc_avr_t result;
2913 8142cddd aurel32
    int sat = 0;
2914 8142cddd aurel32
2915 8142cddd aurel32
#if defined(WORDS_BIGENDIAN)
2916 8142cddd aurel32
    upper = 1;
2917 8142cddd aurel32
#else
2918 8142cddd aurel32
    upper = 0;
2919 8142cddd aurel32
#endif
2920 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
2921 8142cddd aurel32
        int64_t t = (int64_t)b->s32[upper+i*2];
2922 8142cddd aurel32
        result.u64[i] = 0;
2923 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
2924 8142cddd aurel32
            t += a->s32[2*i+j];
2925 8142cddd aurel32
        }
2926 8142cddd aurel32
        result.s32[upper+i*2] = cvtsdsw(t, &sat);
2927 8142cddd aurel32
    }
2928 8142cddd aurel32
2929 8142cddd aurel32
    *r = result;
2930 8142cddd aurel32
    if (sat) {
2931 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2932 8142cddd aurel32
    }
2933 8142cddd aurel32
}
2934 8142cddd aurel32
2935 8142cddd aurel32
void helper_vsum4sbs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2936 8142cddd aurel32
{
2937 8142cddd aurel32
    int i, j;
2938 8142cddd aurel32
    int sat = 0;
2939 8142cddd aurel32
2940 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2941 8142cddd aurel32
        int64_t t = (int64_t)b->s32[i];
2942 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
2943 8142cddd aurel32
            t += a->s8[4*i+j];
2944 8142cddd aurel32
        }
2945 8142cddd aurel32
        r->s32[i] = cvtsdsw(t, &sat);
2946 8142cddd aurel32
    }
2947 8142cddd aurel32
2948 8142cddd aurel32
    if (sat) {
2949 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2950 8142cddd aurel32
    }
2951 8142cddd aurel32
}
2952 8142cddd aurel32
2953 8142cddd aurel32
void helper_vsum4shs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2954 8142cddd aurel32
{
2955 8142cddd aurel32
    int sat = 0;
2956 8142cddd aurel32
    int i;
2957 8142cddd aurel32
2958 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2959 8142cddd aurel32
        int64_t t = (int64_t)b->s32[i];
2960 8142cddd aurel32
        t += a->s16[2*i] + a->s16[2*i+1];
2961 8142cddd aurel32
        r->s32[i] = cvtsdsw(t, &sat);
2962 8142cddd aurel32
    }
2963 8142cddd aurel32
2964 8142cddd aurel32
    if (sat) {
2965 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2966 8142cddd aurel32
    }
2967 8142cddd aurel32
}
2968 8142cddd aurel32
2969 8142cddd aurel32
void helper_vsum4ubs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2970 8142cddd aurel32
{
2971 8142cddd aurel32
    int i, j;
2972 8142cddd aurel32
    int sat = 0;
2973 8142cddd aurel32
2974 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2975 8142cddd aurel32
        uint64_t t = (uint64_t)b->u32[i];
2976 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
2977 8142cddd aurel32
            t += a->u8[4*i+j];
2978 8142cddd aurel32
        }
2979 8142cddd aurel32
        r->u32[i] = cvtuduw(t, &sat);
2980 8142cddd aurel32
    }
2981 8142cddd aurel32
2982 8142cddd aurel32
    if (sat) {
2983 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2984 8142cddd aurel32
    }
2985 8142cddd aurel32
}
2986 8142cddd aurel32
2987 79f85c3a aurel32
#if defined(WORDS_BIGENDIAN)
2988 79f85c3a aurel32
#define UPKHI 1
2989 79f85c3a aurel32
#define UPKLO 0
2990 79f85c3a aurel32
#else
2991 79f85c3a aurel32
#define UPKHI 0
2992 79f85c3a aurel32
#define UPKLO 1
2993 79f85c3a aurel32
#endif
2994 79f85c3a aurel32
#define VUPKPX(suffix, hi)                                      \
2995 79f85c3a aurel32
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)       \
2996 79f85c3a aurel32
    {                                                           \
2997 79f85c3a aurel32
        int i;                                                  \
2998 79f85c3a aurel32
        ppc_avr_t result;                                       \
2999 79f85c3a aurel32
        for (i = 0; i < ARRAY_SIZE(r->u32); i++) {              \
3000 79f85c3a aurel32
            uint16_t e = b->u16[hi ? i : i+4];                  \
3001 79f85c3a aurel32
            uint8_t a = (e >> 15) ? 0xff : 0;                   \
3002 79f85c3a aurel32
            uint8_t r = (e >> 10) & 0x1f;                       \
3003 79f85c3a aurel32
            uint8_t g = (e >> 5) & 0x1f;                        \
3004 79f85c3a aurel32
            uint8_t b = e & 0x1f;                               \
3005 79f85c3a aurel32
            result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
3006 79f85c3a aurel32
        }                                                               \
3007 79f85c3a aurel32
        *r = result;                                                    \
3008 79f85c3a aurel32
    }
3009 79f85c3a aurel32
VUPKPX(lpx, UPKLO)
3010 79f85c3a aurel32
VUPKPX(hpx, UPKHI)
3011 79f85c3a aurel32
#undef VUPKPX
3012 79f85c3a aurel32
3013 6cf1c6e5 aurel32
#define VUPK(suffix, unpacked, packee, hi)                              \
3014 6cf1c6e5 aurel32
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
3015 6cf1c6e5 aurel32
    {                                                                   \
3016 6cf1c6e5 aurel32
        int i;                                                          \
3017 6cf1c6e5 aurel32
        ppc_avr_t result;                                               \
3018 6cf1c6e5 aurel32
        if (hi) {                                                       \
3019 6cf1c6e5 aurel32
            for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
3020 6cf1c6e5 aurel32
                result.unpacked[i] = b->packee[i];                      \
3021 6cf1c6e5 aurel32
            }                                                           \
3022 6cf1c6e5 aurel32
        } else {                                                        \
3023 6cf1c6e5 aurel32
            for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); i++) { \
3024 6cf1c6e5 aurel32
                result.unpacked[i-ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
3025 6cf1c6e5 aurel32
            }                                                           \
3026 6cf1c6e5 aurel32
        }                                                               \
3027 6cf1c6e5 aurel32
        *r = result;                                                    \
3028 6cf1c6e5 aurel32
    }
3029 6cf1c6e5 aurel32
VUPK(hsb, s16, s8, UPKHI)
3030 6cf1c6e5 aurel32
VUPK(hsh, s32, s16, UPKHI)
3031 6cf1c6e5 aurel32
VUPK(lsb, s16, s8, UPKLO)
3032 6cf1c6e5 aurel32
VUPK(lsh, s32, s16, UPKLO)
3033 6cf1c6e5 aurel32
#undef VUPK
3034 79f85c3a aurel32
#undef UPKHI
3035 79f85c3a aurel32
#undef UPKLO
3036 79f85c3a aurel32
3037 34ba2857 aurel32
#undef DO_HANDLE_NAN
3038 34ba2857 aurel32
#undef HANDLE_NAN1
3039 34ba2857 aurel32
#undef HANDLE_NAN2
3040 34ba2857 aurel32
#undef HANDLE_NAN3
3041 d6a46fe8 aurel32
#undef VECTOR_FOR_INORDER_I
3042 d6a46fe8 aurel32
#undef HI_IDX
3043 d6a46fe8 aurel32
#undef LO_IDX
3044 d6a46fe8 aurel32
3045 d6a46fe8 aurel32
/*****************************************************************************/
3046 0487d6a8 j_mayer
/* SPE extension helpers */
3047 0487d6a8 j_mayer
/* Use a table to make this quicker */
3048 0487d6a8 j_mayer
static uint8_t hbrev[16] = {
3049 0487d6a8 j_mayer
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
3050 0487d6a8 j_mayer
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
3051 0487d6a8 j_mayer
};
3052 0487d6a8 j_mayer
3053 b068d6a7 j_mayer
static always_inline uint8_t byte_reverse (uint8_t val)
3054 0487d6a8 j_mayer
{
3055 0487d6a8 j_mayer
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
3056 0487d6a8 j_mayer
}
3057 0487d6a8 j_mayer
3058 b068d6a7 j_mayer
static always_inline uint32_t word_reverse (uint32_t val)
3059 0487d6a8 j_mayer
{
3060 0487d6a8 j_mayer
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
3061 0487d6a8 j_mayer
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
3062 0487d6a8 j_mayer
}
3063 0487d6a8 j_mayer
3064 3cd7d1dd j_mayer
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
3065 57951c27 aurel32
target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
3066 0487d6a8 j_mayer
{
3067 0487d6a8 j_mayer
    uint32_t a, b, d, mask;
3068 0487d6a8 j_mayer
3069 3cd7d1dd j_mayer
    mask = UINT32_MAX >> (32 - MASKBITS);
3070 57951c27 aurel32
    a = arg1 & mask;
3071 57951c27 aurel32
    b = arg2 & mask;
3072 3cd7d1dd j_mayer
    d = word_reverse(1 + word_reverse(a | ~b));
3073 57951c27 aurel32
    return (arg1 & ~mask) | (d & b);
3074 0487d6a8 j_mayer
}
3075 0487d6a8 j_mayer
3076 57951c27 aurel32
uint32_t helper_cntlsw32 (uint32_t val)
3077 0487d6a8 j_mayer
{
3078 0487d6a8 j_mayer
    if (val & 0x80000000)
3079 603fccce j_mayer
        return clz32(~val);
3080 0487d6a8 j_mayer
    else
3081 603fccce j_mayer
        return clz32(val);
3082 0487d6a8 j_mayer
}
3083 0487d6a8 j_mayer
3084 57951c27 aurel32
uint32_t helper_cntlzw32 (uint32_t val)
3085 0487d6a8 j_mayer
{
3086 603fccce j_mayer
    return clz32(val);
3087 0487d6a8 j_mayer
}
3088 0487d6a8 j_mayer
3089 1c97856d aurel32
/* Single-precision floating-point conversions */
3090 1c97856d aurel32
static always_inline uint32_t efscfsi (uint32_t val)
3091 0487d6a8 j_mayer
{
3092 0ca9d380 aurel32
    CPU_FloatU u;
3093 0487d6a8 j_mayer
3094 fbd265b6 aurel32
    u.f = int32_to_float32(val, &env->vec_status);
3095 0487d6a8 j_mayer
3096 0ca9d380 aurel32
    return u.l;
3097 0487d6a8 j_mayer
}
3098 0487d6a8 j_mayer
3099 1c97856d aurel32
static always_inline uint32_t efscfui (uint32_t val)
3100 0487d6a8 j_mayer
{
3101 0ca9d380 aurel32
    CPU_FloatU u;
3102 0487d6a8 j_mayer
3103 fbd265b6 aurel32
    u.f = uint32_to_float32(val, &env->vec_status);
3104 0487d6a8 j_mayer
3105 0ca9d380 aurel32
    return u.l;
3106 0487d6a8 j_mayer
}
3107 0487d6a8 j_mayer
3108 1c97856d aurel32
static always_inline int32_t efsctsi (uint32_t val)
3109 0487d6a8 j_mayer
{
3110 0ca9d380 aurel32
    CPU_FloatU u;
3111 0487d6a8 j_mayer
3112 0ca9d380 aurel32
    u.l = val;
3113 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3114 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3115 0487d6a8 j_mayer
        return 0;
3116 0487d6a8 j_mayer
3117 fbd265b6 aurel32
    return float32_to_int32(u.f, &env->vec_status);
3118 0487d6a8 j_mayer
}
3119 0487d6a8 j_mayer
3120 1c97856d aurel32
static always_inline uint32_t efsctui (uint32_t val)
3121 0487d6a8 j_mayer
{
3122 0ca9d380 aurel32
    CPU_FloatU u;
3123 0487d6a8 j_mayer
3124 0ca9d380 aurel32
    u.l = val;
3125 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3126 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3127 0487d6a8 j_mayer
        return 0;
3128 0487d6a8 j_mayer
3129 fbd265b6 aurel32
    return float32_to_uint32(u.f, &env->vec_status);
3130 0487d6a8 j_mayer
}
3131 0487d6a8 j_mayer
3132 1c97856d aurel32
static always_inline uint32_t efsctsiz (uint32_t val)
3133 0487d6a8 j_mayer
{
3134 0ca9d380 aurel32
    CPU_FloatU u;
3135 0487d6a8 j_mayer
3136 0ca9d380 aurel32
    u.l = val;
3137 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3138 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3139 0487d6a8 j_mayer
        return 0;
3140 0487d6a8 j_mayer
3141 fbd265b6 aurel32
    return float32_to_int32_round_to_zero(u.f, &env->vec_status);
3142 0487d6a8 j_mayer
}
3143 0487d6a8 j_mayer
3144 1c97856d aurel32
static always_inline uint32_t efsctuiz (uint32_t val)
3145 0487d6a8 j_mayer
{
3146 0ca9d380 aurel32
    CPU_FloatU u;
3147 0487d6a8 j_mayer
3148 0ca9d380 aurel32
    u.l = val;
3149 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3150 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3151 0487d6a8 j_mayer
        return 0;
3152 0487d6a8 j_mayer
3153 fbd265b6 aurel32
    return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
3154 0487d6a8 j_mayer
}
3155 0487d6a8 j_mayer
3156 1c97856d aurel32
static always_inline uint32_t efscfsf (uint32_t val)
3157 0487d6a8 j_mayer
{
3158 0ca9d380 aurel32
    CPU_FloatU u;
3159 0487d6a8 j_mayer
    float32 tmp;
3160 0487d6a8 j_mayer
3161 fbd265b6 aurel32
    u.f = int32_to_float32(val, &env->vec_status);
3162 fbd265b6 aurel32
    tmp = int64_to_float32(1ULL << 32, &env->vec_status);
3163 fbd265b6 aurel32
    u.f = float32_div(u.f, tmp, &env->vec_status);
3164 0487d6a8 j_mayer
3165 0ca9d380 aurel32
    return u.l;
3166 0487d6a8 j_mayer
}
3167 0487d6a8 j_mayer
3168 1c97856d aurel32
static always_inline uint32_t efscfuf (uint32_t val)
3169 0487d6a8 j_mayer
{
3170 0ca9d380 aurel32
    CPU_FloatU u;
3171 0487d6a8 j_mayer
    float32 tmp;
3172 0487d6a8 j_mayer
3173 fbd265b6 aurel32
    u.f = uint32_to_float32(val, &env->vec_status);
3174 fbd265b6 aurel32
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3175 fbd265b6 aurel32
    u.f = float32_div(u.f, tmp, &env->vec_status);
3176 0487d6a8 j_mayer
3177 0ca9d380 aurel32
    return u.l;
3178 0487d6a8 j_mayer
}
3179 0487d6a8 j_mayer
3180 1c97856d aurel32
static always_inline uint32_t efsctsf (uint32_t val)
3181 0487d6a8 j_mayer
{
3182 0ca9d380 aurel32
    CPU_FloatU u;
3183 0487d6a8 j_mayer
    float32 tmp;
3184 0487d6a8 j_mayer
3185 0ca9d380 aurel32
    u.l = val;
3186 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3187 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3188 0487d6a8 j_mayer
        return 0;
3189 fbd265b6 aurel32
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3190 fbd265b6 aurel32
    u.f = float32_mul(u.f, tmp, &env->vec_status);
3191 0487d6a8 j_mayer
3192 fbd265b6 aurel32
    return float32_to_int32(u.f, &env->vec_status);
3193 0487d6a8 j_mayer
}
3194 0487d6a8 j_mayer
3195 1c97856d aurel32
static always_inline uint32_t efsctuf (uint32_t val)
3196 0487d6a8 j_mayer
{
3197 0ca9d380 aurel32
    CPU_FloatU u;
3198 0487d6a8 j_mayer
    float32 tmp;
3199 0487d6a8 j_mayer
3200 0ca9d380 aurel32
    u.l = val;
3201 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3202 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3203 0487d6a8 j_mayer
        return 0;
3204 fbd265b6 aurel32
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3205 fbd265b6 aurel32
    u.f = float32_mul(u.f, tmp, &env->vec_status);
3206 0487d6a8 j_mayer
3207 fbd265b6 aurel32
    return float32_to_uint32(u.f, &env->vec_status);
3208 0487d6a8 j_mayer
}
3209 0487d6a8 j_mayer
3210 1c97856d aurel32
#define HELPER_SPE_SINGLE_CONV(name)                                          \
3211 1c97856d aurel32
uint32_t helper_e##name (uint32_t val)                                        \
3212 1c97856d aurel32
{                                                                             \
3213 1c97856d aurel32
    return e##name(val);                                                      \
3214 1c97856d aurel32
}
3215 1c97856d aurel32
/* efscfsi */
3216 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsi);
3217 1c97856d aurel32
/* efscfui */
3218 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfui);
3219 1c97856d aurel32
/* efscfuf */
3220 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfuf);
3221 1c97856d aurel32
/* efscfsf */
3222 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsf);
3223 1c97856d aurel32
/* efsctsi */
3224 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsi);
3225 1c97856d aurel32
/* efsctui */
3226 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctui);
3227 1c97856d aurel32
/* efsctsiz */
3228 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsiz);
3229 1c97856d aurel32
/* efsctuiz */
3230 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuiz);
3231 1c97856d aurel32
/* efsctsf */
3232 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsf);
3233 1c97856d aurel32
/* efsctuf */
3234 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuf);
3235 1c97856d aurel32
3236 1c97856d aurel32
#define HELPER_SPE_VECTOR_CONV(name)                                          \
3237 1c97856d aurel32
uint64_t helper_ev##name (uint64_t val)                                       \
3238 1c97856d aurel32
{                                                                             \
3239 1c97856d aurel32
    return ((uint64_t)e##name(val >> 32) << 32) |                             \
3240 1c97856d aurel32
            (uint64_t)e##name(val);                                           \
3241 0487d6a8 j_mayer
}
3242 1c97856d aurel32
/* evfscfsi */
3243 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsi);
3244 1c97856d aurel32
/* evfscfui */
3245 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfui);
3246 1c97856d aurel32
/* evfscfuf */
3247 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfuf);
3248 1c97856d aurel32
/* evfscfsf */
3249 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsf);
3250 1c97856d aurel32
/* evfsctsi */
3251 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsi);
3252 1c97856d aurel32
/* evfsctui */
3253 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctui);
3254 1c97856d aurel32
/* evfsctsiz */
3255 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsiz);
3256 1c97856d aurel32
/* evfsctuiz */
3257 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuiz);
3258 1c97856d aurel32
/* evfsctsf */
3259 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsf);
3260 1c97856d aurel32
/* evfsctuf */
3261 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuf);
3262 0487d6a8 j_mayer
3263 1c97856d aurel32
/* Single-precision floating-point arithmetic */
3264 1c97856d aurel32
static always_inline uint32_t efsadd (uint32_t op1, uint32_t op2)
3265 0487d6a8 j_mayer
{
3266 1c97856d aurel32
    CPU_FloatU u1, u2;
3267 1c97856d aurel32
    u1.l = op1;
3268 1c97856d aurel32
    u2.l = op2;
3269 fbd265b6 aurel32
    u1.f = float32_add(u1.f, u2.f, &env->vec_status);
3270 1c97856d aurel32
    return u1.l;
3271 0487d6a8 j_mayer
}
3272 0487d6a8 j_mayer
3273 1c97856d aurel32
static always_inline uint32_t efssub (uint32_t op1, uint32_t op2)
3274 0487d6a8 j_mayer
{
3275 1c97856d aurel32
    CPU_FloatU u1, u2;
3276 1c97856d aurel32
    u1.l = op1;
3277 1c97856d aurel32
    u2.l = op2;
3278 fbd265b6 aurel32
    u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
3279 1c97856d aurel32
    return u1.l;
3280 0487d6a8 j_mayer
}
3281 0487d6a8 j_mayer
3282 1c97856d aurel32
static always_inline uint32_t efsmul (uint32_t op1, uint32_t op2)
3283 0487d6a8 j_mayer
{
3284 1c97856d aurel32
    CPU_FloatU u1, u2;
3285 1c97856d aurel32
    u1.l = op1;
3286 1c97856d aurel32
    u2.l = op2;
3287 fbd265b6 aurel32
    u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
3288 1c97856d aurel32
    return u1.l;
3289 0487d6a8 j_mayer
}
3290 0487d6a8 j_mayer
3291 1c97856d aurel32
static always_inline uint32_t efsdiv (uint32_t op1, uint32_t op2)
3292 0487d6a8 j_mayer
{
3293 1c97856d aurel32
    CPU_FloatU u1, u2;
3294 1c97856d aurel32
    u1.l = op1;
3295 1c97856d aurel32
    u2.l = op2;
3296 fbd265b6 aurel32
    u1.f = float32_div(u1.f, u2.f, &env->vec_status);
3297 1c97856d aurel32
    return u1.l;
3298 0487d6a8 j_mayer
}
3299 0487d6a8 j_mayer
3300 1c97856d aurel32
#define HELPER_SPE_SINGLE_ARITH(name)                                         \
3301 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
3302 1c97856d aurel32
{                                                                             \
3303 1c97856d aurel32
    return e##name(op1, op2);                                                 \
3304 1c97856d aurel32
}
3305 1c97856d aurel32
/* efsadd */
3306 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsadd);
3307 1c97856d aurel32
/* efssub */
3308 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fssub);
3309 1c97856d aurel32
/* efsmul */
3310 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsmul);
3311 1c97856d aurel32
/* efsdiv */
3312 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsdiv);
3313 1c97856d aurel32
3314 1c97856d aurel32
#define HELPER_SPE_VECTOR_ARITH(name)                                         \
3315 1c97856d aurel32
uint64_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3316 1c97856d aurel32
{                                                                             \
3317 1c97856d aurel32
    return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |                  \
3318 1c97856d aurel32
            (uint64_t)e##name(op1, op2);                                      \
3319 1c97856d aurel32
}
3320 1c97856d aurel32
/* evfsadd */
3321 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsadd);
3322 1c97856d aurel32
/* evfssub */
3323 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fssub);
3324 1c97856d aurel32
/* evfsmul */
3325 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsmul);
3326 1c97856d aurel32
/* evfsdiv */
3327 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsdiv);
3328 1c97856d aurel32
3329 1c97856d aurel32
/* Single-precision floating-point comparisons */
3330 1c97856d aurel32
static always_inline uint32_t efststlt (uint32_t op1, uint32_t op2)
3331 0487d6a8 j_mayer
{
3332 1c97856d aurel32
    CPU_FloatU u1, u2;
3333 1c97856d aurel32
    u1.l = op1;
3334 1c97856d aurel32
    u2.l = op2;
3335 fbd265b6 aurel32
    return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3336 0487d6a8 j_mayer
}
3337 0487d6a8 j_mayer
3338 1c97856d aurel32
static always_inline uint32_t efststgt (uint32_t op1, uint32_t op2)
3339 0487d6a8 j_mayer
{
3340 1c97856d aurel32
    CPU_FloatU u1, u2;
3341 1c97856d aurel32
    u1.l = op1;
3342 1c97856d aurel32
    u2.l = op2;
3343 fbd265b6 aurel32
    return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
3344 0487d6a8 j_mayer
}
3345 0487d6a8 j_mayer
3346 1c97856d aurel32
static always_inline uint32_t efststeq (uint32_t op1, uint32_t op2)
3347 0487d6a8 j_mayer
{
3348 1c97856d aurel32
    CPU_FloatU u1, u2;
3349 1c97856d aurel32
    u1.l = op1;
3350 1c97856d aurel32
    u2.l = op2;
3351 fbd265b6 aurel32
    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3352 0487d6a8 j_mayer
}
3353 0487d6a8 j_mayer
3354 1c97856d aurel32
static always_inline uint32_t efscmplt (uint32_t op1, uint32_t op2)
3355 0487d6a8 j_mayer
{
3356 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3357 1c97856d aurel32
    return efststlt(op1, op2);
3358 0487d6a8 j_mayer
}
3359 0487d6a8 j_mayer
3360 1c97856d aurel32
static always_inline uint32_t efscmpgt (uint32_t op1, uint32_t op2)
3361 0487d6a8 j_mayer
{
3362 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3363 1c97856d aurel32
    return efststgt(op1, op2);
3364 0487d6a8 j_mayer
}
3365 0487d6a8 j_mayer
3366 1c97856d aurel32
static always_inline uint32_t efscmpeq (uint32_t op1, uint32_t op2)
3367 0487d6a8 j_mayer
{
3368 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3369 1c97856d aurel32
    return efststeq(op1, op2);
3370 0487d6a8 j_mayer
}
3371 0487d6a8 j_mayer
3372 1c97856d aurel32
#define HELPER_SINGLE_SPE_CMP(name)                                           \
3373 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
3374 1c97856d aurel32
{                                                                             \
3375 1c97856d aurel32
    return e##name(op1, op2) << 2;                                            \
3376 1c97856d aurel32
}
3377 1c97856d aurel32
/* efststlt */
3378 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststlt);
3379 1c97856d aurel32
/* efststgt */
3380 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststgt);
3381 1c97856d aurel32
/* efststeq */
3382 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststeq);
3383 1c97856d aurel32
/* efscmplt */
3384 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmplt);
3385 1c97856d aurel32
/* efscmpgt */
3386 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpgt);
3387 1c97856d aurel32
/* efscmpeq */
3388 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpeq);
3389 1c97856d aurel32
3390 1c97856d aurel32
static always_inline uint32_t evcmp_merge (int t0, int t1)
3391 0487d6a8 j_mayer
{
3392 1c97856d aurel32
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
3393 0487d6a8 j_mayer
}
3394 0487d6a8 j_mayer
3395 1c97856d aurel32
#define HELPER_VECTOR_SPE_CMP(name)                                           \
3396 1c97856d aurel32
uint32_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3397 1c97856d aurel32
{                                                                             \
3398 1c97856d aurel32
    return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2));     \
3399 0487d6a8 j_mayer
}
3400 1c97856d aurel32
/* evfststlt */
3401 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststlt);
3402 1c97856d aurel32
/* evfststgt */
3403 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststgt);
3404 1c97856d aurel32
/* evfststeq */
3405 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststeq);
3406 1c97856d aurel32
/* evfscmplt */
3407 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmplt);
3408 1c97856d aurel32
/* evfscmpgt */
3409 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpgt);
3410 1c97856d aurel32
/* evfscmpeq */
3411 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpeq);
3412 0487d6a8 j_mayer
3413 1c97856d aurel32
/* Double-precision floating-point conversion */
3414 1c97856d aurel32
uint64_t helper_efdcfsi (uint32_t val)
3415 0487d6a8 j_mayer
{
3416 1c97856d aurel32
    CPU_DoubleU u;
3417 1c97856d aurel32
3418 fbd265b6 aurel32
    u.d = int32_to_float64(val, &env->vec_status);
3419 1c97856d aurel32
3420 1c97856d aurel32
    return u.ll;
3421 0487d6a8 j_mayer
}
3422 0487d6a8 j_mayer
3423 1c97856d aurel32
uint64_t helper_efdcfsid (uint64_t val)
3424 0487d6a8 j_mayer
{
3425 0ca9d380 aurel32
    CPU_DoubleU u;
3426 0487d6a8 j_mayer
3427 fbd265b6 aurel32
    u.d = int64_to_float64(val, &env->vec_status);
3428 0487d6a8 j_mayer
3429 0ca9d380 aurel32
    return u.ll;
3430 0487d6a8 j_mayer
}
3431 0487d6a8 j_mayer
3432 1c97856d aurel32
uint64_t helper_efdcfui (uint32_t val)
3433 1c97856d aurel32
{
3434 1c97856d aurel32
    CPU_DoubleU u;
3435 1c97856d aurel32
3436 fbd265b6 aurel32
    u.d = uint32_to_float64(val, &env->vec_status);
3437 1c97856d aurel32
3438 1c97856d aurel32
    return u.ll;
3439 1c97856d aurel32
}
3440 1c97856d aurel32
3441 1c97856d aurel32
uint64_t helper_efdcfuid (uint64_t val)
3442 0487d6a8 j_mayer
{
3443 0ca9d380 aurel32
    CPU_DoubleU u;
3444 0487d6a8 j_mayer
3445 fbd265b6 aurel32
    u.d = uint64_to_float64(val, &env->vec_status);
3446 0487d6a8 j_mayer
3447 0ca9d380 aurel32
    return u.ll;
3448 0487d6a8 j_mayer
}
3449 0487d6a8 j_mayer
3450 1c97856d aurel32
uint32_t helper_efdctsi (uint64_t val)
3451 0487d6a8 j_mayer
{
3452 0ca9d380 aurel32
    CPU_DoubleU u;
3453 0487d6a8 j_mayer
3454 0ca9d380 aurel32
    u.ll = val;
3455 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3456 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3457 0487d6a8 j_mayer
        return 0;
3458 0487d6a8 j_mayer
3459 fbd265b6 aurel32
    return float64_to_int32(u.d, &env->vec_status);
3460 0487d6a8 j_mayer
}
3461 0487d6a8 j_mayer
3462 1c97856d aurel32
uint32_t helper_efdctui (uint64_t val)
3463 0487d6a8 j_mayer
{
3464 0ca9d380 aurel32
    CPU_DoubleU u;
3465 0487d6a8 j_mayer
3466 0ca9d380 aurel32
    u.ll = val;
3467 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3468 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3469 0487d6a8 j_mayer
        return 0;
3470 0487d6a8 j_mayer
3471 fbd265b6 aurel32
    return float64_to_uint32(u.d, &env->vec_status);
3472 0487d6a8 j_mayer
}
3473 0487d6a8 j_mayer
3474 1c97856d aurel32
uint32_t helper_efdctsiz (uint64_t val)
3475 0487d6a8 j_mayer
{
3476 0ca9d380 aurel32
    CPU_DoubleU u;
3477 0487d6a8 j_mayer
3478 0ca9d380 aurel32
    u.ll = val;
3479 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3480 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3481 0487d6a8 j_mayer
        return 0;
3482 0487d6a8 j_mayer
3483 fbd265b6 aurel32
    return float64_to_int32_round_to_zero(u.d, &env->vec_status);
3484 0487d6a8 j_mayer
}
3485 0487d6a8 j_mayer
3486 1c97856d aurel32
uint64_t helper_efdctsidz (uint64_t val)
3487 0487d6a8 j_mayer
{
3488 0ca9d380 aurel32
    CPU_DoubleU u;
3489 0487d6a8 j_mayer
3490 0ca9d380 aurel32
    u.ll = val;
3491 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3492 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3493 0487d6a8 j_mayer
        return 0;
3494 0487d6a8 j_mayer
3495 fbd265b6 aurel32
    return float64_to_int64_round_to_zero(u.d, &env->vec_status);
3496 0487d6a8 j_mayer
}
3497 0487d6a8 j_mayer
3498 1c97856d aurel32
uint32_t helper_efdctuiz (uint64_t val)
3499 0487d6a8 j_mayer
{
3500 1c97856d aurel32
    CPU_DoubleU u;
3501 0487d6a8 j_mayer
3502 1c97856d aurel32
    u.ll = val;
3503 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
3504 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3505 1c97856d aurel32
        return 0;
3506 0487d6a8 j_mayer
3507 fbd265b6 aurel32
    return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
3508 0487d6a8 j_mayer
}
3509 0487d6a8 j_mayer
3510 1c97856d aurel32
uint64_t helper_efdctuidz (uint64_t val)
3511 0487d6a8 j_mayer
{
3512 1c97856d aurel32
    CPU_DoubleU u;
3513 0487d6a8 j_mayer
3514 1c97856d aurel32
    u.ll = val;
3515 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
3516 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3517 1c97856d aurel32
        return 0;
3518 0487d6a8 j_mayer
3519 fbd265b6 aurel32
    return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
3520 0487d6a8 j_mayer
}
3521 0487d6a8 j_mayer
3522 1c97856d aurel32
uint64_t helper_efdcfsf (uint32_t val)
3523 0487d6a8 j_mayer
{
3524 0ca9d380 aurel32
    CPU_DoubleU u;
3525 0487d6a8 j_mayer
    float64 tmp;
3526 0487d6a8 j_mayer
3527 fbd265b6 aurel32
    u.d = int32_to_float64(val, &env->vec_status);
3528 fbd265b6 aurel32
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3529 fbd265b6 aurel32
    u.d = float64_div(u.d, tmp, &env->vec_status);
3530 0487d6a8 j_mayer
3531 0ca9d380 aurel32
    return u.ll;
3532 0487d6a8 j_mayer
}
3533 0487d6a8 j_mayer
3534 1c97856d aurel32
uint64_t helper_efdcfuf (uint32_t val)
3535 0487d6a8 j_mayer
{
3536 0ca9d380 aurel32
    CPU_DoubleU u;
3537 0487d6a8 j_mayer
    float64 tmp;
3538 0487d6a8 j_mayer
3539 fbd265b6 aurel32
    u.d = uint32_to_float64(val, &env->vec_status);
3540 fbd265b6 aurel32
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3541 fbd265b6 aurel32
    u.d = float64_div(u.d, tmp, &env->vec_status);
3542 0487d6a8 j_mayer
3543 0ca9d380 aurel32
    return u.ll;
3544 0487d6a8 j_mayer
}
3545 0487d6a8 j_mayer
3546 1c97856d aurel32
uint32_t helper_efdctsf (uint64_t val)
3547 0487d6a8 j_mayer
{
3548 0ca9d380 aurel32
    CPU_DoubleU u;
3549 0487d6a8 j_mayer
    float64 tmp;
3550 0487d6a8 j_mayer
3551 0ca9d380 aurel32
    u.ll = val;
3552 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3553 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3554 0487d6a8 j_mayer
        return 0;
3555 fbd265b6 aurel32
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3556 fbd265b6 aurel32
    u.d = float64_mul(u.d, tmp, &env->vec_status);
3557 0487d6a8 j_mayer
3558 fbd265b6 aurel32
    return float64_to_int32(u.d, &env->vec_status);
3559 0487d6a8 j_mayer
}
3560 0487d6a8 j_mayer
3561 1c97856d aurel32
uint32_t helper_efdctuf (uint64_t val)
3562 0487d6a8 j_mayer
{
3563 0ca9d380 aurel32
    CPU_DoubleU u;
3564 0487d6a8 j_mayer
    float64 tmp;
3565 0487d6a8 j_mayer
3566 0ca9d380 aurel32
    u.ll = val;
3567 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3568 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3569 0487d6a8 j_mayer
        return 0;
3570 fbd265b6 aurel32
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3571 fbd265b6 aurel32
    u.d = float64_mul(u.d, tmp, &env->vec_status);
3572 0487d6a8 j_mayer
3573 fbd265b6 aurel32
    return float64_to_uint32(u.d, &env->vec_status);
3574 0487d6a8 j_mayer
}
3575 0487d6a8 j_mayer
3576 1c97856d aurel32
uint32_t helper_efscfd (uint64_t val)
3577 0487d6a8 j_mayer
{
3578 0ca9d380 aurel32
    CPU_DoubleU u1;
3579 0ca9d380 aurel32
    CPU_FloatU u2;
3580 0487d6a8 j_mayer
3581 0ca9d380 aurel32
    u1.ll = val;
3582 fbd265b6 aurel32
    u2.f = float64_to_float32(u1.d, &env->vec_status);
3583 0487d6a8 j_mayer
3584 0ca9d380 aurel32
    return u2.l;
3585 0487d6a8 j_mayer
}
3586 0487d6a8 j_mayer
3587 1c97856d aurel32
uint64_t helper_efdcfs (uint32_t val)
3588 0487d6a8 j_mayer
{
3589 0ca9d380 aurel32
    CPU_DoubleU u2;
3590 0ca9d380 aurel32
    CPU_FloatU u1;
3591 0487d6a8 j_mayer
3592 0ca9d380 aurel32
    u1.l = val;
3593 fbd265b6 aurel32
    u2.d = float32_to_float64(u1.f, &env->vec_status);
3594 0487d6a8 j_mayer
3595 0ca9d380 aurel32
    return u2.ll;
3596 0487d6a8 j_mayer
}
3597 0487d6a8 j_mayer
3598 1c97856d aurel32
/* Double precision fixed-point arithmetic */
3599 1c97856d aurel32
uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
3600 0487d6a8 j_mayer
{
3601 1c97856d aurel32
    CPU_DoubleU u1, u2;
3602 1c97856d aurel32
    u1.ll = op1;
3603 1c97856d aurel32
    u2.ll = op2;
3604 fbd265b6 aurel32
    u1.d = float64_add(u1.d, u2.d, &env->vec_status);
3605 1c97856d aurel32
    return u1.ll;
3606 0487d6a8 j_mayer
}
3607 0487d6a8 j_mayer
3608 1c97856d aurel32
uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
3609 0487d6a8 j_mayer
{
3610 1c97856d aurel32
    CPU_DoubleU u1, u2;
3611 1c97856d aurel32
    u1.ll = op1;
3612 1c97856d aurel32
    u2.ll = op2;
3613 fbd265b6 aurel32
    u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
3614 1c97856d aurel32
    return u1.ll;
3615 0487d6a8 j_mayer
}
3616 0487d6a8 j_mayer
3617 1c97856d aurel32
uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
3618 0487d6a8 j_mayer
{
3619 1c97856d aurel32
    CPU_DoubleU u1, u2;
3620 1c97856d aurel32
    u1.ll = op1;
3621 1c97856d aurel32
    u2.ll = op2;
3622 fbd265b6 aurel32
    u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
3623 1c97856d aurel32
    return u1.ll;
3624 0487d6a8 j_mayer
}
3625 0487d6a8 j_mayer
3626 1c97856d aurel32
uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
3627 0487d6a8 j_mayer
{
3628 1c97856d aurel32
    CPU_DoubleU u1, u2;
3629 1c97856d aurel32
    u1.ll = op1;
3630 1c97856d aurel32
    u2.ll = op2;
3631 fbd265b6 aurel32
    u1.d = float64_div(u1.d, u2.d, &env->vec_status);
3632 1c97856d aurel32
    return u1.ll;
3633 0487d6a8 j_mayer
}
3634 0487d6a8 j_mayer
3635 1c97856d aurel32
/* Double precision floating point helpers */
3636 1c97856d aurel32
uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
3637 0487d6a8 j_mayer
{
3638 1c97856d aurel32
    CPU_DoubleU u1, u2;
3639 1c97856d aurel32
    u1.ll = op1;
3640 1c97856d aurel32
    u2.ll = op2;
3641 fbd265b6 aurel32
    return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3642 0487d6a8 j_mayer
}
3643 0487d6a8 j_mayer
3644 1c97856d aurel32
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
3645 0487d6a8 j_mayer
{
3646 1c97856d aurel32
    CPU_DoubleU u1, u2;
3647 1c97856d aurel32
    u1.ll = op1;
3648 1c97856d aurel32
    u2.ll = op2;
3649 fbd265b6 aurel32
    return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
3650 0487d6a8 j_mayer
}
3651 0487d6a8 j_mayer
3652 1c97856d aurel32
uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
3653 0487d6a8 j_mayer
{
3654 1c97856d aurel32
    CPU_DoubleU u1, u2;
3655 1c97856d aurel32
    u1.ll = op1;
3656 1c97856d aurel32
    u2.ll = op2;
3657 fbd265b6 aurel32
    return float64_eq(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3658 0487d6a8 j_mayer
}
3659 0487d6a8 j_mayer
3660 1c97856d aurel32
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
3661 0487d6a8 j_mayer
{
3662 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3663 1c97856d aurel32
    return helper_efdtstlt(op1, op2);
3664 0487d6a8 j_mayer
}
3665 0487d6a8 j_mayer
3666 1c97856d aurel32
uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
3667 1c97856d aurel32
{
3668 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3669 1c97856d aurel32
    return helper_efdtstgt(op1, op2);
3670 1c97856d aurel32
}
3671 0487d6a8 j_mayer
3672 1c97856d aurel32
uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
3673 1c97856d aurel32
{
3674 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3675 1c97856d aurel32
    return helper_efdtsteq(op1, op2);
3676 1c97856d aurel32
}
3677 0487d6a8 j_mayer
3678 fdabc366 bellard
/*****************************************************************************/
3679 fdabc366 bellard
/* Softmmu support */
3680 fdabc366 bellard
#if !defined (CONFIG_USER_ONLY)
3681 fdabc366 bellard
3682 fdabc366 bellard
#define MMUSUFFIX _mmu
3683 fdabc366 bellard
3684 fdabc366 bellard
#define SHIFT 0
3685 fdabc366 bellard
#include "softmmu_template.h"
3686 fdabc366 bellard
3687 fdabc366 bellard
#define SHIFT 1
3688 fdabc366 bellard
#include "softmmu_template.h"
3689 fdabc366 bellard
3690 fdabc366 bellard
#define SHIFT 2
3691 fdabc366 bellard
#include "softmmu_template.h"
3692 fdabc366 bellard
3693 fdabc366 bellard
#define SHIFT 3
3694 fdabc366 bellard
#include "softmmu_template.h"
3695 fdabc366 bellard
3696 fdabc366 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
3697 fdabc366 bellard
   NULL, it means that the function was called in C code (i.e. not
3698 fdabc366 bellard
   from generated code or from helper.c) */
3699 fdabc366 bellard
/* XXX: fix it to restore all registers */
3700 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3701 fdabc366 bellard
{
3702 fdabc366 bellard
    TranslationBlock *tb;
3703 fdabc366 bellard
    CPUState *saved_env;
3704 44f8625d bellard
    unsigned long pc;
3705 fdabc366 bellard
    int ret;
3706 fdabc366 bellard
3707 fdabc366 bellard
    /* XXX: hack to restore env in all cases, even if not called from
3708 fdabc366 bellard
       generated code */
3709 fdabc366 bellard
    saved_env = env;
3710 fdabc366 bellard
    env = cpu_single_env;
3711 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3712 76a66253 j_mayer
    if (unlikely(ret != 0)) {
3713 fdabc366 bellard
        if (likely(retaddr)) {
3714 fdabc366 bellard
            /* now we have a real cpu fault */
3715 44f8625d bellard
            pc = (unsigned long)retaddr;
3716 fdabc366 bellard
            tb = tb_find_pc(pc);
3717 fdabc366 bellard
            if (likely(tb)) {
3718 fdabc366 bellard
                /* the PC is inside the translated code. It means that we have
3719 fdabc366 bellard
                   a virtual CPU fault */
3720 fdabc366 bellard
                cpu_restore_state(tb, env, pc, NULL);
3721 76a66253 j_mayer
            }
3722 fdabc366 bellard
        }
3723 e06fcd75 aurel32
        helper_raise_exception_err(env->exception_index, env->error_code);
3724 fdabc366 bellard
    }
3725 fdabc366 bellard
    env = saved_env;
3726 9a64fbe4 bellard
}
3727 9a64fbe4 bellard
3728 74d37793 aurel32
/* Segment registers load and store */
3729 74d37793 aurel32
target_ulong helper_load_sr (target_ulong sr_num)
3730 74d37793 aurel32
{
3731 f6b868fc blueswir1
#if defined(TARGET_PPC64)
3732 f6b868fc blueswir1
    if (env->mmu_model & POWERPC_MMU_64)
3733 f6b868fc blueswir1
        return ppc_load_sr(env, sr_num);
3734 f6b868fc blueswir1
#endif
3735 74d37793 aurel32
    return env->sr[sr_num];
3736 74d37793 aurel32
}
3737 74d37793 aurel32
3738 74d37793 aurel32
void helper_store_sr (target_ulong sr_num, target_ulong val)
3739 74d37793 aurel32
{
3740 45d827d2 aurel32
    ppc_store_sr(env, sr_num, val);
3741 74d37793 aurel32
}
3742 74d37793 aurel32
3743 74d37793 aurel32
/* SLB management */
3744 74d37793 aurel32
#if defined(TARGET_PPC64)
3745 74d37793 aurel32
target_ulong helper_load_slb (target_ulong slb_nr)
3746 74d37793 aurel32
{
3747 74d37793 aurel32
    return ppc_load_slb(env, slb_nr);
3748 74d37793 aurel32
}
3749 74d37793 aurel32
3750 f6b868fc blueswir1
void helper_store_slb (target_ulong rb, target_ulong rs)
3751 74d37793 aurel32
{
3752 f6b868fc blueswir1
    ppc_store_slb(env, rb, rs);
3753 74d37793 aurel32
}
3754 74d37793 aurel32
3755 74d37793 aurel32
void helper_slbia (void)
3756 74d37793 aurel32
{
3757 74d37793 aurel32
    ppc_slb_invalidate_all(env);
3758 74d37793 aurel32
}
3759 74d37793 aurel32
3760 74d37793 aurel32
void helper_slbie (target_ulong addr)
3761 74d37793 aurel32
{
3762 74d37793 aurel32
    ppc_slb_invalidate_one(env, addr);
3763 74d37793 aurel32
}
3764 74d37793 aurel32
3765 74d37793 aurel32
#endif /* defined(TARGET_PPC64) */
3766 74d37793 aurel32
3767 74d37793 aurel32
/* TLB management */
3768 74d37793 aurel32
void helper_tlbia (void)
3769 74d37793 aurel32
{
3770 74d37793 aurel32
    ppc_tlb_invalidate_all(env);
3771 74d37793 aurel32
}
3772 74d37793 aurel32
3773 74d37793 aurel32
void helper_tlbie (target_ulong addr)
3774 74d37793 aurel32
{
3775 74d37793 aurel32
    ppc_tlb_invalidate_one(env, addr);
3776 74d37793 aurel32
}
3777 74d37793 aurel32
3778 76a66253 j_mayer
/* Software driven TLBs management */
3779 76a66253 j_mayer
/* PowerPC 602/603 software TLB load instructions helpers */
3780 74d37793 aurel32
static void do_6xx_tlb (target_ulong new_EPN, int is_code)
3781 76a66253 j_mayer
{
3782 76a66253 j_mayer
    target_ulong RPN, CMP, EPN;
3783 76a66253 j_mayer
    int way;
3784 d9bce9d9 j_mayer
3785 76a66253 j_mayer
    RPN = env->spr[SPR_RPA];
3786 76a66253 j_mayer
    if (is_code) {
3787 76a66253 j_mayer
        CMP = env->spr[SPR_ICMP];
3788 76a66253 j_mayer
        EPN = env->spr[SPR_IMISS];
3789 76a66253 j_mayer
    } else {
3790 76a66253 j_mayer
        CMP = env->spr[SPR_DCMP];
3791 76a66253 j_mayer
        EPN = env->spr[SPR_DMISS];
3792 76a66253 j_mayer
    }
3793 76a66253 j_mayer
    way = (env->spr[SPR_SRR1] >> 17) & 1;
3794 d12d51d5 aliguori
    LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3795 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
3796 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
3797 76a66253 j_mayer
    /* Store this TLB */
3798 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3799 d9bce9d9 j_mayer
                     way, is_code, CMP, RPN);
3800 76a66253 j_mayer
}
3801 76a66253 j_mayer
3802 74d37793 aurel32
void helper_6xx_tlbd (target_ulong EPN)
3803 0f3955e2 aurel32
{
3804 74d37793 aurel32
    do_6xx_tlb(EPN, 0);
3805 0f3955e2 aurel32
}
3806 0f3955e2 aurel32
3807 74d37793 aurel32
void helper_6xx_tlbi (target_ulong EPN)
3808 0f3955e2 aurel32
{
3809 74d37793 aurel32
    do_6xx_tlb(EPN, 1);
3810 0f3955e2 aurel32
}
3811 0f3955e2 aurel32
3812 0f3955e2 aurel32
/* PowerPC 74xx software TLB load instructions helpers */
3813 74d37793 aurel32
static void do_74xx_tlb (target_ulong new_EPN, int is_code)
3814 7dbe11ac j_mayer
{
3815 7dbe11ac j_mayer
    target_ulong RPN, CMP, EPN;
3816 7dbe11ac j_mayer
    int way;
3817 7dbe11ac j_mayer
3818 7dbe11ac j_mayer
    RPN = env->spr[SPR_PTELO];
3819 7dbe11ac j_mayer
    CMP = env->spr[SPR_PTEHI];
3820 7dbe11ac j_mayer
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
3821 7dbe11ac j_mayer
    way = env->spr[SPR_TLBMISS] & 0x3;
3822 d12d51d5 aliguori
    LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3823 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
3824 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
3825 7dbe11ac j_mayer
    /* Store this TLB */
3826 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3827 7dbe11ac j_mayer
                     way, is_code, CMP, RPN);
3828 7dbe11ac j_mayer
}
3829 7dbe11ac j_mayer
3830 74d37793 aurel32
void helper_74xx_tlbd (target_ulong EPN)
3831 0f3955e2 aurel32
{
3832 74d37793 aurel32
    do_74xx_tlb(EPN, 0);
3833 0f3955e2 aurel32
}
3834 0f3955e2 aurel32
3835 74d37793 aurel32
void helper_74xx_tlbi (target_ulong EPN)
3836 0f3955e2 aurel32
{
3837 74d37793 aurel32
    do_74xx_tlb(EPN, 1);
3838 0f3955e2 aurel32
}
3839 0f3955e2 aurel32
3840 a11b8151 j_mayer
static always_inline target_ulong booke_tlb_to_page_size (int size)
3841 a8dea12f j_mayer
{
3842 a8dea12f j_mayer
    return 1024 << (2 * size);
3843 a8dea12f j_mayer
}
3844 a8dea12f j_mayer
3845 a11b8151 j_mayer
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
3846 a8dea12f j_mayer
{
3847 a8dea12f j_mayer
    int size;
3848 a8dea12f j_mayer
3849 a8dea12f j_mayer
    switch (page_size) {
3850 a8dea12f j_mayer
    case 0x00000400UL:
3851 a8dea12f j_mayer
        size = 0x0;
3852 a8dea12f j_mayer
        break;
3853 a8dea12f j_mayer
    case 0x00001000UL:
3854 a8dea12f j_mayer
        size = 0x1;
3855 a8dea12f j_mayer
        break;
3856 a8dea12f j_mayer
    case 0x00004000UL:
3857 a8dea12f j_mayer
        size = 0x2;
3858 a8dea12f j_mayer
        break;
3859 a8dea12f j_mayer
    case 0x00010000UL:
3860 a8dea12f j_mayer
        size = 0x3;
3861 a8dea12f j_mayer
        break;
3862 a8dea12f j_mayer
    case 0x00040000UL:
3863 a8dea12f j_mayer
        size = 0x4;
3864 a8dea12f j_mayer
        break;
3865 a8dea12f j_mayer
    case 0x00100000UL:
3866 a8dea12f j_mayer
        size = 0x5;
3867 a8dea12f j_mayer
        break;
3868 a8dea12f j_mayer
    case 0x00400000UL:
3869 a8dea12f j_mayer
        size = 0x6;
3870 a8dea12f j_mayer
        break;
3871 a8dea12f j_mayer
    case 0x01000000UL:
3872 a8dea12f j_mayer
        size = 0x7;
3873 a8dea12f j_mayer
        break;
3874 a8dea12f j_mayer
    case 0x04000000UL:
3875 a8dea12f j_mayer
        size = 0x8;
3876 a8dea12f j_mayer
        break;
3877 a8dea12f j_mayer
    case 0x10000000UL:
3878 a8dea12f j_mayer
        size = 0x9;
3879 a8dea12f j_mayer
        break;
3880 a8dea12f j_mayer
    case 0x40000000UL:
3881 a8dea12f j_mayer
        size = 0xA;
3882 a8dea12f j_mayer
        break;
3883 a8dea12f j_mayer
#if defined (TARGET_PPC64)
3884 a8dea12f j_mayer
    case 0x000100000000ULL:
3885 a8dea12f j_mayer
        size = 0xB;
3886 a8dea12f j_mayer
        break;
3887 a8dea12f j_mayer
    case 0x000400000000ULL:
3888 a8dea12f j_mayer
        size = 0xC;
3889 a8dea12f j_mayer
        break;
3890 a8dea12f j_mayer
    case 0x001000000000ULL:
3891 a8dea12f j_mayer
        size = 0xD;
3892 a8dea12f j_mayer
        break;
3893 a8dea12f j_mayer
    case 0x004000000000ULL:
3894 a8dea12f j_mayer
        size = 0xE;
3895 a8dea12f j_mayer
        break;
3896 a8dea12f j_mayer
    case 0x010000000000ULL:
3897 a8dea12f j_mayer
        size = 0xF;
3898 a8dea12f j_mayer
        break;
3899 a8dea12f j_mayer
#endif
3900 a8dea12f j_mayer
    default:
3901 a8dea12f j_mayer
        size = -1;
3902 a8dea12f j_mayer
        break;
3903 a8dea12f j_mayer
    }
3904 a8dea12f j_mayer
3905 a8dea12f j_mayer
    return size;
3906 a8dea12f j_mayer
}
3907 a8dea12f j_mayer
3908 76a66253 j_mayer
/* Helpers for 4xx TLB management */
3909 74d37793 aurel32
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
3910 76a66253 j_mayer
{
3911 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3912 74d37793 aurel32
    target_ulong ret;
3913 a8dea12f j_mayer
    int size;
3914 76a66253 j_mayer
3915 74d37793 aurel32
    entry &= 0x3F;
3916 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3917 74d37793 aurel32
    ret = tlb->EPN;
3918 a8dea12f j_mayer
    if (tlb->prot & PAGE_VALID)
3919 74d37793 aurel32
        ret |= 0x400;
3920 a8dea12f j_mayer
    size = booke_page_size_to_tlb(tlb->size);
3921 a8dea12f j_mayer
    if (size < 0 || size > 0x7)
3922 a8dea12f j_mayer
        size = 1;
3923 74d37793 aurel32
    ret |= size << 7;
3924 a8dea12f j_mayer
    env->spr[SPR_40x_PID] = tlb->PID;
3925 74d37793 aurel32
    return ret;
3926 76a66253 j_mayer
}
3927 76a66253 j_mayer
3928 74d37793 aurel32
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
3929 76a66253 j_mayer
{
3930 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3931 74d37793 aurel32
    target_ulong ret;
3932 76a66253 j_mayer
3933 74d37793 aurel32
    entry &= 0x3F;
3934 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3935 74d37793 aurel32
    ret = tlb->RPN;
3936 a8dea12f j_mayer
    if (tlb->prot & PAGE_EXEC)
3937 74d37793 aurel32
        ret |= 0x200;
3938 a8dea12f j_mayer
    if (tlb->prot & PAGE_WRITE)
3939 74d37793 aurel32
        ret |= 0x100;
3940 74d37793 aurel32
    return ret;
3941 76a66253 j_mayer
}
3942 76a66253 j_mayer
3943 74d37793 aurel32
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
3944 76a66253 j_mayer
{
3945 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3946 76a66253 j_mayer
    target_ulong page, end;
3947 76a66253 j_mayer
3948 d12d51d5 aliguori
    LOG_SWTLB("%s entry %d val " ADDRX "\n", __func__, (int)entry, val);
3949 74d37793 aurel32
    entry &= 0x3F;
3950 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3951 76a66253 j_mayer
    /* Invalidate previous TLB (if it's valid) */
3952 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
3953 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
3954 d12d51d5 aliguori
        LOG_SWTLB("%s: invalidate old TLB %d start " ADDRX
3955 74d37793 aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3956 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3957 76a66253 j_mayer
            tlb_flush_page(env, page);
3958 76a66253 j_mayer
    }
3959 74d37793 aurel32
    tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
3960 c294fc58 j_mayer
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
3961 c294fc58 j_mayer
     * If this ever occurs, one should use the ppcemb target instead
3962 c294fc58 j_mayer
     * of the ppc or ppc64 one
3963 c294fc58 j_mayer
     */
3964 74d37793 aurel32
    if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
3965 71c8b8fd j_mayer
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
3966 71c8b8fd j_mayer
                  "are not supported (%d)\n",
3967 74d37793 aurel32
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
3968 c294fc58 j_mayer
    }
3969 74d37793 aurel32
    tlb->EPN = val & ~(tlb->size - 1);
3970 74d37793 aurel32
    if (val & 0x40)
3971 76a66253 j_mayer
        tlb->prot |= PAGE_VALID;
3972 76a66253 j_mayer
    else
3973 76a66253 j_mayer
        tlb->prot &= ~PAGE_VALID;
3974 74d37793 aurel32
    if (val & 0x20) {
3975 c294fc58 j_mayer
        /* XXX: TO BE FIXED */
3976 c294fc58 j_mayer
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
3977 c294fc58 j_mayer
    }
3978 c55e9aef j_mayer
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
3979 74d37793 aurel32
    tlb->attr = val & 0xFF;
3980 d12d51d5 aliguori
    LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3981 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3982 0e69805a aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3983 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
3984 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3985 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3986 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3987 76a66253 j_mayer
    /* Invalidate new TLB (if valid) */
3988 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
3989 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
3990 d12d51d5 aliguori
        LOG_SWTLB("%s: invalidate TLB %d start " ADDRX
3991 0e69805a aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3992 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3993 76a66253 j_mayer
            tlb_flush_page(env, page);
3994 76a66253 j_mayer
    }
3995 76a66253 j_mayer
}
3996 76a66253 j_mayer
3997 74d37793 aurel32
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
3998 76a66253 j_mayer
{
3999 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
4000 76a66253 j_mayer
4001 d12d51d5 aliguori
    LOG_SWTLB("%s entry %i val " ADDRX "\n", __func__, (int)entry, val);
4002 74d37793 aurel32
    entry &= 0x3F;
4003 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
4004 74d37793 aurel32
    tlb->RPN = val & 0xFFFFFC00;
4005 76a66253 j_mayer
    tlb->prot = PAGE_READ;
4006 74d37793 aurel32
    if (val & 0x200)
4007 76a66253 j_mayer
        tlb->prot |= PAGE_EXEC;
4008 74d37793 aurel32
    if (val & 0x100)
4009 76a66253 j_mayer
        tlb->prot |= PAGE_WRITE;
4010 d12d51d5 aliguori
    LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
4011 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
4012 74d37793 aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
4013 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
4014 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
4015 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
4016 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
4017 76a66253 j_mayer
}
4018 5eb7995e j_mayer
4019 74d37793 aurel32
target_ulong helper_4xx_tlbsx (target_ulong address)
4020 74d37793 aurel32
{
4021 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
4022 74d37793 aurel32
}
4023 74d37793 aurel32
4024 a4bb6c3e j_mayer
/* PowerPC 440 TLB management */
4025 74d37793 aurel32
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
4026 5eb7995e j_mayer
{
4027 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
4028 a4bb6c3e j_mayer
    target_ulong EPN, RPN, size;
4029 5eb7995e j_mayer
    int do_flush_tlbs;
4030 5eb7995e j_mayer
4031 d12d51d5 aliguori
    LOG_SWTLB("%s word %d entry %d value " ADDRX "\n",
4032 0e69805a aurel32
                __func__, word, (int)entry, value);
4033 5eb7995e j_mayer
    do_flush_tlbs = 0;
4034 74d37793 aurel32
    entry &= 0x3F;
4035 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
4036 a4bb6c3e j_mayer
    switch (word) {
4037 a4bb6c3e j_mayer
    default:
4038 a4bb6c3e j_mayer
        /* Just here to please gcc */
4039 a4bb6c3e j_mayer
    case 0:
4040 74d37793 aurel32
        EPN = value & 0xFFFFFC00;
4041 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
4042 5eb7995e j_mayer
            do_flush_tlbs = 1;
4043 a4bb6c3e j_mayer
        tlb->EPN = EPN;
4044 74d37793 aurel32
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
4045 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
4046 a4bb6c3e j_mayer
            do_flush_tlbs = 1;
4047 a4bb6c3e j_mayer
        tlb->size = size;
4048 a4bb6c3e j_mayer
        tlb->attr &= ~0x1;
4049 74d37793 aurel32
        tlb->attr |= (value >> 8) & 1;
4050 74d37793 aurel32
        if (value & 0x200) {
4051 a4bb6c3e j_mayer
            tlb->prot |= PAGE_VALID;
4052 a4bb6c3e j_mayer
        } else {
4053 a4bb6c3e j_mayer
            if (tlb->prot & PAGE_VALID) {
4054 a4bb6c3e j_mayer
                tlb->prot &= ~PAGE_VALID;
4055 a4bb6c3e j_mayer
                do_flush_tlbs = 1;
4056 a4bb6c3e j_mayer
            }
4057 5eb7995e j_mayer
        }
4058 a4bb6c3e j_mayer
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
4059 a4bb6c3e j_mayer
        if (do_flush_tlbs)
4060 a4bb6c3e j_mayer
            tlb_flush(env, 1);
4061 a4bb6c3e j_mayer
        break;
4062 a4bb6c3e j_mayer
    case 1:
4063 74d37793 aurel32
        RPN = value & 0xFFFFFC0F;
4064 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
4065 a4bb6c3e j_mayer
            tlb_flush(env, 1);
4066 a4bb6c3e j_mayer
        tlb->RPN = RPN;
4067 a4bb6c3e j_mayer
        break;
4068 a4bb6c3e j_mayer
    case 2:
4069 74d37793 aurel32
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
4070 a4bb6c3e j_mayer
        tlb->prot = tlb->prot & PAGE_VALID;
4071 74d37793 aurel32
        if (value & 0x1)
4072 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ << 4;
4073 74d37793 aurel32
        if (value & 0x2)
4074 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE << 4;
4075 74d37793 aurel32
        if (value & 0x4)
4076 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC << 4;
4077 74d37793 aurel32
        if (value & 0x8)
4078 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ;
4079 74d37793 aurel32
        if (value & 0x10)
4080 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE;
4081 74d37793 aurel32
        if (value & 0x20)
4082 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC;
4083 a4bb6c3e j_mayer
        break;
4084 5eb7995e j_mayer
    }
4085 5eb7995e j_mayer
}
4086 5eb7995e j_mayer
4087 74d37793 aurel32
target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
4088 5eb7995e j_mayer
{
4089 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
4090 74d37793 aurel32
    target_ulong ret;
4091 5eb7995e j_mayer
    int size;
4092 5eb7995e j_mayer
4093 74d37793 aurel32
    entry &= 0x3F;
4094 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
4095 a4bb6c3e j_mayer
    switch (word) {
4096 a4bb6c3e j_mayer
    default:
4097 a4bb6c3e j_mayer
        /* Just here to please gcc */
4098 a4bb6c3e j_mayer
    case 0:
4099 74d37793 aurel32
        ret = tlb->EPN;
4100 a4bb6c3e j_mayer
        size = booke_page_size_to_tlb(tlb->size);
4101 a4bb6c3e j_mayer
        if (size < 0 || size > 0xF)
4102 a4bb6c3e j_mayer
            size = 1;
4103 74d37793 aurel32
        ret |= size << 4;
4104 a4bb6c3e j_mayer
        if (tlb->attr & 0x1)
4105 74d37793 aurel32
            ret |= 0x100;
4106 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_VALID)
4107 74d37793 aurel32
            ret |= 0x200;
4108 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
4109 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] |= tlb->PID;
4110 a4bb6c3e j_mayer
        break;
4111 a4bb6c3e j_mayer
    case 1:
4112 74d37793 aurel32
        ret = tlb->RPN;
4113 a4bb6c3e j_mayer
        break;
4114 a4bb6c3e j_mayer
    case 2:
4115 74d37793 aurel32
        ret = tlb->attr & ~0x1;
4116 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_READ << 4))
4117 74d37793 aurel32
            ret |= 0x1;
4118 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_WRITE << 4))
4119 74d37793 aurel32
            ret |= 0x2;
4120 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_EXEC << 4))
4121 74d37793 aurel32
            ret |= 0x4;
4122 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_READ)
4123 74d37793 aurel32
            ret |= 0x8;
4124 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_WRITE)
4125 74d37793 aurel32
            ret |= 0x10;
4126 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_EXEC)
4127 74d37793 aurel32
            ret |= 0x20;
4128 a4bb6c3e j_mayer
        break;
4129 a4bb6c3e j_mayer
    }
4130 74d37793 aurel32
    return ret;
4131 5eb7995e j_mayer
}
4132 74d37793 aurel32
4133 74d37793 aurel32
target_ulong helper_440_tlbsx (target_ulong address)
4134 74d37793 aurel32
{
4135 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
4136 74d37793 aurel32
}
4137 74d37793 aurel32
4138 76a66253 j_mayer
#endif /* !CONFIG_USER_ONLY */