Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 0497d2f4

History | View | Annotate | Download (124.4 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 c609b12e aurel32
    CPU_DoubleU farg;
1505 06f7332a aurel32
    farg.ll = arg;
1506 d7e4b87e j_mayer
1507 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1508 7c58044c j_mayer
        /* sNaN reciprocal */
1509 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1510 d7e4b87e j_mayer
    } else {
1511 c609b12e aurel32
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1512 d7e4b87e j_mayer
    }
1513 af12906f aurel32
    return farg.d;
1514 d7e4b87e j_mayer
}
1515 d7e4b87e j_mayer
1516 af12906f aurel32
/* fres - fres. */
1517 af12906f aurel32
uint64_t helper_fres (uint64_t arg)
1518 9a64fbe4 bellard
{
1519 06f7332a aurel32
    CPU_DoubleU farg;
1520 6c01bf6c aurel32
    float32 f32;
1521 06f7332a aurel32
    farg.ll = arg;
1522 4ecc3190 bellard
1523 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1524 7c58044c j_mayer
        /* sNaN reciprocal */
1525 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1526 4ecc3190 bellard
    } else {
1527 c609b12e aurel32
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1528 6c01bf6c aurel32
        f32 = float64_to_float32(farg.d, &env->fp_status);
1529 6c01bf6c aurel32
        farg.d = float32_to_float64(f32, &env->fp_status);
1530 4ecc3190 bellard
    }
1531 af12906f aurel32
    return farg.ll;
1532 9a64fbe4 bellard
}
1533 9a64fbe4 bellard
1534 af12906f aurel32
/* frsqrte  - frsqrte. */
1535 af12906f aurel32
uint64_t helper_frsqrte (uint64_t arg)
1536 9a64fbe4 bellard
{
1537 c609b12e aurel32
    CPU_DoubleU farg;
1538 6c01bf6c aurel32
    float32 f32;
1539 06f7332a aurel32
    farg.ll = arg;
1540 4ecc3190 bellard
1541 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1542 7c58044c j_mayer
        /* sNaN reciprocal square root */
1543 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1544 f23c346e aurel32
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1545 7c58044c j_mayer
        /* Reciprocal square root of a negative nonzero number */
1546 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1547 4ecc3190 bellard
    } else {
1548 6c01bf6c aurel32
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1549 c609b12e aurel32
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1550 6c01bf6c aurel32
        f32 = float64_to_float32(farg.d, &env->fp_status);
1551 6c01bf6c aurel32
        farg.d = float32_to_float64(f32, &env->fp_status);
1552 4ecc3190 bellard
    }
1553 af12906f aurel32
    return farg.ll;
1554 9a64fbe4 bellard
}
1555 9a64fbe4 bellard
1556 af12906f aurel32
/* fsel - fsel. */
1557 af12906f aurel32
uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1558 9a64fbe4 bellard
{
1559 6ad7365a aurel32
    CPU_DoubleU farg1;
1560 af12906f aurel32
1561 af12906f aurel32
    farg1.ll = arg1;
1562 af12906f aurel32
1563 572c8952 aurel32
    if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_nan(farg1.d))
1564 6ad7365a aurel32
        return arg2;
1565 4ecc3190 bellard
    else
1566 6ad7365a aurel32
        return arg3;
1567 9a64fbe4 bellard
}
1568 9a64fbe4 bellard
1569 9a819377 aurel32
void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1570 9a64fbe4 bellard
{
1571 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1572 e1571908 aurel32
    uint32_t ret = 0;
1573 af12906f aurel32
    farg1.ll = arg1;
1574 af12906f aurel32
    farg2.ll = arg2;
1575 e1571908 aurel32
1576 9a819377 aurel32
    if (unlikely(float64_is_nan(farg1.d) ||
1577 9a819377 aurel32
                 float64_is_nan(farg2.d))) {
1578 9a819377 aurel32
        ret = 0x01UL;
1579 9a819377 aurel32
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1580 9a819377 aurel32
        ret = 0x08UL;
1581 9a819377 aurel32
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1582 9a819377 aurel32
        ret = 0x04UL;
1583 7c58044c j_mayer
    } else {
1584 9a819377 aurel32
        ret = 0x02UL;
1585 9a64fbe4 bellard
    }
1586 9a819377 aurel32
1587 7c58044c j_mayer
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1588 e1571908 aurel32
    env->fpscr |= ret << FPSCR_FPRF;
1589 9a819377 aurel32
    env->crf[crfD] = ret;
1590 9a819377 aurel32
    if (unlikely(ret == 0x01UL
1591 9a819377 aurel32
                 && (float64_is_signaling_nan(farg1.d) ||
1592 9a819377 aurel32
                     float64_is_signaling_nan(farg2.d)))) {
1593 9a819377 aurel32
        /* sNaN comparison */
1594 9a819377 aurel32
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1595 9a819377 aurel32
    }
1596 9a64fbe4 bellard
}
1597 9a64fbe4 bellard
1598 9a819377 aurel32
void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1599 9a64fbe4 bellard
{
1600 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1601 e1571908 aurel32
    uint32_t ret = 0;
1602 af12906f aurel32
    farg1.ll = arg1;
1603 af12906f aurel32
    farg2.ll = arg2;
1604 e1571908 aurel32
1605 af12906f aurel32
    if (unlikely(float64_is_nan(farg1.d) ||
1606 af12906f aurel32
                 float64_is_nan(farg2.d))) {
1607 9a819377 aurel32
        ret = 0x01UL;
1608 9a819377 aurel32
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1609 9a819377 aurel32
        ret = 0x08UL;
1610 9a819377 aurel32
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1611 9a819377 aurel32
        ret = 0x04UL;
1612 9a819377 aurel32
    } else {
1613 9a819377 aurel32
        ret = 0x02UL;
1614 9a819377 aurel32
    }
1615 9a819377 aurel32
1616 9a819377 aurel32
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1617 9a819377 aurel32
    env->fpscr |= ret << FPSCR_FPRF;
1618 9a819377 aurel32
    env->crf[crfD] = ret;
1619 9a819377 aurel32
    if (unlikely (ret == 0x01UL)) {
1620 af12906f aurel32
        if (float64_is_signaling_nan(farg1.d) ||
1621 af12906f aurel32
            float64_is_signaling_nan(farg2.d)) {
1622 7c58044c j_mayer
            /* sNaN comparison */
1623 7c58044c j_mayer
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1624 7c58044c j_mayer
                                  POWERPC_EXCP_FP_VXVC);
1625 7c58044c j_mayer
        } else {
1626 7c58044c j_mayer
            /* qNaN comparison */
1627 7c58044c j_mayer
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1628 7c58044c j_mayer
        }
1629 9a64fbe4 bellard
    }
1630 9a64fbe4 bellard
}
1631 9a64fbe4 bellard
1632 76a66253 j_mayer
#if !defined (CONFIG_USER_ONLY)
1633 6527f6ea aurel32
void helper_store_msr (target_ulong val)
1634 0411a972 j_mayer
{
1635 6527f6ea aurel32
    val = hreg_store_msr(env, val, 0);
1636 6527f6ea aurel32
    if (val != 0) {
1637 0411a972 j_mayer
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1638 e06fcd75 aurel32
        helper_raise_exception(val);
1639 0411a972 j_mayer
    }
1640 0411a972 j_mayer
}
1641 0411a972 j_mayer
1642 d72a19f7 aurel32
static always_inline void do_rfi (target_ulong nip, target_ulong msr,
1643 0411a972 j_mayer
                                    target_ulong msrm, int keep_msrh)
1644 9a64fbe4 bellard
{
1645 426613db j_mayer
#if defined(TARGET_PPC64)
1646 0411a972 j_mayer
    if (msr & (1ULL << MSR_SF)) {
1647 0411a972 j_mayer
        nip = (uint64_t)nip;
1648 0411a972 j_mayer
        msr &= (uint64_t)msrm;
1649 a42bd6cc j_mayer
    } else {
1650 0411a972 j_mayer
        nip = (uint32_t)nip;
1651 0411a972 j_mayer
        msr = (uint32_t)(msr & msrm);
1652 0411a972 j_mayer
        if (keep_msrh)
1653 0411a972 j_mayer
            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
1654 a42bd6cc j_mayer
    }
1655 426613db j_mayer
#else
1656 0411a972 j_mayer
    nip = (uint32_t)nip;
1657 0411a972 j_mayer
    msr &= (uint32_t)msrm;
1658 426613db j_mayer
#endif
1659 0411a972 j_mayer
    /* XXX: beware: this is false if VLE is supported */
1660 0411a972 j_mayer
    env->nip = nip & ~((target_ulong)0x00000003);
1661 a4f30719 j_mayer
    hreg_store_msr(env, msr, 1);
1662 fdabc366 bellard
#if defined (DEBUG_OP)
1663 0411a972 j_mayer
    cpu_dump_rfi(env->nip, env->msr);
1664 fdabc366 bellard
#endif
1665 0411a972 j_mayer
    /* No need to raise an exception here,
1666 0411a972 j_mayer
     * as rfi is always the last insn of a TB
1667 0411a972 j_mayer
     */
1668 fdabc366 bellard
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1669 9a64fbe4 bellard
}
1670 d9bce9d9 j_mayer
1671 d72a19f7 aurel32
void helper_rfi (void)
1672 0411a972 j_mayer
{
1673 d72a19f7 aurel32
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1674 2ada0ed7 blueswir1
           ~((target_ulong)0x0), 1);
1675 0411a972 j_mayer
}
1676 0411a972 j_mayer
1677 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1678 d72a19f7 aurel32
void helper_rfid (void)
1679 426613db j_mayer
{
1680 d72a19f7 aurel32
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1681 2ada0ed7 blueswir1
           ~((target_ulong)0x0), 0);
1682 d9bce9d9 j_mayer
}
1683 7863667f j_mayer
1684 d72a19f7 aurel32
void helper_hrfid (void)
1685 be147d08 j_mayer
{
1686 d72a19f7 aurel32
    do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
1687 2ada0ed7 blueswir1
           ~((target_ulong)0x0), 0);
1688 be147d08 j_mayer
}
1689 be147d08 j_mayer
#endif
1690 76a66253 j_mayer
#endif
1691 9a64fbe4 bellard
1692 cab3bee2 aurel32
void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
1693 9a64fbe4 bellard
{
1694 cab3bee2 aurel32
    if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1695 cab3bee2 aurel32
                  ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1696 cab3bee2 aurel32
                  ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1697 cab3bee2 aurel32
                  ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1698 cab3bee2 aurel32
                  ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1699 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1700 a42bd6cc j_mayer
    }
1701 9a64fbe4 bellard
}
1702 9a64fbe4 bellard
1703 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1704 cab3bee2 aurel32
void helper_td (target_ulong arg1, target_ulong arg2, uint32_t flags)
1705 d9bce9d9 j_mayer
{
1706 cab3bee2 aurel32
    if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1707 cab3bee2 aurel32
                  ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1708 cab3bee2 aurel32
                  ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1709 cab3bee2 aurel32
                  ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1710 cab3bee2 aurel32
                  ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01)))))
1711 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1712 d9bce9d9 j_mayer
}
1713 d9bce9d9 j_mayer
#endif
1714 d9bce9d9 j_mayer
1715 fdabc366 bellard
/*****************************************************************************/
1716 76a66253 j_mayer
/* PowerPC 601 specific instructions (POWER bridge) */
1717 9a64fbe4 bellard
1718 22e0e173 aurel32
target_ulong helper_clcs (uint32_t arg)
1719 9a64fbe4 bellard
{
1720 22e0e173 aurel32
    switch (arg) {
1721 76a66253 j_mayer
    case 0x0CUL:
1722 76a66253 j_mayer
        /* Instruction cache line size */
1723 22e0e173 aurel32
        return env->icache_line_size;
1724 76a66253 j_mayer
        break;
1725 76a66253 j_mayer
    case 0x0DUL:
1726 76a66253 j_mayer
        /* Data cache line size */
1727 22e0e173 aurel32
        return env->dcache_line_size;
1728 76a66253 j_mayer
        break;
1729 76a66253 j_mayer
    case 0x0EUL:
1730 76a66253 j_mayer
        /* Minimum cache line size */
1731 22e0e173 aurel32
        return (env->icache_line_size < env->dcache_line_size) ?
1732 22e0e173 aurel32
                env->icache_line_size : env->dcache_line_size;
1733 76a66253 j_mayer
        break;
1734 76a66253 j_mayer
    case 0x0FUL:
1735 76a66253 j_mayer
        /* Maximum cache line size */
1736 22e0e173 aurel32
        return (env->icache_line_size > env->dcache_line_size) ?
1737 22e0e173 aurel32
                env->icache_line_size : env->dcache_line_size;
1738 76a66253 j_mayer
        break;
1739 76a66253 j_mayer
    default:
1740 76a66253 j_mayer
        /* Undefined */
1741 22e0e173 aurel32
        return 0;
1742 76a66253 j_mayer
        break;
1743 76a66253 j_mayer
    }
1744 76a66253 j_mayer
}
1745 76a66253 j_mayer
1746 22e0e173 aurel32
target_ulong helper_div (target_ulong arg1, target_ulong arg2)
1747 76a66253 j_mayer
{
1748 22e0e173 aurel32
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1749 76a66253 j_mayer
1750 22e0e173 aurel32
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1751 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1752 76a66253 j_mayer
        env->spr[SPR_MQ] = 0;
1753 22e0e173 aurel32
        return INT32_MIN;
1754 76a66253 j_mayer
    } else {
1755 22e0e173 aurel32
        env->spr[SPR_MQ] = tmp % arg2;
1756 22e0e173 aurel32
        return  tmp / (int32_t)arg2;
1757 76a66253 j_mayer
    }
1758 76a66253 j_mayer
}
1759 76a66253 j_mayer
1760 22e0e173 aurel32
target_ulong helper_divo (target_ulong arg1, target_ulong arg2)
1761 76a66253 j_mayer
{
1762 22e0e173 aurel32
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1763 76a66253 j_mayer
1764 22e0e173 aurel32
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1765 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1766 3d7b417e aurel32
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
1767 76a66253 j_mayer
        env->spr[SPR_MQ] = 0;
1768 22e0e173 aurel32
        return INT32_MIN;
1769 76a66253 j_mayer
    } else {
1770 22e0e173 aurel32
        env->spr[SPR_MQ] = tmp % arg2;
1771 22e0e173 aurel32
        tmp /= (int32_t)arg2;
1772 22e0e173 aurel32
        if ((int32_t)tmp != tmp) {
1773 3d7b417e aurel32
            env->xer |= (1 << XER_OV) | (1 << XER_SO);
1774 76a66253 j_mayer
        } else {
1775 3d7b417e aurel32
            env->xer &= ~(1 << XER_OV);
1776 76a66253 j_mayer
        }
1777 22e0e173 aurel32
        return tmp;
1778 76a66253 j_mayer
    }
1779 76a66253 j_mayer
}
1780 76a66253 j_mayer
1781 22e0e173 aurel32
target_ulong helper_divs (target_ulong arg1, target_ulong arg2)
1782 76a66253 j_mayer
{
1783 22e0e173 aurel32
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1784 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1785 22e0e173 aurel32
        env->spr[SPR_MQ] = 0;
1786 22e0e173 aurel32
        return INT32_MIN;
1787 76a66253 j_mayer
    } else {
1788 22e0e173 aurel32
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1789 22e0e173 aurel32
        return (int32_t)arg1 / (int32_t)arg2;
1790 76a66253 j_mayer
    }
1791 76a66253 j_mayer
}
1792 76a66253 j_mayer
1793 22e0e173 aurel32
target_ulong helper_divso (target_ulong arg1, target_ulong arg2)
1794 76a66253 j_mayer
{
1795 22e0e173 aurel32
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1796 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1797 3d7b417e aurel32
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
1798 22e0e173 aurel32
        env->spr[SPR_MQ] = 0;
1799 22e0e173 aurel32
        return INT32_MIN;
1800 76a66253 j_mayer
    } else {
1801 3d7b417e aurel32
        env->xer &= ~(1 << XER_OV);
1802 22e0e173 aurel32
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1803 22e0e173 aurel32
        return (int32_t)arg1 / (int32_t)arg2;
1804 76a66253 j_mayer
    }
1805 76a66253 j_mayer
}
1806 76a66253 j_mayer
1807 76a66253 j_mayer
#if !defined (CONFIG_USER_ONLY)
1808 22e0e173 aurel32
target_ulong helper_rac (target_ulong addr)
1809 76a66253 j_mayer
{
1810 76a66253 j_mayer
    mmu_ctx_t ctx;
1811 faadf50e j_mayer
    int nb_BATs;
1812 22e0e173 aurel32
    target_ulong ret = 0;
1813 76a66253 j_mayer
1814 76a66253 j_mayer
    /* We don't have to generate many instances of this instruction,
1815 76a66253 j_mayer
     * as rac is supervisor only.
1816 76a66253 j_mayer
     */
1817 faadf50e j_mayer
    /* XXX: FIX THIS: Pretend we have no BAT */
1818 faadf50e j_mayer
    nb_BATs = env->nb_BATs;
1819 faadf50e j_mayer
    env->nb_BATs = 0;
1820 22e0e173 aurel32
    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0)
1821 22e0e173 aurel32
        ret = ctx.raddr;
1822 faadf50e j_mayer
    env->nb_BATs = nb_BATs;
1823 22e0e173 aurel32
    return ret;
1824 76a66253 j_mayer
}
1825 76a66253 j_mayer
1826 d72a19f7 aurel32
void helper_rfsvc (void)
1827 76a66253 j_mayer
{
1828 d72a19f7 aurel32
    do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1829 76a66253 j_mayer
}
1830 76a66253 j_mayer
#endif
1831 76a66253 j_mayer
1832 76a66253 j_mayer
/*****************************************************************************/
1833 76a66253 j_mayer
/* 602 specific instructions */
1834 76a66253 j_mayer
/* mfrom is the most crazy instruction ever seen, imho ! */
1835 76a66253 j_mayer
/* Real implementation uses a ROM table. Do the same */
1836 5e9ae189 aurel32
/* Extremly decomposed:
1837 5e9ae189 aurel32
 *                      -arg / 256
1838 5e9ae189 aurel32
 * return 256 * log10(10           + 1.0) + 0.5
1839 5e9ae189 aurel32
 */
