Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 93fcfe39

History | View | Annotate | Download (113.1 kB)

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