Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ efdef95f

History | View | Annotate | Download (125.1 kB)

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