1840 db9a16a7 aurel32
#if !defined (CONFIG_USER_ONLY)
1841 cf02a65c aurel32
target_ulong helper_602_mfrom (target_ulong arg)
1842 76a66253 j_mayer
{
1843 cf02a65c aurel32
    if (likely(arg < 602)) {
1844 76a66253 j_mayer
#include "mfrom_table.c"
1845 45d827d2 aurel32
        return mfrom_ROM_table[arg];
1846 76a66253 j_mayer
    } else {
1847 cf02a65c aurel32
        return 0;
1848 76a66253 j_mayer
    }
1849 76a66253 j_mayer
}
1850 db9a16a7 aurel32
#endif
1851 76a66253 j_mayer
1852 76a66253 j_mayer
/*****************************************************************************/
1853 76a66253 j_mayer
/* Embedded PowerPC specific helpers */
1854 76a66253 j_mayer
1855 a750fc0b j_mayer
/* XXX: to be improved to check access rights when in user-mode */
1856 06dca6a7 aurel32
target_ulong helper_load_dcr (target_ulong dcrn)
1857 a750fc0b j_mayer
{
1858 06dca6a7 aurel32
    target_ulong val = 0;
1859 a750fc0b j_mayer
1860 a750fc0b j_mayer
    if (unlikely(env->dcr_env == NULL)) {
1861 93fcfe39 aliguori
        qemu_log("No DCR environment\n");
1862 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1863 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1864 06dca6a7 aurel32
    } else if (unlikely(ppc_dcr_read(env->dcr_env, dcrn, &val) != 0)) {
1865 93fcfe39 aliguori
        qemu_log("DCR read error %d %03x\n", (int)dcrn, (int)dcrn);
1866 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1867 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1868 a750fc0b j_mayer
    }
1869 06dca6a7 aurel32
    return val;
1870 a750fc0b j_mayer
}
1871 a750fc0b j_mayer
1872 06dca6a7 aurel32
void helper_store_dcr (target_ulong dcrn, target_ulong val)
1873 a750fc0b j_mayer
{
1874 a750fc0b j_mayer
    if (unlikely(env->dcr_env == NULL)) {
1875 93fcfe39 aliguori
        qemu_log("No DCR environment\n");
1876 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1877 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1878 06dca6a7 aurel32
    } else if (unlikely(ppc_dcr_write(env->dcr_env, dcrn, val) != 0)) {
1879 93fcfe39 aliguori
        qemu_log("DCR write error %d %03x\n", (int)dcrn, (int)dcrn);
1880 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1881 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1882 a750fc0b j_mayer
    }
1883 a750fc0b j_mayer
}
1884 a750fc0b j_mayer
1885 76a66253 j_mayer
#if !defined(CONFIG_USER_ONLY)
1886 d72a19f7 aurel32
void helper_40x_rfci (void)
1887 76a66253 j_mayer
{
1888 d72a19f7 aurel32
    do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1889 d72a19f7 aurel32
           ~((target_ulong)0xFFFF0000), 0);
1890 a42bd6cc j_mayer
}
1891 a42bd6cc j_mayer
1892 d72a19f7 aurel32
void helper_rfci (void)
1893 a42bd6cc j_mayer
{
1894 d72a19f7 aurel32
    do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1895 d72a19f7 aurel32
           ~((target_ulong)0x3FFF0000), 0);
1896 a42bd6cc j_mayer
}
1897 a42bd6cc j_mayer
1898 d72a19f7 aurel32
void helper_rfdi (void)
1899 a42bd6cc j_mayer
{
1900 d72a19f7 aurel32
    do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1901 d72a19f7 aurel32
           ~((target_ulong)0x3FFF0000), 0);
1902 a42bd6cc j_mayer
}
1903 a42bd6cc j_mayer
1904 d72a19f7 aurel32
void helper_rfmci (void)
1905 a42bd6cc j_mayer
{
1906 d72a19f7 aurel32
    do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1907 d72a19f7 aurel32
           ~((target_ulong)0x3FFF0000), 0);
1908 76a66253 j_mayer
}
1909 76a66253 j_mayer
#endif
1910 76a66253 j_mayer
1911 76a66253 j_mayer
/* 440 specific */
1912 ef0d51af aurel32
target_ulong helper_dlmzb (target_ulong high, target_ulong low, uint32_t update_Rc)
1913 76a66253 j_mayer
{
1914 76a66253 j_mayer
    target_ulong mask;
1915 76a66253 j_mayer
    int i;
1916 76a66253 j_mayer
1917 76a66253 j_mayer
    i = 1;
1918 76a66253 j_mayer
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1919 ef0d51af aurel32
        if ((high & mask) == 0) {
1920 ef0d51af aurel32
            if (update_Rc) {
1921 ef0d51af aurel32
                env->crf[0] = 0x4;
1922 ef0d51af aurel32
            }
1923 76a66253 j_mayer
            goto done;
1924 ef0d51af aurel32
        }
1925 76a66253 j_mayer
        i++;
1926 76a66253 j_mayer
    }
1927 76a66253 j_mayer
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1928 ef0d51af aurel32
        if ((low & mask) == 0) {
1929 ef0d51af aurel32
            if (update_Rc) {
1930 ef0d51af aurel32
                env->crf[0] = 0x8;
1931 ef0d51af aurel32
            }
1932 ef0d51af aurel32
            goto done;
1933 ef0d51af aurel32
        }
1934 76a66253 j_mayer
        i++;
1935 76a66253 j_mayer
    }
1936 ef0d51af aurel32
    if (update_Rc) {
1937 ef0d51af aurel32
        env->crf[0] = 0x2;
1938 ef0d51af aurel32
    }
1939 76a66253 j_mayer
 done:
1940 ef0d51af aurel32
    env->xer = (env->xer & ~0x7F) | i;
1941 ef0d51af aurel32
    if (update_Rc) {
1942 ef0d51af aurel32
        env->crf[0] |= xer_so;
1943 ef0d51af aurel32
    }
1944 ef0d51af aurel32
    return i;
1945 fdabc366 bellard
}
1946 fdabc366 bellard
1947 1c97856d aurel32
/*****************************************************************************/
1948 d6a46fe8 aurel32
/* Altivec extension helpers */
1949 d6a46fe8 aurel32
#if defined(WORDS_BIGENDIAN)
1950 d6a46fe8 aurel32
#define HI_IDX 0
1951 d6a46fe8 aurel32
#define LO_IDX 1
1952 d6a46fe8 aurel32
#else
1953 d6a46fe8 aurel32
#define HI_IDX 1
1954 d6a46fe8 aurel32
#define LO_IDX 0
1955 d6a46fe8 aurel32
#endif
1956 d6a46fe8 aurel32
1957 d6a46fe8 aurel32
#if defined(WORDS_BIGENDIAN)
1958 d6a46fe8 aurel32
#define VECTOR_FOR_INORDER_I(index, element)            \
1959 d6a46fe8 aurel32
    for (index = 0; index < ARRAY_SIZE(r->element); index++)
1960 d6a46fe8 aurel32
#else
1961 d6a46fe8 aurel32
#define VECTOR_FOR_INORDER_I(index, element)            \
1962 d6a46fe8 aurel32
  for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
1963 d6a46fe8 aurel32
#endif
1964 d6a46fe8 aurel32
1965 34ba2857 aurel32
/* If X is a NaN, store the corresponding QNaN into RESULT.  Otherwise,
1966 34ba2857 aurel32
 * execute the following block.  */
1967 34ba2857 aurel32
#define DO_HANDLE_NAN(result, x)                \
1968 34ba2857 aurel32
    if (float32_is_nan(x) || float32_is_signaling_nan(x)) {     \
1969 34ba2857 aurel32
        CPU_FloatU __f;                                         \
1970 34ba2857 aurel32
        __f.f = x;                                              \
1971 34ba2857 aurel32
        __f.l = __f.l | (1 << 22);  /* Set QNaN bit. */         \
1972 34ba2857 aurel32
        result = __f.f;                                         \
1973 34ba2857 aurel32
    } else
1974 34ba2857 aurel32
1975 34ba2857 aurel32
#define HANDLE_NAN1(result, x)                  \
1976 34ba2857 aurel32
    DO_HANDLE_NAN(result, x)
1977 34ba2857 aurel32
#define HANDLE_NAN2(result, x, y)               \
1978 34ba2857 aurel32
    DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y)
1979 34ba2857 aurel32
#define HANDLE_NAN3(result, x, y, z)            \
1980 34ba2857 aurel32
    DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z)
1981 34ba2857 aurel32
1982 00d3b8f5 aurel32
/* Saturating arithmetic helpers.  */
1983 00d3b8f5 aurel32
#define SATCVT(from, to, from_type, to_type, min, max, use_min, use_max) \
1984 00d3b8f5 aurel32
    static always_inline to_type cvt##from##to (from_type x, int *sat)  \
1985 00d3b8f5 aurel32
    {                                                                   \
1986 00d3b8f5 aurel32
        to_type r;                                                      \
1987 00d3b8f5 aurel32
        if (use_min && x < min) {                                       \
1988 00d3b8f5 aurel32
            r = min;                                                    \
1989 00d3b8f5 aurel32
            *sat = 1;                                                   \
1990 00d3b8f5 aurel32
        } else if (use_max && x > max) {                                \
1991 00d3b8f5 aurel32
            r = max;                                                    \
1992 00d3b8f5 aurel32
            *sat = 1;                                                   \
1993 00d3b8f5 aurel32
        } else {                                                        \
1994 00d3b8f5 aurel32
            r = x;                                                      \
1995 00d3b8f5 aurel32
        }                                                               \
1996 00d3b8f5 aurel32
        return r;                                                       \
1997 00d3b8f5 aurel32
    }
1998 00d3b8f5 aurel32
SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX, 1, 1)
1999 00d3b8f5 aurel32
SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX, 1, 1)
2000 00d3b8f5 aurel32
SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX, 1, 1)
2001 00d3b8f5 aurel32
SATCVT(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX, 0, 1)
2002 00d3b8f5 aurel32
SATCVT(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX, 0, 1)
2003 00d3b8f5 aurel32
SATCVT(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX, 0, 1)
2004 00d3b8f5 aurel32
SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX, 1, 1)
2005 00d3b8f5 aurel32
SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX, 1, 1)
2006 00d3b8f5 aurel32
SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX, 1, 1)
2007 00d3b8f5 aurel32
#undef SATCVT
2008 00d3b8f5 aurel32
2009 cbfb6ae9 aurel32
#define LVE(name, access, swap, element)                        \
2010 cbfb6ae9 aurel32
    void helper_##name (ppc_avr_t *r, target_ulong addr)        \
2011 cbfb6ae9 aurel32
    {                                                           \
2012 cbfb6ae9 aurel32
        size_t n_elems = ARRAY_SIZE(r->element);                \
2013 cbfb6ae9 aurel32
        int adjust = HI_IDX*(n_elems-1);                        \
2014 cbfb6ae9 aurel32
        int sh = sizeof(r->element[0]) >> 1;                    \
2015 cbfb6ae9 aurel32
        int index = (addr & 0xf) >> sh;                         \
2016 cbfb6ae9 aurel32
        if(msr_le) {                                            \
2017 cbfb6ae9 aurel32
            r->element[LO_IDX ? index : (adjust - index)] = swap(access(addr)); \
2018 cbfb6ae9 aurel32
        } else {                                                        \
2019 cbfb6ae9 aurel32
            r->element[LO_IDX ? index : (adjust - index)] = access(addr); \
2020 cbfb6ae9 aurel32
        }                                                               \
2021 cbfb6ae9 aurel32
    }
2022 cbfb6ae9 aurel32
#define I(x) (x)
2023 cbfb6ae9 aurel32
LVE(lvebx, ldub, I, u8)
2024 cbfb6ae9 aurel32
LVE(lvehx, lduw, bswap16, u16)
2025 cbfb6ae9 aurel32
LVE(lvewx, ldl, bswap32, u32)
2026 cbfb6ae9 aurel32
#undef I
2027 cbfb6ae9 aurel32
#undef LVE
2028 cbfb6ae9 aurel32
2029 bf8d8ded aurel32
void helper_lvsl (ppc_avr_t *r, target_ulong sh)
2030 bf8d8ded aurel32
{
2031 bf8d8ded aurel32
    int i, j = (sh & 0xf);
2032 bf8d8ded aurel32
2033 bf8d8ded aurel32
    VECTOR_FOR_INORDER_I (i, u8) {
2034 bf8d8ded aurel32
        r->u8[i] = j++;
2035 bf8d8ded aurel32
    }
2036 bf8d8ded aurel32
}
2037 bf8d8ded aurel32
2038 bf8d8ded aurel32
void helper_lvsr (ppc_avr_t *r, target_ulong sh)
2039 bf8d8ded aurel32
{
2040 bf8d8ded aurel32
    int i, j = 0x10 - (sh & 0xf);
2041 bf8d8ded aurel32
2042 bf8d8ded aurel32
    VECTOR_FOR_INORDER_I (i, u8) {
2043 bf8d8ded aurel32
        r->u8[i] = j++;
2044 bf8d8ded aurel32
    }
2045 bf8d8ded aurel32
}
2046 bf8d8ded aurel32
2047 cbfb6ae9 aurel32
#define STVE(name, access, swap, element)                       \
2048 cbfb6ae9 aurel32
    void helper_##name (ppc_avr_t *r, target_ulong addr)        \
2049 cbfb6ae9 aurel32
    {                                                           \
2050 cbfb6ae9 aurel32
        size_t n_elems = ARRAY_SIZE(r->element);                \
2051 cbfb6ae9 aurel32
        int adjust = HI_IDX*(n_elems-1);                        \
2052 cbfb6ae9 aurel32
        int sh = sizeof(r->element[0]) >> 1;                    \
2053 cbfb6ae9 aurel32
        int index = (addr & 0xf) >> sh;                         \
2054 cbfb6ae9 aurel32
        if(msr_le) {                                            \
2055 cbfb6ae9 aurel32
            access(addr, swap(r->element[LO_IDX ? index : (adjust - index)])); \
2056 cbfb6ae9 aurel32
        } else {                                                        \
2057 cbfb6ae9 aurel32
            access(addr, r->element[LO_IDX ? index : (adjust - index)]); \
2058 cbfb6ae9 aurel32
        }                                                               \
2059 cbfb6ae9 aurel32
    }
2060 cbfb6ae9 aurel32
#define I(x) (x)
2061 cbfb6ae9 aurel32
STVE(stvebx, stb, I, u8)
2062 cbfb6ae9 aurel32
STVE(stvehx, stw, bswap16, u16)
2063 cbfb6ae9 aurel32
STVE(stvewx, stl, bswap32, u32)
2064 cbfb6ae9 aurel32
#undef I
2065 cbfb6ae9 aurel32
#undef LVE
2066 cbfb6ae9 aurel32
2067 6e87b7c7 aurel32
void helper_mtvscr (ppc_avr_t *r)
2068 6e87b7c7 aurel32
{
2069 6e87b7c7 aurel32
#if defined(WORDS_BIGENDIAN)
2070 6e87b7c7 aurel32
    env->vscr = r->u32[3];
2071 6e87b7c7 aurel32
#else
2072 6e87b7c7 aurel32
    env->vscr = r->u32[0];
2073 6e87b7c7 aurel32
#endif
2074 6e87b7c7 aurel32
    set_flush_to_zero(vscr_nj, &env->vec_status);
2075 6e87b7c7 aurel32
}
2076 6e87b7c7 aurel32
2077 e343da72 aurel32
void helper_vaddcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2078 e343da72 aurel32
{
2079 e343da72 aurel32
    int i;
2080 e343da72 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2081 e343da72 aurel32
        r->u32[i] = ~a->u32[i] < b->u32[i];
2082 e343da72 aurel32
    }
2083 e343da72 aurel32
}
2084 e343da72 aurel32
2085 7872c51c aurel32
#define VARITH_DO(name, op, element)        \
2086 7872c51c aurel32
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)          \
2087 7872c51c aurel32
{                                                                       \
2088 7872c51c aurel32
    int i;                                                              \
2089 7872c51c aurel32
    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                      \
2090 7872c51c aurel32
        r->element[i] = a->element[i] op b->element[i];                 \
2091 7872c51c aurel32
    }                                                                   \
2092 7872c51c aurel32
}
2093 7872c51c aurel32
#define VARITH(suffix, element)                  \
2094 7872c51c aurel32
  VARITH_DO(add##suffix, +, element)             \
2095 7872c51c aurel32
  VARITH_DO(sub##suffix, -, element)
2096 7872c51c aurel32
VARITH(ubm, u8)
2097 7872c51c aurel32
VARITH(uhm, u16)
2098 7872c51c aurel32
VARITH(uwm, u32)
2099 7872c51c aurel32
#undef VARITH_DO
2100 7872c51c aurel32
#undef VARITH
2101 7872c51c aurel32
2102 56fdd213 aurel32
#define VARITHFP(suffix, func)                                          \
2103 56fdd213 aurel32
    void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
2104 56fdd213 aurel32
    {                                                                   \
2105 56fdd213 aurel32
        int i;                                                          \
2106 56fdd213 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2107 56fdd213 aurel32
            HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
2108 56fdd213 aurel32
                r->f[i] = func(a->f[i], b->f[i], &env->vec_status);     \
2109 56fdd213 aurel32
            }                                                           \
2110 56fdd213 aurel32
        }                                                               \
2111 56fdd213 aurel32
    }
2112 56fdd213 aurel32
VARITHFP(addfp, float32_add)
2113 56fdd213 aurel32
VARITHFP(subfp, float32_sub)
2114 56fdd213 aurel32
#undef VARITHFP
2115 56fdd213 aurel32
2116 5ab09f33 aurel32
#define VARITHSAT_CASE(type, op, cvt, element)                          \
2117 5ab09f33 aurel32
    {                                                                   \
2118 5ab09f33 aurel32
        type result = (type)a->element[i] op (type)b->element[i];       \
2119 5ab09f33 aurel32
        r->element[i] = cvt(result, &sat);                              \
2120 5ab09f33 aurel32
    }
2121 5ab09f33 aurel32
2122 5ab09f33 aurel32
#define VARITHSAT_DO(name, op, optype, cvt, element)                    \
2123 5ab09f33 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2124 5ab09f33 aurel32
    {                                                                   \
2125 5ab09f33 aurel32
        int sat = 0;                                                    \
2126 5ab09f33 aurel32
        int i;                                                          \
2127 5ab09f33 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2128 5ab09f33 aurel32
            switch (sizeof(r->element[0])) {                            \
2129 5ab09f33 aurel32
            case 1: VARITHSAT_CASE(optype, op, cvt, element); break;    \
2130 5ab09f33 aurel32
            case 2: VARITHSAT_CASE(optype, op, cvt, element); break;    \
2131 5ab09f33 aurel32
            case 4: VARITHSAT_CASE(optype, op, cvt, element); break;    \
2132 5ab09f33 aurel32
            }                                                           \
2133 5ab09f33 aurel32
        }                                                               \
2134 5ab09f33 aurel32
        if (sat) {                                                      \
2135 5ab09f33 aurel32
            env->vscr |= (1 << VSCR_SAT);                               \
2136 5ab09f33 aurel32
        }                                                               \
2137 5ab09f33 aurel32
    }
