Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ a74cdab4

History | View | Annotate | Download (134.3 kB)

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