Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 136be99e

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