2138 5ab09f33 aurel32
#define VARITHSAT_SIGNED(suffix, element, optype, cvt)        \
2139 5ab09f33 aurel32
    VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element)    \
2140 5ab09f33 aurel32
    VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
2141 5ab09f33 aurel32
#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt)       \
2142 5ab09f33 aurel32
    VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element)     \
2143 5ab09f33 aurel32
    VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
2144 5ab09f33 aurel32
VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
2145 5ab09f33 aurel32
VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
2146 5ab09f33 aurel32
VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
2147 5ab09f33 aurel32
VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
2148 5ab09f33 aurel32
VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
2149 5ab09f33 aurel32
VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
2150 5ab09f33 aurel32
#undef VARITHSAT_CASE
2151 5ab09f33 aurel32
#undef VARITHSAT_DO
2152 5ab09f33 aurel32
#undef VARITHSAT_SIGNED
2153 5ab09f33 aurel32
#undef VARITHSAT_UNSIGNED
2154 5ab09f33 aurel32
2155 fab3cbe9 aurel32
#define VAVG_DO(name, element, etype)                                   \
2156 fab3cbe9 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2157 fab3cbe9 aurel32
    {                                                                   \
2158 fab3cbe9 aurel32
        int i;                                                          \
2159 fab3cbe9 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2160 fab3cbe9 aurel32
            etype x = (etype)a->element[i] + (etype)b->element[i] + 1;  \
2161 fab3cbe9 aurel32
            r->element[i] = x >> 1;                                     \
2162 fab3cbe9 aurel32
        }                                                               \
2163 fab3cbe9 aurel32
    }
2164 fab3cbe9 aurel32
2165 fab3cbe9 aurel32
#define VAVG(type, signed_element, signed_type, unsigned_element, unsigned_type) \
2166 fab3cbe9 aurel32
    VAVG_DO(avgs##type, signed_element, signed_type)                    \
2167 fab3cbe9 aurel32
    VAVG_DO(avgu##type, unsigned_element, unsigned_type)
2168 fab3cbe9 aurel32
VAVG(b, s8, int16_t, u8, uint16_t)
2169 fab3cbe9 aurel32
VAVG(h, s16, int32_t, u16, uint32_t)
2170 fab3cbe9 aurel32
VAVG(w, s32, int64_t, u32, uint64_t)
2171 fab3cbe9 aurel32
#undef VAVG_DO
2172 fab3cbe9 aurel32
#undef VAVG
2173 fab3cbe9 aurel32
2174 e140632e aurel32
#define VCF(suffix, cvt, element)                                       \
2175 e140632e aurel32
    void helper_vcf##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim)  \
2176 e140632e aurel32
    {                                                                   \
2177 e140632e aurel32
        int i;                                                          \
2178 e140632e aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2179 e140632e aurel32
            float32 t = cvt(b->element[i], &env->vec_status);           \
2180 e140632e aurel32
            r->f[i] = float32_scalbn (t, -uim, &env->vec_status);       \
2181 e140632e aurel32
        }                                                               \
2182 e140632e aurel32
    }
2183 e140632e aurel32
VCF(ux, uint32_to_float32, u32)
2184 e140632e aurel32
VCF(sx, int32_to_float32, s32)
2185 e140632e aurel32
#undef VCF
2186 e140632e aurel32
2187 1add6e23 aurel32
#define VCMP_DO(suffix, compare, element, record)                       \
2188 1add6e23 aurel32
    void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2189 1add6e23 aurel32
    {                                                                   \
2190 1add6e23 aurel32
        uint32_t ones = (uint32_t)-1;                                   \
2191 1add6e23 aurel32
        uint32_t all = ones;                                            \
2192 1add6e23 aurel32
        uint32_t none = 0;                                              \
2193 1add6e23 aurel32
        int i;                                                          \
2194 1add6e23 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2195 1add6e23 aurel32
            uint32_t result = (a->element[i] compare b->element[i] ? ones : 0x0); \
2196 1add6e23 aurel32
            switch (sizeof (a->element[0])) {                           \
2197 1add6e23 aurel32
            case 4: r->u32[i] = result; break;                          \
2198 1add6e23 aurel32
            case 2: r->u16[i] = result; break;                          \
2199 1add6e23 aurel32
            case 1: r->u8[i] = result; break;                           \
2200 1add6e23 aurel32
            }                                                           \
2201 1add6e23 aurel32
            all &= result;                                              \
2202 1add6e23 aurel32
            none |= result;                                             \
2203 1add6e23 aurel32
        }                                                               \
2204 1add6e23 aurel32
        if (record) {                                                   \
2205 1add6e23 aurel32
            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
2206 1add6e23 aurel32
        }                                                               \
2207 1add6e23 aurel32
    }
2208 1add6e23 aurel32
#define VCMP(suffix, compare, element)          \
2209 1add6e23 aurel32
    VCMP_DO(suffix, compare, element, 0)        \
2210 1add6e23 aurel32
    VCMP_DO(suffix##_dot, compare, element, 1)
2211 1add6e23 aurel32
VCMP(equb, ==, u8)
2212 1add6e23 aurel32
VCMP(equh, ==, u16)
2213 1add6e23 aurel32
VCMP(equw, ==, u32)
2214 1add6e23 aurel32
VCMP(gtub, >, u8)
2215 1add6e23 aurel32
VCMP(gtuh, >, u16)
2216 1add6e23 aurel32
VCMP(gtuw, >, u32)
2217 1add6e23 aurel32
VCMP(gtsb, >, s8)
2218 1add6e23 aurel32
VCMP(gtsh, >, s16)
2219 1add6e23 aurel32
VCMP(gtsw, >, s32)
2220 1add6e23 aurel32
#undef VCMP_DO
2221 1add6e23 aurel32
#undef VCMP
2222 1add6e23 aurel32
2223 819ca121 aurel32
#define VCMPFP_DO(suffix, compare, order, record)                       \
2224 819ca121 aurel32
    void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2225 819ca121 aurel32
    {                                                                   \
2226 819ca121 aurel32
        uint32_t ones = (uint32_t)-1;                                   \
2227 819ca121 aurel32
        uint32_t all = ones;                                            \
2228 819ca121 aurel32
        uint32_t none = 0;                                              \
2229 819ca121 aurel32
        int i;                                                          \
2230 819ca121 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2231 819ca121 aurel32
            uint32_t result;                                            \
2232 819ca121 aurel32
            int rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status); \
2233 819ca121 aurel32
            if (rel == float_relation_unordered) {                      \
2234 819ca121 aurel32
                result = 0;                                             \
2235 819ca121 aurel32
            } else if (rel compare order) {                             \
2236 819ca121 aurel32
                result = ones;                                          \
2237 819ca121 aurel32
            } else {                                                    \
2238 819ca121 aurel32
                result = 0;                                             \
2239 819ca121 aurel32
            }                                                           \
2240 819ca121 aurel32
            r->u32[i] = result;                                         \
2241 819ca121 aurel32
            all &= result;                                              \
2242 819ca121 aurel32
            none |= result;                                             \
2243 819ca121 aurel32
        }                                                               \
2244 819ca121 aurel32
        if (record) {                                                   \
2245 819ca121 aurel32
            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
2246 819ca121 aurel32
        }                                                               \
2247 819ca121 aurel32
    }
2248 819ca121 aurel32
#define VCMPFP(suffix, compare, order)           \
2249 819ca121 aurel32
    VCMPFP_DO(suffix, compare, order, 0)         \
2250 819ca121 aurel32
    VCMPFP_DO(suffix##_dot, compare, order, 1)
2251 819ca121 aurel32
VCMPFP(eqfp, ==, float_relation_equal)
2252 819ca121 aurel32
VCMPFP(gefp, !=, float_relation_less)
2253 819ca121 aurel32
VCMPFP(gtfp, ==, float_relation_greater)
2254 819ca121 aurel32
#undef VCMPFP_DO
2255 819ca121 aurel32
#undef VCMPFP
2256 819ca121 aurel32
2257 819ca121 aurel32
static always_inline void vcmpbfp_internal (ppc_avr_t *r, ppc_avr_t *a,
2258 819ca121 aurel32
                                            ppc_avr_t *b, int record)
2259 819ca121 aurel32
{
2260 819ca121 aurel32
    int i;
2261 819ca121 aurel32
    int all_in = 0;
2262 819ca121 aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2263 819ca121 aurel32
        int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
2264 819ca121 aurel32
        if (le_rel == float_relation_unordered) {
2265 819ca121 aurel32
            r->u32[i] = 0xc0000000;
2266 819ca121 aurel32
            /* ALL_IN does not need to be updated here.  */
2267 819ca121 aurel32
        } else {
2268 819ca121 aurel32
            float32 bneg = float32_chs(b->f[i]);
2269 819ca121 aurel32
            int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
2270 819ca121 aurel32
            int le = le_rel != float_relation_greater;
2271 819ca121 aurel32
            int ge = ge_rel != float_relation_less;
2272 819ca121 aurel32
            r->u32[i] = ((!le) << 31) | ((!ge) << 30);
2273 819ca121 aurel32
            all_in |= (!le | !ge);
2274 819ca121 aurel32
        }
2275 819ca121 aurel32
    }
2276 819ca121 aurel32
    if (record) {
2277 819ca121 aurel32
        env->crf[6] = (all_in == 0) << 1;
2278 819ca121 aurel32
    }
2279 819ca121 aurel32
}
2280 819ca121 aurel32
2281 819ca121 aurel32
void helper_vcmpbfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2282 819ca121 aurel32
{
2283 819ca121 aurel32
    vcmpbfp_internal(r, a, b, 0);
2284 819ca121 aurel32
}
2285 819ca121 aurel32
2286 819ca121 aurel32
void helper_vcmpbfp_dot (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2287 819ca121 aurel32
{
2288 819ca121 aurel32
    vcmpbfp_internal(r, a, b, 1);
2289 819ca121 aurel32
}
2290 819ca121 aurel32
2291 875b31db aurel32
#define VCT(suffix, satcvt, element)                                    \
2292 875b31db aurel32
    void helper_vct##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim)  \
2293 875b31db aurel32
    {                                                                   \
2294 875b31db aurel32
        int i;                                                          \
2295 875b31db aurel32
        int sat = 0;                                                    \
2296 875b31db aurel32
        float_status s = env->vec_status;                               \
2297 875b31db aurel32
        set_float_rounding_mode(float_round_to_zero, &s);               \
2298 875b31db aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2299 875b31db aurel32
            if (float32_is_nan(b->f[i]) ||                              \
2300 875b31db aurel32
                float32_is_signaling_nan(b->f[i])) {                    \
2301 875b31db aurel32
                r->element[i] = 0;                                      \
2302 875b31db aurel32
            } else {                                                    \
2303 875b31db aurel32
                float64 t = float32_to_float64(b->f[i], &s);            \
2304 875b31db aurel32
                int64_t j;                                              \
2305 875b31db aurel32
                t = float64_scalbn(t, uim, &s);                         \
2306 875b31db aurel32
                j = float64_to_int64(t, &s);                            \
2307 875b31db aurel32
                r->element[i] = satcvt(j, &sat);                        \
2308 875b31db aurel32
            }                                                           \
2309 875b31db aurel32
        }                                                               \
2310 875b31db aurel32
        if (sat) {                                                      \
2311 875b31db aurel32
            env->vscr |= (1 << VSCR_SAT);                               \
2312 875b31db aurel32
        }                                                               \
2313 875b31db aurel32
    }
2314 875b31db aurel32
VCT(uxs, cvtsduw, u32)
2315 875b31db aurel32
VCT(sxs, cvtsdsw, s32)
2316 875b31db aurel32
#undef VCT
2317 875b31db aurel32
2318 35cf7c7e aurel32
void helper_vmaddfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2319 35cf7c7e aurel32
{
2320 35cf7c7e aurel32
    int i;
2321 35cf7c7e aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2322 35cf7c7e aurel32
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2323 35cf7c7e aurel32
            /* Need to do the computation in higher precision and round
2324 35cf7c7e aurel32
             * once at the end.  */
2325 35cf7c7e aurel32
            float64 af, bf, cf, t;
2326 35cf7c7e aurel32
            af = float32_to_float64(a->f[i], &env->vec_status);
2327 35cf7c7e aurel32
            bf = float32_to_float64(b->f[i], &env->vec_status);
2328 35cf7c7e aurel32
            cf = float32_to_float64(c->f[i], &env->vec_status);
2329 35cf7c7e aurel32
            t = float64_mul(af, cf, &env->vec_status);
2330 35cf7c7e aurel32
            t = float64_add(t, bf, &env->vec_status);
2331 35cf7c7e aurel32
            r->f[i] = float64_to_float32(t, &env->vec_status);
2332 35cf7c7e aurel32
        }
2333 35cf7c7e aurel32
    }
2334 35cf7c7e aurel32
}
2335 35cf7c7e aurel32
2336 b161ae27 aurel32
void helper_vmhaddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2337 b161ae27 aurel32
{
2338 b161ae27 aurel32
    int sat = 0;
2339 b161ae27 aurel32
    int i;
2340 b161ae27 aurel32
2341 b161ae27 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2342 b161ae27 aurel32
        int32_t prod = a->s16[i] * b->s16[i];
2343 b161ae27 aurel32
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2344 b161ae27 aurel32
        r->s16[i] = cvtswsh (t, &sat);
2345 b161ae27 aurel32
    }
2346 b161ae27 aurel32
2347 b161ae27 aurel32
    if (sat) {
2348 b161ae27 aurel32
        env->vscr |= (1 << VSCR_SAT);
2349 b161ae27 aurel32
    }
2350 b161ae27 aurel32
}
2351 b161ae27 aurel32
2352 b161ae27 aurel32
void helper_vmhraddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2353 b161ae27 aurel32
{
2354 b161ae27 aurel32
    int sat = 0;
2355 b161ae27 aurel32
    int i;
2356 b161ae27 aurel32
2357 b161ae27 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2358 b161ae27 aurel32
        int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
2359 b161ae27 aurel32
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2360 b161ae27 aurel32
        r->s16[i] = cvtswsh (t, &sat);
2361 b161ae27 aurel32
    }
2362 b161ae27 aurel32
2363 b161ae27 aurel32
    if (sat) {
2364 b161ae27 aurel32
        env->vscr |= (1 << VSCR_SAT);
2365 b161ae27 aurel32
    }
2366 b161ae27 aurel32
}
2367 b161ae27 aurel32
2368 e4039339 aurel32
#define VMINMAX_DO(name, compare, element)                              \
2369 e4039339 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2370 e4039339 aurel32
    {                                                                   \
2371 e4039339 aurel32
        int i;                                                          \
2372 e4039339 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2373 e4039339 aurel32
            if (a->element[i] compare b->element[i]) {                  \
2374 e4039339 aurel32
                r->element[i] = b->element[i];                          \
2375 e4039339 aurel32
            } else {                                                    \
2376 e4039339 aurel32
                r->element[i] = a->element[i];                          \
2377 e4039339 aurel32
            }                                                           \
2378 e4039339 aurel32
        }                                                               \
2379 e4039339 aurel32
    }
2380 e4039339 aurel32
#define VMINMAX(suffix, element)                \
2381 e4039339 aurel32
  VMINMAX_DO(min##suffix, >, element)           \
2382 e4039339 aurel32
  VMINMAX_DO(max##suffix, <, element)
2383 e4039339 aurel32
VMINMAX(sb, s8)
2384 e4039339 aurel32
VMINMAX(sh, s16)
2385 e4039339 aurel32
VMINMAX(sw, s32)
2386 e4039339 aurel32
VMINMAX(ub, u8)
2387 e4039339 aurel32
VMINMAX(uh, u16)
2388 e4039339 aurel32
VMINMAX(uw, u32)
2389 e4039339 aurel32
#undef VMINMAX_DO
2390 e4039339 aurel32
#undef VMINMAX
2391 e4039339 aurel32
2392 1536ff64 aurel32
#define VMINMAXFP(suffix, rT, rF)                                       \
2393 1536ff64 aurel32
    void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
2394 1536ff64 aurel32
    {                                                                   \
2395 1536ff64 aurel32
        int i;                                                          \
2396 1536ff64 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2397 1536ff64 aurel32
            HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
2398 1536ff64 aurel32
                if (float32_lt_quiet(a->f[i], b->f[i], &env->vec_status)) { \
2399 1536ff64 aurel32
                    r->f[i] = rT->f[i];                                 \
2400 1536ff64 aurel32
                } else {                                                \
2401 1536ff64 aurel32
                    r->f[i] = rF->f[i];                                 \
2402 1536ff64 aurel32
                }                                                       \
2403 1536ff64 aurel32
            }                                                           \
2404 1536ff64 aurel32
        }                                                               \
2405 1536ff64 aurel32
    }
2406 1536ff64 aurel32
VMINMAXFP(minfp, a, b)
2407 1536ff64 aurel32
VMINMAXFP(maxfp, b, a)
2408 1536ff64 aurel32
#undef VMINMAXFP
2409 1536ff64 aurel32
2410 bcd2ee23 aurel32
void helper_vmladduhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2411 bcd2ee23 aurel32
{
2412 bcd2ee23 aurel32
    int i;
2413 bcd2ee23 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2414 bcd2ee23 aurel32
        int32_t prod = a->s16[i] * b->s16[i];
2415 bcd2ee23 aurel32
        r->s16[i] = (int16_t) (prod + c->s16[i]);
2416 bcd2ee23 aurel32
    }
2417 bcd2ee23 aurel32
}
2418 bcd2ee23 aurel32
2419 3b430048 aurel32
#define VMRG_DO(name, element, highp)                                   \
2420 3b430048 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2421 3b430048 aurel32
    {                                                                   \
2422 3b430048 aurel32
        ppc_avr_t result;                                               \
2423 3b430048 aurel32
        int i;                                                          \
2424 3b430048 aurel32
        size_t n_elems = ARRAY_SIZE(r->element);                        \
2425 3b430048 aurel32
        for (i = 0; i < n_elems/2; i++) {                               \
2426 3b430048 aurel32
            if (highp) {                                                \
2427 3b430048 aurel32
                result.element[i*2+HI_IDX] = a->element[i];             \
2428 3b430048 aurel32
                result.element[i*2+LO_IDX] = b->element[i];             \
2429 3b430048 aurel32
            } else {                                                    \
2430 3b430048 aurel32
                result.element[n_elems - i*2 - (1+HI_IDX)] = b->element[n_elems - i - 1]; \
2431 3b430048 aurel32
                result.element[n_elems - i*2 - (1+LO_IDX)] = a->element[n_elems - i - 1]; \
2432 3b430048 aurel32
            }                                                           \
2433 3b430048 aurel32
        }                                                               \
2434 3b430048 aurel32
        *r = result;                                                    \
2435 3b430048 aurel32
    }
