Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ a15bb0d6

History | View | Annotate | Download (134.3 kB)

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