Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ eaabeef2

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