2436 3b430048 aurel32
#if defined(WORDS_BIGENDIAN)
2437 3b430048 aurel32
#define MRGHI 0
2438 b392e756 aurel32
#define MRGLO 1
2439 3b430048 aurel32
#else
2440 3b430048 aurel32
#define MRGHI 1
2441 3b430048 aurel32
#define MRGLO 0
2442 3b430048 aurel32
#endif
2443 3b430048 aurel32
#define VMRG(suffix, element)                   \
2444 3b430048 aurel32
  VMRG_DO(mrgl##suffix, element, MRGHI)         \
2445 3b430048 aurel32
  VMRG_DO(mrgh##suffix, element, MRGLO)
2446 3b430048 aurel32
VMRG(b, u8)
2447 3b430048 aurel32
VMRG(h, u16)
2448 3b430048 aurel32
VMRG(w, u32)
2449 3b430048 aurel32
#undef VMRG_DO
2450 3b430048 aurel32
#undef VMRG
2451 3b430048 aurel32
#undef MRGHI
2452 3b430048 aurel32
#undef MRGLO
2453 3b430048 aurel32
2454 b04ae981 aurel32
void helper_vmsummbm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2455 b04ae981 aurel32
{
2456 b04ae981 aurel32
    int32_t prod[16];
2457 b04ae981 aurel32
    int i;
2458 b04ae981 aurel32
2459 b04ae981 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
2460 b04ae981 aurel32
        prod[i] = (int32_t)a->s8[i] * b->u8[i];
2461 b04ae981 aurel32
    }
2462 b04ae981 aurel32
2463 b04ae981 aurel32
    VECTOR_FOR_INORDER_I(i, s32) {
2464 b04ae981 aurel32
        r->s32[i] = c->s32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2465 b04ae981 aurel32
    }
2466 b04ae981 aurel32
}
2467 b04ae981 aurel32
2468 eae07261 aurel32
void helper_vmsumshm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2469 eae07261 aurel32
{
2470 eae07261 aurel32
    int32_t prod[8];
2471 eae07261 aurel32
    int i;
2472 eae07261 aurel32
2473 eae07261 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2474 eae07261 aurel32
        prod[i] = a->s16[i] * b->s16[i];
2475 eae07261 aurel32
    }
2476 eae07261 aurel32
2477 eae07261 aurel32
    VECTOR_FOR_INORDER_I(i, s32) {
2478 eae07261 aurel32
        r->s32[i] = c->s32[i] + prod[2*i] + prod[2*i+1];
2479 eae07261 aurel32
    }
2480 eae07261 aurel32
}
2481 eae07261 aurel32
2482 eae07261 aurel32
void helper_vmsumshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2483 eae07261 aurel32
{
2484 eae07261 aurel32
    int32_t prod[8];
2485 eae07261 aurel32
    int i;
2486 eae07261 aurel32
    int sat = 0;
2487 eae07261 aurel32
2488 eae07261 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2489 eae07261 aurel32
        prod[i] = (int32_t)a->s16[i] * b->s16[i];
2490 eae07261 aurel32
    }
2491 eae07261 aurel32
2492 eae07261 aurel32
    VECTOR_FOR_INORDER_I (i, s32) {
2493 eae07261 aurel32
        int64_t t = (int64_t)c->s32[i] + prod[2*i] + prod[2*i+1];
2494 eae07261 aurel32
        r->u32[i] = cvtsdsw(t, &sat);
2495 eae07261 aurel32
    }
2496 eae07261 aurel32
2497 eae07261 aurel32
    if (sat) {
2498 eae07261 aurel32
        env->vscr |= (1 << VSCR_SAT);
2499 eae07261 aurel32
    }
2500 eae07261 aurel32
}
2501 eae07261 aurel32
2502 b04ae981 aurel32
void helper_vmsumubm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2503 b04ae981 aurel32
{
2504 b04ae981 aurel32
    uint16_t prod[16];
2505 b04ae981 aurel32
    int i;
2506 b04ae981 aurel32
2507 b04ae981 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2508 b04ae981 aurel32
        prod[i] = a->u8[i] * b->u8[i];
2509 b04ae981 aurel32
    }
2510 b04ae981 aurel32
2511 b04ae981 aurel32
    VECTOR_FOR_INORDER_I(i, u32) {
2512 b04ae981 aurel32
        r->u32[i] = c->u32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2513 b04ae981 aurel32
    }
2514 b04ae981 aurel32
}
2515 b04ae981 aurel32
2516 4d9903b6 aurel32
void helper_vmsumuhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2517 4d9903b6 aurel32
{
2518 4d9903b6 aurel32
    uint32_t prod[8];
2519 4d9903b6 aurel32
    int i;
2520 4d9903b6 aurel32
2521 4d9903b6 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2522 4d9903b6 aurel32
        prod[i] = a->u16[i] * b->u16[i];
2523 4d9903b6 aurel32
    }
2524 4d9903b6 aurel32
2525 4d9903b6 aurel32
    VECTOR_FOR_INORDER_I(i, u32) {
2526 4d9903b6 aurel32
        r->u32[i] = c->u32[i] + prod[2*i] + prod[2*i+1];
2527 4d9903b6 aurel32
    }
2528 4d9903b6 aurel32
}
2529 4d9903b6 aurel32
2530 4d9903b6 aurel32
void helper_vmsumuhs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2531 4d9903b6 aurel32
{
2532 4d9903b6 aurel32
    uint32_t prod[8];
2533 4d9903b6 aurel32
    int i;
2534 4d9903b6 aurel32
    int sat = 0;
2535 4d9903b6 aurel32
2536 4d9903b6 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2537 4d9903b6 aurel32
        prod[i] = a->u16[i] * b->u16[i];
2538 4d9903b6 aurel32
    }
2539 4d9903b6 aurel32
2540 4d9903b6 aurel32
    VECTOR_FOR_INORDER_I (i, s32) {
2541 4d9903b6 aurel32
        uint64_t t = (uint64_t)c->u32[i] + prod[2*i] + prod[2*i+1];
2542 4d9903b6 aurel32
        r->u32[i] = cvtuduw(t, &sat);
2543 4d9903b6 aurel32
    }
2544 4d9903b6 aurel32
2545 4d9903b6 aurel32
    if (sat) {
2546 4d9903b6 aurel32
        env->vscr |= (1 << VSCR_SAT);
2547 4d9903b6 aurel32
    }
2548 4d9903b6 aurel32
}
2549 4d9903b6 aurel32
2550 2c277908 aurel32
#define VMUL_DO(name, mul_element, prod_element, evenp)                 \
2551 2c277908 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2552 2c277908 aurel32
    {                                                                   \
2553 2c277908 aurel32
        int i;                                                          \
2554 2c277908 aurel32
        VECTOR_FOR_INORDER_I(i, prod_element) {                         \
2555 2c277908 aurel32
            if (evenp) {                                                \
2556 2c277908 aurel32
                r->prod_element[i] = a->mul_element[i*2+HI_IDX] * b->mul_element[i*2+HI_IDX]; \
2557 2c277908 aurel32
            } else {                                                    \
2558 2c277908 aurel32
                r->prod_element[i] = a->mul_element[i*2+LO_IDX] * b->mul_element[i*2+LO_IDX]; \
2559 2c277908 aurel32
            }                                                           \
2560 2c277908 aurel32
        }                                                               \
2561 2c277908 aurel32
    }
2562 2c277908 aurel32
#define VMUL(suffix, mul_element, prod_element) \
2563 2c277908 aurel32
  VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
2564 2c277908 aurel32
  VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
2565 2c277908 aurel32
VMUL(sb, s8, s16)
2566 2c277908 aurel32
VMUL(sh, s16, s32)
2567 2c277908 aurel32
VMUL(ub, u8, u16)
2568 2c277908 aurel32
VMUL(uh, u16, u32)
2569 2c277908 aurel32
#undef VMUL_DO
2570 2c277908 aurel32
#undef VMUL
2571 2c277908 aurel32
2572 35cf7c7e aurel32
void helper_vnmsubfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2573 35cf7c7e aurel32
{
2574 35cf7c7e aurel32
    int i;
2575 35cf7c7e aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2576 35cf7c7e aurel32
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2577 35cf7c7e aurel32
            /* Need to do the computation is higher precision and round
2578 35cf7c7e aurel32
             * once at the end.  */
2579 35cf7c7e aurel32
            float64 af, bf, cf, t;
2580 35cf7c7e aurel32
            af = float32_to_float64(a->f[i], &env->vec_status);
2581 35cf7c7e aurel32
            bf = float32_to_float64(b->f[i], &env->vec_status);
2582 35cf7c7e aurel32
            cf = float32_to_float64(c->f[i], &env->vec_status);
2583 35cf7c7e aurel32
            t = float64_mul(af, cf, &env->vec_status);
2584 35cf7c7e aurel32
            t = float64_sub(t, bf, &env->vec_status);
2585 35cf7c7e aurel32
            t = float64_chs(t);
2586 35cf7c7e aurel32
            r->f[i] = float64_to_float32(t, &env->vec_status);
2587 35cf7c7e aurel32
        }
2588 35cf7c7e aurel32
    }
2589 35cf7c7e aurel32
}
2590 35cf7c7e aurel32
2591 d1258698 aurel32
void helper_vperm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2592 d1258698 aurel32
{
2593 d1258698 aurel32
    ppc_avr_t result;
2594 d1258698 aurel32
    int i;
2595 d1258698 aurel32
    VECTOR_FOR_INORDER_I (i, u8) {
2596 d1258698 aurel32
        int s = c->u8[i] & 0x1f;
2597 d1258698 aurel32
#if defined(WORDS_BIGENDIAN)
2598 d1258698 aurel32
        int index = s & 0xf;
2599 d1258698 aurel32
#else
2600 d1258698 aurel32
        int index = 15 - (s & 0xf);
2601 d1258698 aurel32
#endif
2602 d1258698 aurel32
        if (s & 0x10) {
2603 d1258698 aurel32
            result.u8[i] = b->u8[index];
2604 d1258698 aurel32
        } else {
2605 d1258698 aurel32
            result.u8[i] = a->u8[index];
2606 d1258698 aurel32
        }
2607 d1258698 aurel32
    }
2608 d1258698 aurel32
    *r = result;
2609 d1258698 aurel32
}
2610 d1258698 aurel32
2611 5335a145 aurel32
#if defined(WORDS_BIGENDIAN)
2612 5335a145 aurel32
#define PKBIG 1
2613 5335a145 aurel32
#else
2614 5335a145 aurel32
#define PKBIG 0
2615 5335a145 aurel32
#endif
2616 1dd9ffb9 aurel32
void helper_vpkpx (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2617 1dd9ffb9 aurel32
{
2618 1dd9ffb9 aurel32
    int i, j;
2619 1dd9ffb9 aurel32
    ppc_avr_t result;
2620 1dd9ffb9 aurel32
#if defined(WORDS_BIGENDIAN)
2621 1dd9ffb9 aurel32
    const ppc_avr_t *x[2] = { a, b };
2622 1dd9ffb9 aurel32
#else
2623 1dd9ffb9 aurel32
    const ppc_avr_t *x[2] = { b, a };
2624 1dd9ffb9 aurel32
#endif
2625 1dd9ffb9 aurel32
2626 1dd9ffb9 aurel32
    VECTOR_FOR_INORDER_I (i, u64) {
2627 1dd9ffb9 aurel32
        VECTOR_FOR_INORDER_I (j, u32){
2628 1dd9ffb9 aurel32
            uint32_t e = x[i]->u32[j];
2629 1dd9ffb9 aurel32
            result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
2630 1dd9ffb9 aurel32
                                 ((e >> 6) & 0x3e0) |
2631 1dd9ffb9 aurel32
                                 ((e >> 3) & 0x1f));
2632 1dd9ffb9 aurel32
        }
2633 1dd9ffb9 aurel32
    }
2634 1dd9ffb9 aurel32
    *r = result;
2635 1dd9ffb9 aurel32
}
2636 1dd9ffb9 aurel32
2637 5335a145 aurel32
#define VPK(suffix, from, to, cvt, dosat)       \
2638 5335a145 aurel32
    void helper_vpk##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2639 5335a145 aurel32
    {                                                                   \
2640 5335a145 aurel32
        int i;                                                          \
2641 5335a145 aurel32
        int sat = 0;                                                    \
2642 5335a145 aurel32
        ppc_avr_t result;                                               \
2643 5335a145 aurel32
        ppc_avr_t *a0 = PKBIG ? a : b;                                  \
2644 5335a145 aurel32
        ppc_avr_t *a1 = PKBIG ? b : a;                                  \
2645 5335a145 aurel32
        VECTOR_FOR_INORDER_I (i, from) {                                \
2646 5335a145 aurel32
            result.to[i] = cvt(a0->from[i], &sat);                      \
2647 5335a145 aurel32
            result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);  \
2648 5335a145 aurel32
        }                                                               \
2649 5335a145 aurel32
        *r = result;                                                    \
2650 5335a145 aurel32
        if (dosat && sat) {                                             \
2651 5335a145 aurel32
            env->vscr |= (1 << VSCR_SAT);                               \
2652 5335a145 aurel32
        }                                                               \
2653 5335a145 aurel32
    }
2654 5335a145 aurel32
#define I(x, y) (x)
2655 5335a145 aurel32
VPK(shss, s16, s8, cvtshsb, 1)
2656 5335a145 aurel32
VPK(shus, s16, u8, cvtshub, 1)
2657 5335a145 aurel32
VPK(swss, s32, s16, cvtswsh, 1)
2658 5335a145 aurel32
VPK(swus, s32, u16, cvtswuh, 1)
2659 5335a145 aurel32
VPK(uhus, u16, u8, cvtuhub, 1)
2660 5335a145 aurel32
VPK(uwus, u32, u16, cvtuwuh, 1)
2661 5335a145 aurel32
VPK(uhum, u16, u8, I, 0)
2662 5335a145 aurel32
VPK(uwum, u32, u16, I, 0)
2663 5335a145 aurel32
#undef I
2664 5335a145 aurel32
#undef VPK
2665 5335a145 aurel32
#undef PKBIG
2666 5335a145 aurel32
2667 bdfbac35 aurel32
void helper_vrefp (ppc_avr_t *r, ppc_avr_t *b)
2668 bdfbac35 aurel32
{
2669 bdfbac35 aurel32
    int i;
2670 bdfbac35 aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2671 bdfbac35 aurel32
        HANDLE_NAN1(r->f[i], b->f[i]) {
2672 bdfbac35 aurel32
            r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
2673 bdfbac35 aurel32
        }
2674 bdfbac35 aurel32
    }
2675 bdfbac35 aurel32
}
2676 bdfbac35 aurel32
2677 f6b19645 aurel32
#define VRFI(suffix, rounding)                                          \
2678 f6b19645 aurel32
    void helper_vrfi##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
2679 f6b19645 aurel32
    {                                                                   \
2680 f6b19645 aurel32
        int i;                                                          \
2681 f6b19645 aurel32
        float_status s = env->vec_status;                               \
2682 f6b19645 aurel32
        set_float_rounding_mode(rounding, &s);                          \
2683 f6b19645 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2684 f6b19645 aurel32
            HANDLE_NAN1(r->f[i], b->f[i]) {                             \
2685 f6b19645 aurel32
                r->f[i] = float32_round_to_int (b->f[i], &s);           \
2686 f6b19645 aurel32
            }                                                           \
2687 f6b19645 aurel32
        }                                                               \
2688 f6b19645 aurel32
    }
2689 f6b19645 aurel32
VRFI(n, float_round_nearest_even)
2690 f6b19645 aurel32
VRFI(m, float_round_down)
2691 f6b19645 aurel32
VRFI(p, float_round_up)
2692 f6b19645 aurel32
VRFI(z, float_round_to_zero)
2693 f6b19645 aurel32
#undef VRFI
2694 f6b19645 aurel32
2695 5e1d0985 aurel32
#define VROTATE(suffix, element)                                        \
2696 5e1d0985 aurel32
    void helper_vrl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2697 5e1d0985 aurel32
    {                                                                   \
2698 5e1d0985 aurel32
        int i;                                                          \
2699 5e1d0985 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2700 5e1d0985 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2701 5e1d0985 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2702 5e1d0985 aurel32
            r->element[i] = (a->element[i] << shift) | (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
2703 5e1d0985 aurel32
        }                                                               \
2704 5e1d0985 aurel32
    }
2705 5e1d0985 aurel32
VROTATE(b, u8)
2706 5e1d0985 aurel32
VROTATE(h, u16)
2707 5e1d0985 aurel32
VROTATE(w, u32)
2708 5e1d0985 aurel32
#undef VROTATE
2709 5e1d0985 aurel32
2710 071fc3b1 aurel32
void helper_vrsqrtefp (ppc_avr_t *r, ppc_avr_t *b)
2711 071fc3b1 aurel32
{
2712 071fc3b1 aurel32
    int i;
2713 071fc3b1 aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2714 071fc3b1 aurel32
        HANDLE_NAN1(r->f[i], b->f[i]) {
2715 071fc3b1 aurel32
            float32 t = float32_sqrt(b->f[i], &env->vec_status);
2716 071fc3b1 aurel32
            r->f[i] = float32_div(float32_one, t, &env->vec_status);
2717 071fc3b1 aurel32
        }
2718 071fc3b1 aurel32
    }
2719 071fc3b1 aurel32
}
2720 071fc3b1 aurel32
2721 d1258698 aurel32
void helper_vsel (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2722 d1258698 aurel32
{
2723 d1258698 aurel32
    r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
2724 d1258698 aurel32
    r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
2725 d1258698 aurel32
}
2726 d1258698 aurel32
2727 b580763f aurel32
void helper_vlogefp (ppc_avr_t *r, ppc_avr_t *b)
2728 f586ce09 aurel32
{
2729 f586ce09 aurel32
    int i;
2730 f586ce09 aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2731 f586ce09 aurel32
        HANDLE_NAN1(r->f[i], b->f[i]) {
2732 f586ce09 aurel32
            r->f[i] = float32_log2(b->f[i], &env->vec_status);
2733 f586ce09 aurel32
        }
2734 f586ce09 aurel32
    }
2735 f586ce09 aurel32
}
2736 f586ce09 aurel32
2737 d9430add aurel32
#if defined(WORDS_BIGENDIAN)
2738 d9430add aurel32
#define LEFT 0
2739 d9430add aurel32
#define RIGHT 1
2740 d9430add aurel32
#else
2741 d9430add aurel32
#define LEFT 1
2742 d9430add aurel32
#define RIGHT 0
2743 d9430add aurel32
#endif
2744 d9430add aurel32
/* The specification says that the results are undefined if all of the
2745 d9430add aurel32
 * shift counts are not identical.  We check to make sure that they are
2746 d9430add aurel32
 * to conform to what real hardware appears to do.  */
