Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 2c0d18dd

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