Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ c3d420ea

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