2747 d9430add aurel32
#define VSHIFT(suffix, leftp)                                           \
2748 d9430add aurel32
    void helper_vs##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
2749 d9430add aurel32
    {                                                                   \
2750 d9430add aurel32
        int shift = b->u8[LO_IDX*0x15] & 0x7;                           \
2751 d9430add aurel32
        int doit = 1;                                                   \
2752 d9430add aurel32
        int i;                                                          \
2753 d9430add aurel32
        for (i = 0; i < ARRAY_SIZE(r->u8); i++) {                       \
2754 d9430add aurel32
            doit = doit && ((b->u8[i] & 0x7) == shift);                 \
2755 d9430add aurel32
        }                                                               \
2756 d9430add aurel32
        if (doit) {                                                     \
2757 d9430add aurel32
            if (shift == 0) {                                           \
2758 d9430add aurel32
                *r = *a;                                                \
2759 d9430add aurel32
            } else if (leftp) {                                         \
2760 d9430add aurel32
                uint64_t carry = a->u64[LO_IDX] >> (64 - shift);        \
2761 d9430add aurel32
                r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry;     \
2762 d9430add aurel32
                r->u64[LO_IDX] = a->u64[LO_IDX] << shift;               \
2763 d9430add aurel32
            } else {                                                    \
2764 d9430add aurel32
                uint64_t carry = a->u64[HI_IDX] << (64 - shift);        \
2765 d9430add aurel32
                r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry;     \
2766 d9430add aurel32
                r->u64[HI_IDX] = a->u64[HI_IDX] >> shift;               \
2767 d9430add aurel32
            }                                                           \
2768 d9430add aurel32
        }                                                               \
2769 d9430add aurel32
    }
2770 d9430add aurel32
VSHIFT(l, LEFT)
2771 d9430add aurel32
VSHIFT(r, RIGHT)
2772 d9430add aurel32
#undef VSHIFT
2773 d9430add aurel32
#undef LEFT
2774 d9430add aurel32
#undef RIGHT
2775 d9430add aurel32
2776 d79f0809 aurel32
#define VSL(suffix, element)                                            \
2777 d79f0809 aurel32
    void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2778 d79f0809 aurel32
    {                                                                   \
2779 d79f0809 aurel32
        int i;                                                          \
2780 d79f0809 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2781 d79f0809 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2782 d79f0809 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2783 d79f0809 aurel32
            r->element[i] = a->element[i] << shift;                     \
2784 d79f0809 aurel32
        }                                                               \
2785 d79f0809 aurel32
    }
2786 d79f0809 aurel32
VSL(b, u8)
2787 d79f0809 aurel32
VSL(h, u16)
2788 d79f0809 aurel32
VSL(w, u32)
2789 d79f0809 aurel32
#undef VSL
2790 d79f0809 aurel32
2791 cd633b10 aurel32
void helper_vsldoi (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
2792 cd633b10 aurel32
{
2793 cd633b10 aurel32
    int sh = shift & 0xf;
2794 cd633b10 aurel32
    int i;
2795 cd633b10 aurel32
    ppc_avr_t result;
2796 cd633b10 aurel32
2797 cd633b10 aurel32
#if defined(WORDS_BIGENDIAN)
2798 cd633b10 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2799 cd633b10 aurel32
        int index = sh + i;
2800 cd633b10 aurel32
        if (index > 0xf) {
2801 cd633b10 aurel32
            result.u8[i] = b->u8[index-0x10];
2802 cd633b10 aurel32
        } else {
2803 cd633b10 aurel32
            result.u8[i] = a->u8[index];
2804 cd633b10 aurel32
        }
2805 cd633b10 aurel32
    }
2806 cd633b10 aurel32
#else
2807 cd633b10 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2808 cd633b10 aurel32
        int index = (16 - sh) + i;
2809 cd633b10 aurel32
        if (index > 0xf) {
2810 cd633b10 aurel32
            result.u8[i] = a->u8[index-0x10];
2811 cd633b10 aurel32
        } else {
2812 cd633b10 aurel32
            result.u8[i] = b->u8[index];
2813 cd633b10 aurel32
        }
2814 cd633b10 aurel32
    }
2815 cd633b10 aurel32
#endif
2816 cd633b10 aurel32
    *r = result;
2817 cd633b10 aurel32
}
2818 cd633b10 aurel32
2819 7b239bec aurel32
void helper_vslo (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2820 7b239bec aurel32
{
2821 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2822 7b239bec aurel32
2823 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2824 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2825 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2826 7b239bec aurel32
#else
2827 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2828 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2829 7b239bec aurel32
#endif
2830 7b239bec aurel32
}
2831 7b239bec aurel32
2832 e4e6bee7 aurel32
/* Experimental testing shows that hardware masks the immediate.  */
2833 e4e6bee7 aurel32
#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
2834 e4e6bee7 aurel32
#if defined(WORDS_BIGENDIAN)
2835 e4e6bee7 aurel32
#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
2836 e4e6bee7 aurel32
#else
2837 e4e6bee7 aurel32
#define SPLAT_ELEMENT(element) (ARRAY_SIZE(r->element)-1 - _SPLAT_MASKED(element))
2838 e4e6bee7 aurel32
#endif
2839 e4e6bee7 aurel32
#define VSPLT(suffix, element)                                          \
2840 e4e6bee7 aurel32
    void helper_vsplt##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
2841 e4e6bee7 aurel32
    {                                                                   \
2842 e4e6bee7 aurel32
        uint32_t s = b->element[SPLAT_ELEMENT(element)];                \
2843 e4e6bee7 aurel32
        int i;                                                          \
2844 e4e6bee7 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2845 e4e6bee7 aurel32
            r->element[i] = s;                                          \
2846 e4e6bee7 aurel32
        }                                                               \
2847 e4e6bee7 aurel32
    }
2848 e4e6bee7 aurel32
VSPLT(b, u8)
2849 e4e6bee7 aurel32
VSPLT(h, u16)
2850 e4e6bee7 aurel32
VSPLT(w, u32)
2851 e4e6bee7 aurel32
#undef VSPLT
2852 e4e6bee7 aurel32
#undef SPLAT_ELEMENT
2853 e4e6bee7 aurel32
#undef _SPLAT_MASKED
2854 e4e6bee7 aurel32
2855 c026766b aurel32
#define VSPLTI(suffix, element, splat_type)                     \
2856 c026766b aurel32
    void helper_vspltis##suffix (ppc_avr_t *r, uint32_t splat)  \
2857 c026766b aurel32
    {                                                           \
2858 c026766b aurel32
        splat_type x = (int8_t)(splat << 3) >> 3;               \
2859 c026766b aurel32
        int i;                                                  \
2860 c026766b aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {          \
2861 c026766b aurel32
            r->element[i] = x;                                  \
2862 c026766b aurel32
        }                                                       \
2863 c026766b aurel32
    }
2864 c026766b aurel32
VSPLTI(b, s8, int8_t)
2865 c026766b aurel32
VSPLTI(h, s16, int16_t)
2866 c026766b aurel32
VSPLTI(w, s32, int32_t)
2867 c026766b aurel32
#undef VSPLTI
2868 c026766b aurel32
2869 07ef34c3 aurel32
#define VSR(suffix, element)                                            \
2870 07ef34c3 aurel32
    void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2871 07ef34c3 aurel32
    {                                                                   \
2872 07ef34c3 aurel32
        int i;                                                          \
2873 07ef34c3 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2874 07ef34c3 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2875 07ef34c3 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2876 07ef34c3 aurel32
            r->element[i] = a->element[i] >> shift;                     \
2877 07ef34c3 aurel32
        }                                                               \
2878 07ef34c3 aurel32
    }
2879 07ef34c3 aurel32
VSR(ab, s8)
2880 07ef34c3 aurel32
VSR(ah, s16)
2881 07ef34c3 aurel32
VSR(aw, s32)
2882 07ef34c3 aurel32
VSR(b, u8)
2883 07ef34c3 aurel32
VSR(h, u16)
2884 07ef34c3 aurel32
VSR(w, u32)
2885 07ef34c3 aurel32
#undef VSR
2886 07ef34c3 aurel32
2887 7b239bec aurel32
void helper_vsro (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2888 7b239bec aurel32
{
2889 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2890 7b239bec aurel32
2891 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2892 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2893 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2894 7b239bec aurel32
#else
2895 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2896 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2897 7b239bec aurel32
#endif
2898 7b239bec aurel32
}
2899 7b239bec aurel32
2900 e343da72 aurel32
void helper_vsubcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2901 e343da72 aurel32
{
2902 e343da72 aurel32
    int i;
2903 e343da72 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2904 e343da72 aurel32
        r->u32[i] = a->u32[i] >= b->u32[i];
2905 e343da72 aurel32
    }
2906 e343da72 aurel32
}
2907 e343da72 aurel32
2908 8142cddd aurel32
void helper_vsumsws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2909 8142cddd aurel32
{
2910 8142cddd aurel32
    int64_t t;
2911 8142cddd aurel32
    int i, upper;
2912 8142cddd aurel32
    ppc_avr_t result;
2913 8142cddd aurel32
    int sat = 0;
2914 8142cddd aurel32
2915 8142cddd aurel32
#if defined(WORDS_BIGENDIAN)
2916 8142cddd aurel32
    upper = ARRAY_SIZE(r->s32)-1;
2917 8142cddd aurel32
#else
2918 8142cddd aurel32
    upper = 0;
2919 8142cddd aurel32
#endif
2920 8142cddd aurel32
    t = (int64_t)b->s32[upper];
2921 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2922 8142cddd aurel32
        t += a->s32[i];
2923 8142cddd aurel32
        result.s32[i] = 0;
2924 8142cddd aurel32
    }
2925 8142cddd aurel32
    result.s32[upper] = cvtsdsw(t, &sat);
2926 8142cddd aurel32
    *r = result;
2927 8142cddd aurel32
2928 8142cddd aurel32
    if (sat) {
2929 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2930 8142cddd aurel32
    }
2931 8142cddd aurel32
}
2932 8142cddd aurel32
2933 8142cddd aurel32
void helper_vsum2sws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2934 8142cddd aurel32
{
2935 8142cddd aurel32
    int i, j, upper;
2936 8142cddd aurel32
    ppc_avr_t result;
2937 8142cddd aurel32
    int sat = 0;
2938 8142cddd aurel32
2939 8142cddd aurel32
#if defined(WORDS_BIGENDIAN)
2940 8142cddd aurel32
    upper = 1;
2941 8142cddd aurel32
#else
2942 8142cddd aurel32
    upper = 0;
2943 8142cddd aurel32
#endif
2944 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
2945 8142cddd aurel32
        int64_t t = (int64_t)b->s32[upper+i*2];
2946 8142cddd aurel32
        result.u64[i] = 0;
2947 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
2948 8142cddd aurel32
            t += a->s32[2*i+j];
2949 8142cddd aurel32
        }
2950 8142cddd aurel32
        result.s32[upper+i*2] = cvtsdsw(t, &sat);
2951 8142cddd aurel32
    }
2952 8142cddd aurel32
2953 8142cddd aurel32
    *r = result;
2954 8142cddd aurel32
    if (sat) {
2955 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2956 8142cddd aurel32
    }
2957 8142cddd aurel32
}
2958 8142cddd aurel32
2959 8142cddd aurel32
void helper_vsum4sbs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2960 8142cddd aurel32
{
2961 8142cddd aurel32
    int i, j;
2962 8142cddd aurel32
    int sat = 0;
2963 8142cddd aurel32
2964 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2965 8142cddd aurel32
        int64_t t = (int64_t)b->s32[i];
2966 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
2967 8142cddd aurel32
            t += a->s8[4*i+j];
2968 8142cddd aurel32
        }
2969 8142cddd aurel32
        r->s32[i] = cvtsdsw(t, &sat);
2970 8142cddd aurel32
    }
2971 8142cddd aurel32
2972 8142cddd aurel32
    if (sat) {
2973 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2974 8142cddd aurel32
    }
2975 8142cddd aurel32
}
2976 8142cddd aurel32
2977 8142cddd aurel32
void helper_vsum4shs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2978 8142cddd aurel32
{
2979 8142cddd aurel32
    int sat = 0;
2980 8142cddd aurel32
    int i;
2981 8142cddd aurel32
2982 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2983 8142cddd aurel32
        int64_t t = (int64_t)b->s32[i];
2984 8142cddd aurel32
        t += a->s16[2*i] + a->s16[2*i+1];
2985 8142cddd aurel32
        r->s32[i] = cvtsdsw(t, &sat);
2986 8142cddd aurel32
    }
2987 8142cddd aurel32
2988 8142cddd aurel32
    if (sat) {
2989 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2990 8142cddd aurel32
    }
2991 8142cddd aurel32
}
2992 8142cddd aurel32
2993 8142cddd aurel32
void helper_vsum4ubs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2994 8142cddd aurel32
{
2995 8142cddd aurel32
    int i, j;
2996 8142cddd aurel32
    int sat = 0;
2997 8142cddd aurel32
2998 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2999 8142cddd aurel32
        uint64_t t = (uint64_t)b->u32[i];
3000 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
3001 8142cddd aurel32
            t += a->u8[4*i+j];
3002 8142cddd aurel32
        }
3003 8142cddd aurel32
        r->u32[i] = cvtuduw(t, &sat);
3004 8142cddd aurel32
    }
3005 8142cddd aurel32
3006 8142cddd aurel32
    if (sat) {
3007 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
3008 8142cddd aurel32
    }
3009 8142cddd aurel32
}
3010 8142cddd aurel32
3011 79f85c3a aurel32
#if defined(WORDS_BIGENDIAN)
3012 79f85c3a aurel32
#define UPKHI 1
3013 79f85c3a aurel32
#define UPKLO 0
3014 79f85c3a aurel32
#else
3015 79f85c3a aurel32
#define UPKHI 0
3016 79f85c3a aurel32
#define UPKLO 1
3017 79f85c3a aurel32
#endif
3018 79f85c3a aurel32
#define VUPKPX(suffix, hi)                                      \
3019 79f85c3a aurel32
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)       \
3020 79f85c3a aurel32
    {                                                           \
3021 79f85c3a aurel32
        int i;                                                  \
3022 79f85c3a aurel32
        ppc_avr_t result;                                       \
3023 79f85c3a aurel32
        for (i = 0; i < ARRAY_SIZE(r->u32); i++) {              \
3024 79f85c3a aurel32
            uint16_t e = b->u16[hi ? i : i+4];                  \
3025 79f85c3a aurel32
            uint8_t a = (e >> 15) ? 0xff : 0;                   \
3026 79f85c3a aurel32
            uint8_t r = (e >> 10) & 0x1f;                       \
3027 79f85c3a aurel32
            uint8_t g = (e >> 5) & 0x1f;                        \
3028 79f85c3a aurel32
            uint8_t b = e & 0x1f;                               \
3029 79f85c3a aurel32
            result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
3030 79f85c3a aurel32
        }                                                               \
3031 79f85c3a aurel32
        *r = result;                                                    \
3032 79f85c3a aurel32
    }
3033 79f85c3a aurel32
VUPKPX(lpx, UPKLO)
3034 79f85c3a aurel32
VUPKPX(hpx, UPKHI)
3035 79f85c3a aurel32
#undef VUPKPX
3036 79f85c3a aurel32
3037 6cf1c6e5 aurel32
#define VUPK(suffix, unpacked, packee, hi)                              \
3038 6cf1c6e5 aurel32
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
3039 6cf1c6e5 aurel32
    {                                                                   \
3040 6cf1c6e5 aurel32
        int i;                                                          \
3041 6cf1c6e5 aurel32
        ppc_avr_t result;                                               \
3042 6cf1c6e5 aurel32
        if (hi) {                                                       \
3043 6cf1c6e5 aurel32
            for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
3044 6cf1c6e5 aurel32
                result.unpacked[i] = b->packee[i];                      \
3045 6cf1c6e5 aurel32
            }                                                           \
3046 6cf1c6e5 aurel32
        } else {                                                        \
3047 6cf1c6e5 aurel32
            for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); i++) { \
3048 6cf1c6e5 aurel32
                result.unpacked[i-ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
3049 6cf1c6e5 aurel32
            }                                                           \
3050 6cf1c6e5 aurel32
        }                                                               \
3051 6cf1c6e5 aurel32
        *r = result;                                                    \
3052 6cf1c6e5 aurel32
    }
3053 6cf1c6e5 aurel32
VUPK(hsb, s16, s8, UPKHI)
3054 6cf1c6e5 aurel32
VUPK(hsh, s32, s16, UPKHI)
3055 6cf1c6e5 aurel32
VUPK(lsb, s16, s8, UPKLO)
3056 6cf1c6e5 aurel32
VUPK(lsh, s32, s16, UPKLO)
3057 6cf1c6e5 aurel32
#undef VUPK
3058 79f85c3a aurel32
#undef UPKHI
3059 79f85c3a aurel32
#undef UPKLO
3060 79f85c3a aurel32
3061 34ba2857 aurel32
#undef DO_HANDLE_NAN
3062 34ba2857 aurel32
#undef HANDLE_NAN1
3063 34ba2857 aurel32
#undef HANDLE_NAN2
3064 34ba2857 aurel32
#undef HANDLE_NAN3
3065 d6a46fe8 aurel32
#undef VECTOR_FOR_INORDER_I
3066 d6a46fe8 aurel32
#undef HI_IDX
3067 d6a46fe8 aurel32
#undef LO_IDX
3068 d6a46fe8 aurel32
3069 d6a46fe8 aurel32
/*****************************************************************************/
3070 0487d6a8 j_mayer
/* SPE extension helpers */
3071 0487d6a8 j_mayer
/* Use a table to make this quicker */
3072 0487d6a8 j_mayer
static uint8_t hbrev[16] = {
3073 0487d6a8 j_mayer
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
3074 0487d6a8 j_mayer
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
3075 0487d6a8 j_mayer
};
3076 0487d6a8 j_mayer
3077 b068d6a7 j_mayer
static always_inline uint8_t byte_reverse (uint8_t val)
3078 0487d6a8 j_mayer
{
3079 0487d6a8 j_mayer
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
3080 0487d6a8 j_mayer
}
3081 0487d6a8 j_mayer
3082 b068d6a7 j_mayer
static always_inline uint32_t word_reverse (uint32_t val)
3083 0487d6a8 j_mayer
{
3084 0487d6a8 j_mayer
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
3085 0487d6a8 j_mayer
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
3086 0487d6a8 j_mayer
}
3087 0487d6a8 j_mayer
3088 3cd7d1dd j_mayer
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
3089 57951c27 aurel32
target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
3090 0487d6a8 j_mayer
{
3091 0487d6a8 j_mayer
    uint32_t a, b, d, mask;
3092 0487d6a8 j_mayer
3093 3cd7d1dd j_mayer
    mask = UINT32_MAX >> (32 - MASKBITS);
3094 57951c27 aurel32
    a = arg1 & mask;
3095 57951c27 aurel32
    b = arg2 & mask;
3096 3cd7d1dd j_mayer
    d = word_reverse(1 + word_reverse(a | ~b));
3097 57951c27 aurel32
    return (arg1 & ~mask) | (d & b);
3098 0487d6a8 j_mayer
}
3099 0487d6a8 j_mayer
3100 57951c27 aurel32
uint32_t helper_cntlsw32 (uint32_t val)
3101 0487d6a8 j_mayer
{
3102 0487d6a8 j_mayer
    if (val & 0x80000000)
3103 603fccce j_mayer
        return clz32(~val);
3104 0487d6a8 j_mayer
    else
3105 603fccce j_mayer
        return clz32(val);
3106 0487d6a8 j_mayer
}
3107 0487d6a8 j_mayer
3108 57951c27 aurel32
uint32_t helper_cntlzw32 (uint32_t val)
3109 0487d6a8 j_mayer
{
3110 603fccce j_mayer
    return clz32(val);
3111 0487d6a8 j_mayer
}
3112 0487d6a8 j_mayer
3113 1c97856d aurel32
/* Single-precision floating-point conversions */
3114 1c97856d aurel32
static always_inline uint32_t efscfsi (uint32_t val)
3115 0487d6a8 j_mayer
{
3116 0ca9d380 aurel32
    CPU_FloatU u;
3117 0487d6a8 j_mayer
3118 fbd265b6 aurel32
    u.f = int32_to_float32(val, &env->vec_status);
3119 0487d6a8 j_mayer
3120 0ca9d380 aurel32
    return u.l;
3121 0487d6a8 j_mayer
}
3122 0487d6a8 j_mayer
3123 1c97856d aurel32
static always_inline uint32_t efscfui (uint32_t val)
3124 0487d6a8 j_mayer
{
3125 0ca9d380 aurel32
    CPU_FloatU u;
3126 0487d6a8 j_mayer
3127 fbd265b6 aurel32
    u.f = uint32_to_float32(val, &env->vec_status);
3128 0487d6a8 j_mayer
3129 0ca9d380 aurel32
    return u.l;
3130 0487d6a8 j_mayer
}
3131 0487d6a8 j_mayer
3132 1c97856d aurel32
static always_inline int32_t efsctsi (uint32_t val)
3133 0487d6a8 j_mayer
{
3134 0ca9d380 aurel32
    CPU_FloatU u;
3135 0487d6a8 j_mayer
3136 0ca9d380 aurel32
    u.l = val;
3137 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3138 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3139 0487d6a8 j_mayer
        return 0;
3140 0487d6a8 j_mayer
3141 fbd265b6 aurel32
    return float32_to_int32(u.f, &env->vec_status);
3142 0487d6a8 j_mayer
}
3143 0487d6a8 j_mayer
3144 1c97856d aurel32
static always_inline uint32_t efsctui (uint32_t val)
3145 0487d6a8 j_mayer
{
3146 0ca9d380 aurel32
    CPU_FloatU u;
3147 0487d6a8 j_mayer
3148 0ca9d380 aurel32
    u.l = val;
3149 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3150 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3151 0487d6a8 j_mayer
        return 0;
3152 0487d6a8 j_mayer
3153 fbd265b6 aurel32
    return float32_to_uint32(u.f, &env->vec_status);
3154 0487d6a8 j_mayer
}
3155 0487d6a8 j_mayer
3156 1c97856d aurel32
static always_inline uint32_t efsctsiz (uint32_t val)
3157 0487d6a8 j_mayer
{
3158 0ca9d380 aurel32
    CPU_FloatU u;
3159 0487d6a8 j_mayer
3160 0ca9d380 aurel32
    u.l = val;
3161 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3162 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3163 0487d6a8 j_mayer
        return 0;
3164 0487d6a8 j_mayer
3165 fbd265b6 aurel32
    return float32_to_int32_round_to_zero(u.f, &env->vec_status);
3166 0487d6a8 j_mayer
}
3167 0487d6a8 j_mayer
3168 1c97856d aurel32
static always_inline uint32_t efsctuiz (uint32_t val)
3169 0487d6a8 j_mayer
{
3170 0ca9d380 aurel32
    CPU_FloatU u;
3171 0487d6a8 j_mayer
3172 0ca9d380 aurel32
    u.l = val;
3173 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3174 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3175 0487d6a8 j_mayer
        return 0;
3176 0487d6a8 j_mayer
3177 fbd265b6 aurel32
    return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
3178 0487d6a8 j_mayer
}
3179 0487d6a8 j_mayer
3180 1c97856d aurel32
static always_inline uint32_t efscfsf (uint32_t val)
3181 0487d6a8 j_mayer
{
3182 0ca9d380 aurel32
    CPU_FloatU u;
3183 0487d6a8 j_mayer
    float32 tmp;
3184 0487d6a8 j_mayer
3185 fbd265b6 aurel32
    u.f = int32_to_float32(val, &env->vec_status);
3186 fbd265b6 aurel32
    tmp = int64_to_float32(1ULL << 32, &env->vec_status);
3187 fbd265b6 aurel32
    u.f = float32_div(u.f, tmp, &env->vec_status);
3188 0487d6a8 j_mayer
3189 0ca9d380 aurel32
    return u.l;
3190 0487d6a8 j_mayer
}
3191 0487d6a8 j_mayer
3192 1c97856d aurel32
static always_inline uint32_t efscfuf (uint32_t val)
3193 0487d6a8 j_mayer
{
3194 0ca9d380 aurel32
    CPU_FloatU u;
3195 0487d6a8 j_mayer
    float32 tmp;
3196 0487d6a8 j_mayer
3197 fbd265b6 aurel32
    u.f = uint32_to_float32(val, &env->vec_status);
3198 fbd265b6 aurel32
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3199 fbd265b6 aurel32
    u.f = float32_div(u.f, tmp, &env->vec_status);
3200 0487d6a8 j_mayer
3201 0ca9d380 aurel32
    return u.l;
3202 0487d6a8 j_mayer
}
3203 0487d6a8 j_mayer
3204 1c97856d aurel32
static always_inline uint32_t efsctsf (uint32_t val)
3205 0487d6a8 j_mayer
{
3206 0ca9d380 aurel32
    CPU_FloatU u;
3207 0487d6a8 j_mayer
    float32 tmp;
3208 0487d6a8 j_mayer
3209 0ca9d380 aurel32
    u.l = val;
3210 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3211 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3212 0487d6a8 j_mayer
        return 0;
3213 fbd265b6 aurel32
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3214 fbd265b6 aurel32
    u.f = float32_mul(u.f, tmp, &env->vec_status);
3215 0487d6a8 j_mayer
3216 fbd265b6 aurel32
    return float32_to_int32(u.f, &env->vec_status);
3217 0487d6a8 j_mayer
}
3218 0487d6a8 j_mayer
3219 1c97856d aurel32
static always_inline uint32_t efsctuf (uint32_t val)
3220 0487d6a8 j_mayer
{
3221 0ca9d380 aurel32
    CPU_FloatU u;
3222 0487d6a8 j_mayer
    float32 tmp;
3223 0487d6a8 j_mayer
3224 0ca9d380 aurel32
    u.l = val;
3225 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3226 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3227 0487d6a8 j_mayer
        return 0;
3228 fbd265b6 aurel32
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3229 fbd265b6 aurel32
    u.f = float32_mul(u.f, tmp, &env->vec_status);
3230 0487d6a8 j_mayer
3231 fbd265b6 aurel32
    return float32_to_uint32(u.f, &env->vec_status);
3232 0487d6a8 j_mayer
}
3233 0487d6a8 j_mayer
3234 1c97856d aurel32
#define HELPER_SPE_SINGLE_CONV(name)                                          \
3235 1c97856d aurel32
uint32_t helper_e##name (uint32_t val)                                        \
3236 1c97856d aurel32
{                                                                             \
3237 1c97856d aurel32
    return e##name(val);                                                      \
3238 1c97856d aurel32
}
3239 1c97856d aurel32
/* efscfsi */
3240 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsi);
3241 1c97856d aurel32
/* efscfui */
3242 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfui);
3243 1c97856d aurel32
/* efscfuf */
3244 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfuf);
3245 1c97856d aurel32
/* efscfsf */
3246 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsf);
3247 1c97856d aurel32
/* efsctsi */
3248 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsi);
3249 1c97856d aurel32
/* efsctui */
3250 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctui);
3251 1c97856d aurel32
/* efsctsiz */
3252 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsiz);
3253 1c97856d aurel32
/* efsctuiz */
3254 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuiz);
3255 1c97856d aurel32
/* efsctsf */
3256 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsf);
3257 1c97856d aurel32
/* efsctuf */
3258 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuf);
3259 1c97856d aurel32
3260 1c97856d aurel32
#define HELPER_SPE_VECTOR_CONV(name)                                          \
3261 1c97856d aurel32
uint64_t helper_ev##name (uint64_t val)                                       \
3262 1c97856d aurel32
{                                                                             \
3263 1c97856d aurel32
    return ((uint64_t)e##name(val >> 32) << 32) |                             \
3264 1c97856d aurel32
            (uint64_t)e##name(val);                                           \
3265 0487d6a8 j_mayer
}
3266 1c97856d aurel32
/* evfscfsi */
3267 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsi);
3268 1c97856d aurel32
/* evfscfui */
3269 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfui);
3270 1c97856d aurel32
/* evfscfuf */
3271 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfuf);
3272 1c97856d aurel32
/* evfscfsf */
3273 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsf);
3274 1c97856d aurel32
/* evfsctsi */
3275 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsi);
3276 1c97856d aurel32
/* evfsctui */
3277 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctui);
3278 1c97856d aurel32
/* evfsctsiz */
3279 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsiz);
3280 1c97856d aurel32
/* evfsctuiz */
3281 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuiz);
3282 1c97856d aurel32
/* evfsctsf */
3283 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsf);
3284 1c97856d aurel32
/* evfsctuf */
3285 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuf);
3286 0487d6a8 j_mayer
3287 1c97856d aurel32
/* Single-precision floating-point arithmetic */
3288 1c97856d aurel32
static always_inline uint32_t efsadd (uint32_t op1, uint32_t op2)
3289 0487d6a8 j_mayer
{
3290 1c97856d aurel32
    CPU_FloatU u1, u2;
3291 1c97856d aurel32
    u1.l = op1;
3292 1c97856d aurel32
    u2.l = op2;
3293 fbd265b6 aurel32
    u1.f = float32_add(u1.f, u2.f, &env->vec_status);
3294 1c97856d aurel32
    return u1.l;
3295 0487d6a8 j_mayer
}
3296 0487d6a8 j_mayer
3297 1c97856d aurel32
static always_inline uint32_t efssub (uint32_t op1, uint32_t op2)
3298 0487d6a8 j_mayer
{
3299 1c97856d aurel32
    CPU_FloatU u1, u2;
3300 1c97856d aurel32
    u1.l = op1;
3301 1c97856d aurel32
    u2.l = op2;
3302 fbd265b6 aurel32
    u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
3303 1c97856d aurel32
    return u1.l;
3304 0487d6a8 j_mayer
}
3305 0487d6a8 j_mayer
3306 1c97856d aurel32
static always_inline uint32_t efsmul (uint32_t op1, uint32_t op2)
3307 0487d6a8 j_mayer
{
3308 1c97856d aurel32
    CPU_FloatU u1, u2;
3309 1c97856d aurel32
    u1.l = op1;
3310 1c97856d aurel32
    u2.l = op2;
3311 fbd265b6 aurel32
    u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
3312 1c97856d aurel32
    return u1.l;
3313 0487d6a8 j_mayer
}
3314 0487d6a8 j_mayer
3315 1c97856d aurel32
static always_inline uint32_t efsdiv (uint32_t op1, uint32_t op2)
3316 0487d6a8 j_mayer
{
3317 1c97856d aurel32
    CPU_FloatU u1, u2;
3318 1c97856d aurel32
    u1.l = op1;
3319 1c97856d aurel32
    u2.l = op2;
3320 fbd265b6 aurel32
    u1.f = float32_div(u1.f, u2.f, &env->vec_status);
3321 1c97856d aurel32
    return u1.l;
3322 0487d6a8 j_mayer
}
3323 0487d6a8 j_mayer
3324 1c97856d aurel32
#define HELPER_SPE_SINGLE_ARITH(name)                                         \
3325 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
3326 1c97856d aurel32
{                                                                             \
3327 1c97856d aurel32
    return e##name(op1, op2);                                                 \
3328 1c97856d aurel32
}
3329 1c97856d aurel32
/* efsadd */
3330 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsadd);
3331 1c97856d aurel32
/* efssub */
3332 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fssub);
3333 1c97856d aurel32
/* efsmul */
3334 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsmul);
3335 1c97856d aurel32
/* efsdiv */
3336 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsdiv);
3337 1c97856d aurel32
3338 1c97856d aurel32
#define HELPER_SPE_VECTOR_ARITH(name)                                         \
3339 1c97856d aurel32
uint64_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3340 1c97856d aurel32
{                                                                             \
3341 1c97856d aurel32
    return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |                  \
3342 1c97856d aurel32
            (uint64_t)e##name(op1, op2);                                      \
3343 1c97856d aurel32
}
3344 1c97856d aurel32
/* evfsadd */
3345 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsadd);
3346 1c97856d aurel32
/* evfssub */
3347 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fssub);
3348 1c97856d aurel32
/* evfsmul */
3349 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsmul);
3350 1c97856d aurel32
/* evfsdiv */
3351 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsdiv);
3352 1c97856d aurel32
3353 1c97856d aurel32
/* Single-precision floating-point comparisons */
3354 1c97856d aurel32
static always_inline uint32_t efststlt (uint32_t op1, uint32_t op2)
3355 0487d6a8 j_mayer
{
3356 1c97856d aurel32
    CPU_FloatU u1, u2;
3357 1c97856d aurel32
    u1.l = op1;
3358 1c97856d aurel32
    u2.l = op2;
3359 fbd265b6 aurel32
    return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3360 0487d6a8 j_mayer
}
3361 0487d6a8 j_mayer
3362 1c97856d aurel32
static always_inline uint32_t efststgt (uint32_t op1, uint32_t op2)
3363 0487d6a8 j_mayer
{
3364 1c97856d aurel32
    CPU_FloatU u1, u2;
3365 1c97856d aurel32
    u1.l = op1;
3366 1c97856d aurel32
    u2.l = op2;
3367 fbd265b6 aurel32
    return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
3368 0487d6a8 j_mayer
}
3369 0487d6a8 j_mayer
3370 1c97856d aurel32
static always_inline uint32_t efststeq (uint32_t op1, uint32_t op2)
3371 0487d6a8 j_mayer
{
3372 1c97856d aurel32
    CPU_FloatU u1, u2;
3373 1c97856d aurel32
    u1.l = op1;
3374 1c97856d aurel32
    u2.l = op2;
3375 fbd265b6 aurel32
    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3376 0487d6a8 j_mayer
}
3377 0487d6a8 j_mayer
3378 1c97856d aurel32
static always_inline uint32_t efscmplt (uint32_t op1, uint32_t op2)
3379 0487d6a8 j_mayer
{
3380 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3381 1c97856d aurel32
    return efststlt(op1, op2);
3382 0487d6a8 j_mayer
}
3383 0487d6a8 j_mayer
3384 1c97856d aurel32
static always_inline uint32_t efscmpgt (uint32_t op1, uint32_t op2)
3385 0487d6a8 j_mayer
{
3386 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3387 1c97856d aurel32
    return efststgt(op1, op2);
3388 0487d6a8 j_mayer
}
3389 0487d6a8 j_mayer
3390 1c97856d aurel32
static always_inline uint32_t efscmpeq (uint32_t op1, uint32_t op2)
3391 0487d6a8 j_mayer
{
3392 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3393 1c97856d aurel32
    return efststeq(op1, op2);
3394 0487d6a8 j_mayer
}
3395 0487d6a8 j_mayer
3396 1c97856d aurel32
#define HELPER_SINGLE_SPE_CMP(name)                                           \
3397 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
3398 1c97856d aurel32
{                                                                             \
3399 1c97856d aurel32
    return e##name(op1, op2) << 2;                                            \
3400 1c97856d aurel32
}
3401 1c97856d aurel32
/* efststlt */
3402 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststlt);
3403 1c97856d aurel32
/* efststgt */
3404 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststgt);
3405 1c97856d aurel32
/* efststeq */
3406 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststeq);
3407 1c97856d aurel32
/* efscmplt */
3408 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmplt);
3409 1c97856d aurel32
/* efscmpgt */
3410 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpgt);
3411 1c97856d aurel32
/* efscmpeq */
3412 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpeq);
3413 1c97856d aurel32
3414 1c97856d aurel32
static always_inline uint32_t evcmp_merge (int t0, int t1)
3415 0487d6a8 j_mayer
{
3416 1c97856d aurel32
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
3417 0487d6a8 j_mayer
}
3418 0487d6a8 j_mayer
3419 1c97856d aurel32
#define HELPER_VECTOR_SPE_CMP(name)                                           \
3420 1c97856d aurel32
uint32_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3421 1c97856d aurel32
{                                                                             \
3422 1c97856d aurel32
    return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2));     \
3423 0487d6a8 j_mayer
}
3424 1c97856d aurel32
/* evfststlt */
3425 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststlt);
3426 1c97856d aurel32
/* evfststgt */
3427 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststgt);
3428 1c97856d aurel32
/* evfststeq */
3429 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststeq);
3430 1c97856d aurel32
/* evfscmplt */
3431 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmplt);
3432 1c97856d aurel32
/* evfscmpgt */
3433 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpgt);
3434 1c97856d aurel32
/* evfscmpeq */
3435 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpeq);
3436 0487d6a8 j_mayer
3437 1c97856d aurel32
/* Double-precision floating-point conversion */
3438 1c97856d aurel32
uint64_t helper_efdcfsi (uint32_t val)
3439 0487d6a8 j_mayer
{
3440 1c97856d aurel32
    CPU_DoubleU u;
3441 1c97856d aurel32
3442 fbd265b6 aurel32
    u.d = int32_to_float64(val, &env->vec_status);
3443 1c97856d aurel32
3444 1c97856d aurel32
    return u.ll;
3445 0487d6a8 j_mayer
}
3446 0487d6a8 j_mayer
3447 1c97856d aurel32
uint64_t helper_efdcfsid (uint64_t val)
3448 0487d6a8 j_mayer
{
3449 0ca9d380 aurel32
    CPU_DoubleU u;
3450 0487d6a8 j_mayer
3451 fbd265b6 aurel32
    u.d = int64_to_float64(val, &env->vec_status);
3452 0487d6a8 j_mayer
3453 0ca9d380 aurel32
    return u.ll;
3454 0487d6a8 j_mayer
}
3455 0487d6a8 j_mayer
3456 1c97856d aurel32
uint64_t helper_efdcfui (uint32_t val)
3457 1c97856d aurel32
{
3458 1c97856d aurel32
    CPU_DoubleU u;
3459 1c97856d aurel32
3460 fbd265b6 aurel32
    u.d = uint32_to_float64(val, &env->vec_status);
3461 1c97856d aurel32
3462 1c97856d aurel32
    return u.ll;
3463 1c97856d aurel32
}
3464 1c97856d aurel32
3465 1c97856d aurel32
uint64_t helper_efdcfuid (uint64_t val)
3466 0487d6a8 j_mayer
{
3467 0ca9d380 aurel32
    CPU_DoubleU u;
3468 0487d6a8 j_mayer
3469 fbd265b6 aurel32
    u.d = uint64_to_float64(val, &env->vec_status);
3470 0487d6a8 j_mayer
3471 0ca9d380 aurel32
    return u.ll;
3472 0487d6a8 j_mayer
}
3473 0487d6a8 j_mayer
3474 1c97856d aurel32
uint32_t helper_efdctsi (uint64_t val)
3475 0487d6a8 j_mayer
{
3476 0ca9d380 aurel32
    CPU_DoubleU u;
3477 0487d6a8 j_mayer
3478 0ca9d380 aurel32
    u.ll = val;
3479 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3480 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3481 0487d6a8 j_mayer
        return 0;
3482 0487d6a8 j_mayer
3483 fbd265b6 aurel32
    return float64_to_int32(u.d, &env->vec_status);
3484 0487d6a8 j_mayer
}
3485 0487d6a8 j_mayer
3486 1c97856d aurel32
uint32_t helper_efdctui (uint64_t val)
3487 0487d6a8 j_mayer
{
3488 0ca9d380 aurel32
    CPU_DoubleU u;
3489 0487d6a8 j_mayer
3490 0ca9d380 aurel32
    u.ll = val;
3491 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3492 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3493 0487d6a8 j_mayer
        return 0;
3494 0487d6a8 j_mayer
3495 fbd265b6 aurel32
    return float64_to_uint32(u.d, &env->vec_status);
3496 0487d6a8 j_mayer
}
3497 0487d6a8 j_mayer
3498 1c97856d aurel32
uint32_t helper_efdctsiz (uint64_t val)
3499 0487d6a8 j_mayer
{
3500 0ca9d380 aurel32
    CPU_DoubleU u;
3501 0487d6a8 j_mayer
3502 0ca9d380 aurel32
    u.ll = val;
3503 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3504 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3505 0487d6a8 j_mayer
        return 0;
3506 0487d6a8 j_mayer
3507 fbd265b6 aurel32
    return float64_to_int32_round_to_zero(u.d, &env->vec_status);
3508 0487d6a8 j_mayer
}
3509 0487d6a8 j_mayer
3510 1c97856d aurel32
uint64_t helper_efdctsidz (uint64_t val)
3511 0487d6a8 j_mayer
{
3512 0ca9d380 aurel32
    CPU_DoubleU u;
3513 0487d6a8 j_mayer
3514 0ca9d380 aurel32
    u.ll = val;
3515 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3516 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3517 0487d6a8 j_mayer
        return 0;
3518 0487d6a8 j_mayer
3519 fbd265b6 aurel32
    return float64_to_int64_round_to_zero(u.d, &env->vec_status);
3520 0487d6a8 j_mayer
}
3521 0487d6a8 j_mayer
3522 1c97856d aurel32
uint32_t helper_efdctuiz (uint64_t val)
3523 0487d6a8 j_mayer
{
3524 1c97856d aurel32
    CPU_DoubleU u;
3525 0487d6a8 j_mayer
3526 1c97856d aurel32
    u.ll = val;
3527 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
3528 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3529 1c97856d aurel32
        return 0;
3530 0487d6a8 j_mayer
3531 fbd265b6 aurel32
    return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
3532 0487d6a8 j_mayer
}
3533 0487d6a8 j_mayer
3534 1c97856d aurel32
uint64_t helper_efdctuidz (uint64_t val)
3535 0487d6a8 j_mayer
{
3536 1c97856d aurel32
    CPU_DoubleU u;
3537 0487d6a8 j_mayer
3538 1c97856d aurel32
    u.ll = val;
3539 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
3540 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3541 1c97856d aurel32
        return 0;
3542 0487d6a8 j_mayer
3543 fbd265b6 aurel32
    return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
3544 0487d6a8 j_mayer
}
3545 0487d6a8 j_mayer
3546 1c97856d aurel32
uint64_t helper_efdcfsf (uint32_t val)
3547 0487d6a8 j_mayer
{
3548 0ca9d380 aurel32
    CPU_DoubleU u;
3549 0487d6a8 j_mayer
    float64 tmp;
3550 0487d6a8 j_mayer
3551 fbd265b6 aurel32
    u.d = int32_to_float64(val, &env->vec_status);
3552 fbd265b6 aurel32
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3553 fbd265b6 aurel32
    u.d = float64_div(u.d, tmp, &env->vec_status);
3554 0487d6a8 j_mayer
3555 0ca9d380 aurel32
    return u.ll;
3556 0487d6a8 j_mayer
}
3557 0487d6a8 j_mayer
3558 1c97856d aurel32
uint64_t helper_efdcfuf (uint32_t val)
3559 0487d6a8 j_mayer
{
3560 0ca9d380 aurel32
    CPU_DoubleU u;
3561 0487d6a8 j_mayer
    float64 tmp;
3562 0487d6a8 j_mayer
3563 fbd265b6 aurel32
    u.d = uint32_to_float64(val, &env->vec_status);
3564 fbd265b6 aurel32
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3565 fbd265b6 aurel32
    u.d = float64_div(u.d, tmp, &env->vec_status);
3566 0487d6a8 j_mayer
3567 0ca9d380 aurel32
    return u.ll;
3568 0487d6a8 j_mayer
}
3569 0487d6a8 j_mayer
3570 1c97856d aurel32
uint32_t helper_efdctsf (uint64_t val)
3571 0487d6a8 j_mayer
{
3572 0ca9d380 aurel32
    CPU_DoubleU u;
3573 0487d6a8 j_mayer
    float64 tmp;
3574 0487d6a8 j_mayer
3575 0ca9d380 aurel32
    u.ll = val;
3576 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3577 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3578 0487d6a8 j_mayer
        return 0;
3579 fbd265b6 aurel32
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3580 fbd265b6 aurel32
    u.d = float64_mul(u.d, tmp, &env->vec_status);
3581 0487d6a8 j_mayer
3582 fbd265b6 aurel32
    return float64_to_int32(u.d, &env->vec_status);
3583 0487d6a8 j_mayer
}
3584 0487d6a8 j_mayer
3585 1c97856d aurel32
uint32_t helper_efdctuf (uint64_t val)
3586 0487d6a8 j_mayer
{
3587 0ca9d380 aurel32
    CPU_DoubleU u;
3588 0487d6a8 j_mayer
    float64 tmp;
3589 0487d6a8 j_mayer
3590 0ca9d380 aurel32
    u.ll = val;
3591 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3592 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3593 0487d6a8 j_mayer
        return 0;
3594 fbd265b6 aurel32
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3595 fbd265b6 aurel32
    u.d = float64_mul(u.d, tmp, &env->vec_status);
3596 0487d6a8 j_mayer
3597 fbd265b6 aurel32
    return float64_to_uint32(u.d, &env->vec_status);
3598 0487d6a8 j_mayer
}
3599 0487d6a8 j_mayer
3600 1c97856d aurel32
uint32_t helper_efscfd (uint64_t val)
3601 0487d6a8 j_mayer
{
3602 0ca9d380 aurel32
    CPU_DoubleU u1;
3603 0ca9d380 aurel32
    CPU_FloatU u2;
3604 0487d6a8 j_mayer
3605 0ca9d380 aurel32
    u1.ll = val;
3606 fbd265b6 aurel32
    u2.f = float64_to_float32(u1.d, &env->vec_status);
3607 0487d6a8 j_mayer
3608 0ca9d380 aurel32
    return u2.l;
3609 0487d6a8 j_mayer
}
3610 0487d6a8 j_mayer
3611 1c97856d aurel32
uint64_t helper_efdcfs (uint32_t val)
3612 0487d6a8 j_mayer
{
3613 0ca9d380 aurel32
    CPU_DoubleU u2;
3614 0ca9d380 aurel32
    CPU_FloatU u1;
3615 0487d6a8 j_mayer
3616 0ca9d380 aurel32
    u1.l = val;
3617 fbd265b6 aurel32
    u2.d = float32_to_float64(u1.f, &env->vec_status);
3618 0487d6a8 j_mayer
3619 0ca9d380 aurel32
    return u2.ll;
3620 0487d6a8 j_mayer
}
3621 0487d6a8 j_mayer
3622 1c97856d aurel32
/* Double precision fixed-point arithmetic */
3623 1c97856d aurel32
uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
3624 0487d6a8 j_mayer
{
3625 1c97856d aurel32
    CPU_DoubleU u1, u2;
3626 1c97856d aurel32
    u1.ll = op1;
3627 1c97856d aurel32
    u2.ll = op2;
3628 fbd265b6 aurel32
    u1.d = float64_add(u1.d, u2.d, &env->vec_status);
3629 1c97856d aurel32
    return u1.ll;
3630 0487d6a8 j_mayer
}
3631 0487d6a8 j_mayer
3632 1c97856d aurel32
uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
3633 0487d6a8 j_mayer
{
3634 1c97856d aurel32
    CPU_DoubleU u1, u2;
3635 1c97856d aurel32
    u1.ll = op1;
3636 1c97856d aurel32
    u2.ll = op2;
3637 fbd265b6 aurel32
    u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
3638 1c97856d aurel32
    return u1.ll;
3639 0487d6a8 j_mayer
}
3640 0487d6a8 j_mayer
3641 1c97856d aurel32
uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
3642 0487d6a8 j_mayer
{
3643 1c97856d aurel32
    CPU_DoubleU u1, u2;
3644 1c97856d aurel32
    u1.ll = op1;
3645 1c97856d aurel32
    u2.ll = op2;
3646 fbd265b6 aurel32
    u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
3647 1c97856d aurel32
    return u1.ll;
3648 0487d6a8 j_mayer
}
3649 0487d6a8 j_mayer
3650 1c97856d aurel32
uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
3651 0487d6a8 j_mayer
{
3652 1c97856d aurel32
    CPU_DoubleU u1, u2;
3653 1c97856d aurel32
    u1.ll = op1;
3654 1c97856d aurel32
    u2.ll = op2;
3655 fbd265b6 aurel32
    u1.d = float64_div(u1.d, u2.d, &env->vec_status);
3656 1c97856d aurel32
    return u1.ll;
3657 0487d6a8 j_mayer
}
3658 0487d6a8 j_mayer
3659 1c97856d aurel32
/* Double precision floating point helpers */
3660 1c97856d aurel32
uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
3661 0487d6a8 j_mayer
{
3662 1c97856d aurel32
    CPU_DoubleU u1, u2;
3663 1c97856d aurel32
    u1.ll = op1;
3664 1c97856d aurel32
    u2.ll = op2;
3665 fbd265b6 aurel32
    return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3666 0487d6a8 j_mayer
}
3667 0487d6a8 j_mayer
3668 1c97856d aurel32
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
3669 0487d6a8 j_mayer
{
3670 1c97856d aurel32
    CPU_DoubleU u1, u2;
3671 1c97856d aurel32
    u1.ll = op1;
3672 1c97856d aurel32
    u2.ll = op2;
3673 fbd265b6 aurel32
    return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
3674 0487d6a8 j_mayer
}
3675 0487d6a8 j_mayer
3676 1c97856d aurel32
uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
3677 0487d6a8 j_mayer
{
3678 1c97856d aurel32
    CPU_DoubleU u1, u2;
3679 1c97856d aurel32
    u1.ll = op1;
3680 1c97856d aurel32
    u2.ll = op2;
3681 fbd265b6 aurel32
    return float64_eq(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3682 0487d6a8 j_mayer
}
3683 0487d6a8 j_mayer
3684 1c97856d aurel32
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
3685 0487d6a8 j_mayer
{
3686 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3687 1c97856d aurel32
    return helper_efdtstlt(op1, op2);
3688 0487d6a8 j_mayer
}
3689 0487d6a8 j_mayer
3690 1c97856d aurel32
uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
3691 1c97856d aurel32
{
3692 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3693 1c97856d aurel32
    return helper_efdtstgt(op1, op2);
3694 1c97856d aurel32
}
3695 0487d6a8 j_mayer
3696 1c97856d aurel32
uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
3697 1c97856d aurel32
{
3698 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3699 1c97856d aurel32
    return helper_efdtsteq(op1, op2);
3700 1c97856d aurel32
}
3701 0487d6a8 j_mayer
3702 fdabc366 bellard
/*****************************************************************************/
3703 fdabc366 bellard
/* Softmmu support */
3704 fdabc366 bellard
#if !defined (CONFIG_USER_ONLY)
3705 fdabc366 bellard
3706 fdabc366 bellard
#define MMUSUFFIX _mmu
3707 fdabc366 bellard
3708 fdabc366 bellard
#define SHIFT 0
3709 fdabc366 bellard
#include "softmmu_template.h"
3710 fdabc366 bellard
3711 fdabc366 bellard
#define SHIFT 1
3712 fdabc366 bellard
#include "softmmu_template.h"
3713 fdabc366 bellard
3714 fdabc366 bellard
#define SHIFT 2
3715 fdabc366 bellard
#include "softmmu_template.h"
3716 fdabc366 bellard
3717 fdabc366 bellard
#define SHIFT 3
3718 fdabc366 bellard
#include "softmmu_template.h"
3719 fdabc366 bellard
3720 fdabc366 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
3721 fdabc366 bellard
   NULL, it means that the function was called in C code (i.e. not
3722 fdabc366 bellard
   from generated code or from helper.c) */
3723 fdabc366 bellard
/* XXX: fix it to restore all registers */
3724 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3725 fdabc366 bellard
{
3726 fdabc366 bellard
    TranslationBlock *tb;
3727 fdabc366 bellard
    CPUState *saved_env;
3728 44f8625d bellard
    unsigned long pc;
3729 fdabc366 bellard
    int ret;
3730 fdabc366 bellard
3731 fdabc366 bellard
    /* XXX: hack to restore env in all cases, even if not called from
3732 fdabc366 bellard
       generated code */
3733 fdabc366 bellard
    saved_env = env;
3734 fdabc366 bellard
    env = cpu_single_env;
3735 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3736 76a66253 j_mayer
    if (unlikely(ret != 0)) {
3737 fdabc366 bellard
        if (likely(retaddr)) {
3738 fdabc366 bellard
            /* now we have a real cpu fault */
3739 44f8625d bellard
            pc = (unsigned long)retaddr;
3740 fdabc366 bellard
            tb = tb_find_pc(pc);
3741 fdabc366 bellard
            if (likely(tb)) {
3742 fdabc366 bellard
                /* the PC is inside the translated code. It means that we have
3743 fdabc366 bellard
                   a virtual CPU fault */
3744 fdabc366 bellard
                cpu_restore_state(tb, env, pc, NULL);
3745 76a66253 j_mayer
            }
3746 fdabc366 bellard
        }
3747 e06fcd75 aurel32
        helper_raise_exception_err(env->exception_index, env->error_code);
3748 fdabc366 bellard
    }
3749 fdabc366 bellard
    env = saved_env;
3750 9a64fbe4 bellard
}
3751 9a64fbe4 bellard
3752 74d37793 aurel32
/* Segment registers load and store */
3753 74d37793 aurel32
target_ulong helper_load_sr (target_ulong sr_num)
3754 74d37793 aurel32
{
3755 f6b868fc blueswir1
#if defined(TARGET_PPC64)
3756 f6b868fc blueswir1
    if (env->mmu_model & POWERPC_MMU_64)
3757 f6b868fc blueswir1
        return ppc_load_sr(env, sr_num);
3758 f6b868fc blueswir1
#endif
3759 74d37793 aurel32
    return env->sr[sr_num];
3760 74d37793 aurel32
}
3761 74d37793 aurel32
3762 74d37793 aurel32
void helper_store_sr (target_ulong sr_num, target_ulong val)
3763 74d37793 aurel32
{
3764 45d827d2 aurel32
    ppc_store_sr(env, sr_num, val);
3765 74d37793 aurel32
}
3766 74d37793 aurel32
3767 74d37793 aurel32
/* SLB management */
3768 74d37793 aurel32
#if defined(TARGET_PPC64)
3769 74d37793 aurel32
target_ulong helper_load_slb (target_ulong slb_nr)
3770 74d37793 aurel32
{
3771 74d37793 aurel32
    return ppc_load_slb(env, slb_nr);
3772 74d37793 aurel32
}
3773 74d37793 aurel32
3774 f6b868fc blueswir1
void helper_store_slb (target_ulong rb, target_ulong rs)
3775 74d37793 aurel32
{
3776 f6b868fc blueswir1
    ppc_store_slb(env, rb, rs);
3777 74d37793 aurel32
}
3778 74d37793 aurel32
3779 74d37793 aurel32
void helper_slbia (void)
3780 74d37793 aurel32
{
3781 74d37793 aurel32
    ppc_slb_invalidate_all(env);
3782 74d37793 aurel32
}
3783 74d37793 aurel32
3784 74d37793 aurel32
void helper_slbie (target_ulong addr)
3785 74d37793 aurel32
{
3786 74d37793 aurel32
    ppc_slb_invalidate_one(env, addr);
3787 74d37793 aurel32
}
3788 74d37793 aurel32
3789 74d37793 aurel32
#endif /* defined(TARGET_PPC64) */
3790 74d37793 aurel32
3791 74d37793 aurel32
/* TLB management */
3792 74d37793 aurel32
void helper_tlbia (void)
3793 74d37793 aurel32
{
3794 74d37793 aurel32
    ppc_tlb_invalidate_all(env);
3795 74d37793 aurel32
}
3796 74d37793 aurel32
3797 74d37793 aurel32
void helper_tlbie (target_ulong addr)
3798 74d37793 aurel32
{
3799 74d37793 aurel32
    ppc_tlb_invalidate_one(env, addr);
3800 74d37793 aurel32
}
3801 74d37793 aurel32
3802 76a66253 j_mayer
/* Software driven TLBs management */
3803 76a66253 j_mayer
/* PowerPC 602/603 software TLB load instructions helpers */
3804 74d37793 aurel32
static void do_6xx_tlb (target_ulong new_EPN, int is_code)
3805 76a66253 j_mayer
{
3806 76a66253 j_mayer
    target_ulong RPN, CMP, EPN;
3807 76a66253 j_mayer
    int way;
3808 d9bce9d9 j_mayer
3809 76a66253 j_mayer
    RPN = env->spr[SPR_RPA];
3810 76a66253 j_mayer
    if (is_code) {
3811 76a66253 j_mayer
        CMP = env->spr[SPR_ICMP];
3812 76a66253 j_mayer
        EPN = env->spr[SPR_IMISS];
3813 76a66253 j_mayer
    } else {
3814 76a66253 j_mayer
        CMP = env->spr[SPR_DCMP];
3815 76a66253 j_mayer
        EPN = env->spr[SPR_DMISS];
3816 76a66253 j_mayer
    }
3817 76a66253 j_mayer
    way = (env->spr[SPR_SRR1] >> 17) & 1;
3818 d12d51d5 aliguori
    LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3819 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
3820 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
3821 76a66253 j_mayer
    /* Store this TLB */
3822 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3823 d9bce9d9 j_mayer
                     way, is_code, CMP, RPN);
3824 76a66253 j_mayer
}
3825 76a66253 j_mayer
3826 74d37793 aurel32
void helper_6xx_tlbd (target_ulong EPN)
3827 0f3955e2 aurel32
{
3828 74d37793 aurel32
    do_6xx_tlb(EPN, 0);
3829 0f3955e2 aurel32
}
3830 0f3955e2 aurel32
3831 74d37793 aurel32
void helper_6xx_tlbi (target_ulong EPN)
3832 0f3955e2 aurel32
{
3833 74d37793 aurel32
    do_6xx_tlb(EPN, 1);
3834 0f3955e2 aurel32
}
3835 0f3955e2 aurel32
3836 0f3955e2 aurel32
/* PowerPC 74xx software TLB load instructions helpers */
3837 74d37793 aurel32
static void do_74xx_tlb (target_ulong new_EPN, int is_code)
3838 7dbe11ac j_mayer
{
3839 7dbe11ac j_mayer
    target_ulong RPN, CMP, EPN;
3840 7dbe11ac j_mayer
    int way;
3841 7dbe11ac j_mayer
3842 7dbe11ac j_mayer
    RPN = env->spr[SPR_PTELO];
3843 7dbe11ac j_mayer
    CMP = env->spr[SPR_PTEHI];
3844 7dbe11ac j_mayer
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
3845 7dbe11ac j_mayer
    way = env->spr[SPR_TLBMISS] & 0x3;
3846 d12d51d5 aliguori
    LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3847 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
3848 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
3849 7dbe11ac j_mayer
    /* Store this TLB */
3850 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3851 7dbe11ac j_mayer
                     way, is_code, CMP, RPN);
3852 7dbe11ac j_mayer
}
3853 7dbe11ac j_mayer
3854 74d37793 aurel32
void helper_74xx_tlbd (target_ulong EPN)
3855 0f3955e2 aurel32
{
3856 74d37793 aurel32
    do_74xx_tlb(EPN, 0);
3857 0f3955e2 aurel32
}
3858 0f3955e2 aurel32
3859 74d37793 aurel32
void helper_74xx_tlbi (target_ulong EPN)
3860 0f3955e2 aurel32
{
3861 74d37793 aurel32
    do_74xx_tlb(EPN, 1);
3862 0f3955e2 aurel32
}
3863 0f3955e2 aurel32
3864 a11b8151 j_mayer
static always_inline target_ulong booke_tlb_to_page_size (int size)
3865 a8dea12f j_mayer
{
3866 a8dea12f j_mayer
    return 1024 << (2 * size);
3867 a8dea12f j_mayer
}
3868 a8dea12f j_mayer
3869 a11b8151 j_mayer
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
3870 a8dea12f j_mayer
{
3871 a8dea12f j_mayer
    int size;
3872 a8dea12f j_mayer
3873 a8dea12f j_mayer
    switch (page_size) {
3874 a8dea12f j_mayer
    case 0x00000400UL:
3875 a8dea12f j_mayer
        size = 0x0;
3876 a8dea12f j_mayer
        break;
3877 a8dea12f j_mayer
    case 0x00001000UL:
3878 a8dea12f j_mayer
        size = 0x1;
3879 a8dea12f j_mayer
        break;
3880 a8dea12f j_mayer
    case 0x00004000UL:
3881 a8dea12f j_mayer
        size = 0x2;
3882 a8dea12f j_mayer
        break;
3883 a8dea12f j_mayer
    case 0x00010000UL:
3884 a8dea12f j_mayer
        size = 0x3;
3885 a8dea12f j_mayer
        break;
3886 a8dea12f j_mayer
    case 0x00040000UL:
3887 a8dea12f j_mayer
        size = 0x4;
3888 a8dea12f j_mayer
        break;
3889 a8dea12f j_mayer
    case 0x00100000UL:
3890 a8dea12f j_mayer
        size = 0x5;
3891 a8dea12f j_mayer
        break;
3892 a8dea12f j_mayer
    case 0x00400000UL:
3893 a8dea12f j_mayer
        size = 0x6;
3894 a8dea12f j_mayer
        break;
3895 a8dea12f j_mayer
    case 0x01000000UL:
3896 a8dea12f j_mayer
        size = 0x7;
3897 a8dea12f j_mayer
        break;
3898 a8dea12f j_mayer
    case 0x04000000UL:
3899 a8dea12f j_mayer
        size = 0x8;
3900 a8dea12f j_mayer
        break;
3901 a8dea12f j_mayer
    case 0x10000000UL:
3902 a8dea12f j_mayer
        size = 0x9;
3903 a8dea12f j_mayer
        break;
3904 a8dea12f j_mayer
    case 0x40000000UL:
3905 a8dea12f j_mayer
        size = 0xA;
3906 a8dea12f j_mayer
        break;
3907 a8dea12f j_mayer
#if defined (TARGET_PPC64)
3908 a8dea12f j_mayer
    case 0x000100000000ULL:
3909 a8dea12f j_mayer
        size = 0xB;
3910 a8dea12f j_mayer
        break;
3911 a8dea12f j_mayer
    case 0x000400000000ULL:
3912 a8dea12f j_mayer
        size = 0xC;
3913 a8dea12f j_mayer
        break;
3914 a8dea12f j_mayer
    case 0x001000000000ULL:
3915 a8dea12f j_mayer
        size = 0xD;
3916 a8dea12f j_mayer
        break;
3917 a8dea12f j_mayer
    case 0x004000000000ULL:
3918 a8dea12f j_mayer
        size = 0xE;
3919 a8dea12f j_mayer
        break;
3920 a8dea12f j_mayer
    case 0x010000000000ULL:
3921 a8dea12f j_mayer
        size = 0xF;
3922 a8dea12f j_mayer
        break;
3923 a8dea12f j_mayer
#endif
3924 a8dea12f j_mayer
    default:
3925 a8dea12f j_mayer
        size = -1;
3926 a8dea12f j_mayer
        break;
3927 a8dea12f j_mayer
    }
3928 a8dea12f j_mayer
3929 a8dea12f j_mayer
    return size;
3930 a8dea12f j_mayer
}
3931 a8dea12f j_mayer
3932 76a66253 j_mayer
/* Helpers for 4xx TLB management */
3933 74d37793 aurel32
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
3934 76a66253 j_mayer
{
3935 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3936 74d37793 aurel32
    target_ulong ret;
3937 a8dea12f j_mayer
    int size;
3938 76a66253 j_mayer
3939 74d37793 aurel32
    entry &= 0x3F;
3940 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3941 74d37793 aurel32
    ret = tlb->EPN;
3942 a8dea12f j_mayer
    if (tlb->prot & PAGE_VALID)
3943 74d37793 aurel32
        ret |= 0x400;
3944 a8dea12f j_mayer
    size = booke_page_size_to_tlb(tlb->size);
3945 a8dea12f j_mayer
    if (size < 0 || size > 0x7)
3946 a8dea12f j_mayer
        size = 1;
3947 74d37793 aurel32
    ret |= size << 7;
3948 a8dea12f j_mayer
    env->spr[SPR_40x_PID] = tlb->PID;
3949 74d37793 aurel32
    return ret;
3950 76a66253 j_mayer
}
3951 76a66253 j_mayer
3952 74d37793 aurel32
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
3953 76a66253 j_mayer
{
3954 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3955 74d37793 aurel32
    target_ulong ret;
3956 76a66253 j_mayer
3957 74d37793 aurel32
    entry &= 0x3F;
3958 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3959 74d37793 aurel32
    ret = tlb->RPN;
3960 a8dea12f j_mayer
    if (tlb->prot & PAGE_EXEC)
3961 74d37793 aurel32
        ret |= 0x200;
3962 a8dea12f j_mayer
    if (tlb->prot & PAGE_WRITE)
3963 74d37793 aurel32
        ret |= 0x100;
3964 74d37793 aurel32
    return ret;
3965 76a66253 j_mayer
}
3966 76a66253 j_mayer
3967 74d37793 aurel32
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
3968 76a66253 j_mayer
{
3969 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3970 76a66253 j_mayer
    target_ulong page, end;
3971 76a66253 j_mayer
3972 d12d51d5 aliguori
    LOG_SWTLB("%s entry %d val " ADDRX "\n", __func__, (int)entry, val);
3973 74d37793 aurel32
    entry &= 0x3F;
3974 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3975 76a66253 j_mayer
    /* Invalidate previous TLB (if it's valid) */
3976 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
3977 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
3978 d12d51d5 aliguori
        LOG_SWTLB("%s: invalidate old TLB %d start " ADDRX
3979 74d37793 aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3980 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3981 76a66253 j_mayer
            tlb_flush_page(env, page);
3982 76a66253 j_mayer
    }
3983 74d37793 aurel32
    tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
3984 c294fc58 j_mayer
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
3985 c294fc58 j_mayer
     * If this ever occurs, one should use the ppcemb target instead
3986 c294fc58 j_mayer
     * of the ppc or ppc64 one
3987 c294fc58 j_mayer
     */
3988 74d37793 aurel32
    if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
3989 71c8b8fd j_mayer
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
3990 71c8b8fd j_mayer
                  "are not supported (%d)\n",
3991 74d37793 aurel32
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
3992 c294fc58 j_mayer
    }
3993 74d37793 aurel32
    tlb->EPN = val & ~(tlb->size - 1);
3994 74d37793 aurel32
    if (val & 0x40)
3995 76a66253 j_mayer
        tlb->prot |= PAGE_VALID;
3996 76a66253 j_mayer
    else
3997 76a66253 j_mayer
        tlb->prot &= ~PAGE_VALID;
3998 74d37793 aurel32
    if (val & 0x20) {
3999 c294fc58 j_mayer
        /* XXX: TO BE FIXED */
4000 c294fc58 j_mayer
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
4001 c294fc58 j_mayer
    }
4002 c55e9aef j_mayer
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
4003 74d37793 aurel32
    tlb->attr = val & 0xFF;
4004 d12d51d5 aliguori
    LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
4005 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
4006 0e69805a aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
4007 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
4008 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
4009 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
4010 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
4011 76a66253 j_mayer
    /* Invalidate new TLB (if valid) */
4012 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
4013 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
4014 d12d51d5 aliguori
        LOG_SWTLB("%s: invalidate TLB %d start " ADDRX
4015 0e69805a aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
4016 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
4017 76a66253 j_mayer
            tlb_flush_page(env, page);
4018 76a66253 j_mayer
    }
4019 76a66253 j_mayer
}
4020 76a66253 j_mayer
4021 74d37793 aurel32
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
4022 76a66253 j_mayer
{
4023 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
4024 76a66253 j_mayer
4025 d12d51d5 aliguori
    LOG_SWTLB("%s entry %i val " ADDRX "\n", __func__, (int)entry, val);
4026 74d37793 aurel32
    entry &= 0x3F;
4027 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
4028 74d37793 aurel32
    tlb->RPN = val & 0xFFFFFC00;
4029 76a66253 j_mayer
    tlb->prot = PAGE_READ;
4030 74d37793 aurel32
    if (val & 0x200)
4031 76a66253 j_mayer
        tlb->prot |= PAGE_EXEC;
4032 74d37793 aurel32
    if (val & 0x100)
4033 76a66253 j_mayer
        tlb->prot |= PAGE_WRITE;
4034 d12d51d5 aliguori
    LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
4035 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
4036 74d37793 aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
4037 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
4038 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
4039 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
4040 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
4041 76a66253 j_mayer
}
4042 5eb7995e j_mayer
4043 74d37793 aurel32
target_ulong helper_4xx_tlbsx (target_ulong address)
4044 74d37793 aurel32
{
4045 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
4046 74d37793 aurel32
}
4047 74d37793 aurel32
4048 a4bb6c3e j_mayer
/* PowerPC 440 TLB management */
4049 74d37793 aurel32
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
4050 5eb7995e j_mayer
{
4051 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
4052 a4bb6c3e j_mayer
    target_ulong EPN, RPN, size;
4053 5eb7995e j_mayer
    int do_flush_tlbs;
4054 5eb7995e j_mayer
4055 d12d51d5 aliguori
    LOG_SWTLB("%s word %d entry %d value " ADDRX "\n",
4056 0e69805a aurel32
                __func__, word, (int)entry, value);
4057 5eb7995e j_mayer
    do_flush_tlbs = 0;
4058 74d37793 aurel32
    entry &= 0x3F;
4059 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
4060 a4bb6c3e j_mayer
    switch (word) {
4061 a4bb6c3e j_mayer
    default:
4062 a4bb6c3e j_mayer
        /* Just here to please gcc */
4063 a4bb6c3e j_mayer
    case 0:
4064 74d37793 aurel32
        EPN = value & 0xFFFFFC00;
4065 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
4066 5eb7995e j_mayer
            do_flush_tlbs = 1;
4067 a4bb6c3e j_mayer
        tlb->EPN = EPN;
4068 74d37793 aurel32
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
4069 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
4070 a4bb6c3e j_mayer
            do_flush_tlbs = 1;
4071 a4bb6c3e j_mayer
        tlb->size = size;
4072 a4bb6c3e j_mayer
        tlb->attr &= ~0x1;
4073 74d37793 aurel32
        tlb->attr |= (value >> 8) & 1;
4074 74d37793 aurel32
        if (value & 0x200) {
4075 a4bb6c3e j_mayer
            tlb->prot |= PAGE_VALID;
4076 a4bb6c3e j_mayer
        } else {
4077 a4bb6c3e j_mayer
            if (tlb->prot & PAGE_VALID) {
4078 a4bb6c3e j_mayer
                tlb->prot &= ~PAGE_VALID;
4079 a4bb6c3e j_mayer
                do_flush_tlbs = 1;
4080 a4bb6c3e j_mayer
            }
4081 5eb7995e j_mayer
        }
4082 a4bb6c3e j_mayer
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
4083 a4bb6c3e j_mayer
        if (do_flush_tlbs)
4084 a4bb6c3e j_mayer
            tlb_flush(env, 1);
4085 a4bb6c3e j_mayer
        break;
4086 a4bb6c3e j_mayer
    case 1:
4087 74d37793 aurel32
        RPN = value & 0xFFFFFC0F;
4088 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
4089 a4bb6c3e j_mayer
            tlb_flush(env, 1);
4090 a4bb6c3e j_mayer
        tlb->RPN = RPN;
4091 a4bb6c3e j_mayer
        break;
4092 a4bb6c3e j_mayer
    case 2:
4093 74d37793 aurel32
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
4094 a4bb6c3e j_mayer
        tlb->prot = tlb->prot & PAGE_VALID;
4095 74d37793 aurel32
        if (value & 0x1)
4096 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ << 4;
4097 74d37793 aurel32
        if (value & 0x2)
4098 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE << 4;
4099 74d37793 aurel32
        if (value & 0x4)
4100 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC << 4;
4101 74d37793 aurel32
        if (value & 0x8)
4102 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ;
4103 74d37793 aurel32
        if (value & 0x10)
4104 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE;
4105 74d37793 aurel32
        if (value & 0x20)
4106 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC;
4107 a4bb6c3e j_mayer
        break;
4108 5eb7995e j_mayer
    }
4109 5eb7995e j_mayer
}
4110 5eb7995e j_mayer
4111 74d37793 aurel32
target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
4112 5eb7995e j_mayer
{
4113 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
4114 74d37793 aurel32
    target_ulong ret;
4115 5eb7995e j_mayer
    int size;
4116 5eb7995e j_mayer
4117 74d37793 aurel32
    entry &= 0x3F;
4118 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
4119 a4bb6c3e j_mayer
    switch (word) {
4120 a4bb6c3e j_mayer
    default:
4121 a4bb6c3e j_mayer
        /* Just here to please gcc */
4122 a4bb6c3e j_mayer
    case 0:
4123 74d37793 aurel32
        ret = tlb->EPN;
4124 a4bb6c3e j_mayer
        size = booke_page_size_to_tlb(tlb->size);
4125 a4bb6c3e j_mayer
        if (size < 0 || size > 0xF)
4126 a4bb6c3e j_mayer
            size = 1;
4127 74d37793 aurel32
        ret |= size << 4;
4128 a4bb6c3e j_mayer
        if (tlb->attr & 0x1)
4129 74d37793 aurel32
            ret |= 0x100;
4130 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_VALID)
4131 74d37793 aurel32
            ret |= 0x200;
4132 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
4133 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] |= tlb->PID;
4134 a4bb6c3e j_mayer
        break;
4135 a4bb6c3e j_mayer
    case 1:
4136 74d37793 aurel32
        ret = tlb->RPN;
4137 a4bb6c3e j_mayer
        break;
4138 a4bb6c3e j_mayer
    case 2:
4139 74d37793 aurel32
        ret = tlb->attr & ~0x1;
4140 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_READ << 4))
4141 74d37793 aurel32
            ret |= 0x1;
4142 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_WRITE << 4))
4143 74d37793 aurel32
            ret |= 0x2;
4144 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_EXEC << 4))
4145 74d37793 aurel32
            ret |= 0x4;
4146 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_READ)
4147 74d37793 aurel32
            ret |= 0x8;
4148 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_WRITE)
4149 74d37793 aurel32
            ret |= 0x10;
4150 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_EXEC)
4151 74d37793 aurel32
            ret |= 0x20;
4152 a4bb6c3e j_mayer
        break;
4153 a4bb6c3e j_mayer
    }
4154 74d37793 aurel32
    return ret;
4155 5eb7995e j_mayer
}
4156 74d37793 aurel32
4157 74d37793 aurel32
target_ulong helper_440_tlbsx (target_ulong address)
4158 74d37793 aurel32
{
4159 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
4160 74d37793 aurel32
}
4161 74d37793 aurel32
4162 76a66253 j_mayer
#endif /* !CONFIG_USER_ONLY */