Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 819ca121

History | View | Annotate | Download (122.1 kB)

1 9a64fbe4 bellard
/*
2 3fc6c082 bellard
 *  PowerPC emulation helpers for qemu.
3 5fafdf24 ths
 *
4 76a66253 j_mayer
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5 9a64fbe4 bellard
 *
6 9a64fbe4 bellard
 * This library is free software; you can redistribute it and/or
7 9a64fbe4 bellard
 * modify it under the terms of the GNU Lesser General Public
8 9a64fbe4 bellard
 * License as published by the Free Software Foundation; either
9 9a64fbe4 bellard
 * version 2 of the License, or (at your option) any later version.
10 9a64fbe4 bellard
 *
11 9a64fbe4 bellard
 * This library is distributed in the hope that it will be useful,
12 9a64fbe4 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 9a64fbe4 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 9a64fbe4 bellard
 * Lesser General Public License for more details.
15 9a64fbe4 bellard
 *
16 9a64fbe4 bellard
 * You should have received a copy of the GNU Lesser General Public
17 9a64fbe4 bellard
 * License along with this library; if not, write to the Free Software
18 fad6cb1a aurel32
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19 9a64fbe4 bellard
 */
20 7b239bec aurel32
#include <string.h>
21 9a64fbe4 bellard
#include "exec.h"
22 603fccce j_mayer
#include "host-utils.h"
23 a7812ae4 pbrook
#include "helper.h"
24 9a64fbe4 bellard
25 0411a972 j_mayer
#include "helper_regs.h"
26 0487d6a8 j_mayer
27 fdabc366 bellard
//#define DEBUG_OP
28 fdabc366 bellard
//#define DEBUG_EXCEPTIONS
29 76a66253 j_mayer
//#define DEBUG_SOFTWARE_TLB
30 fdabc366 bellard
31 d12d51d5 aliguori
#ifdef DEBUG_SOFTWARE_TLB
32 93fcfe39 aliguori
#  define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
33 d12d51d5 aliguori
#else
34 d12d51d5 aliguori
#  define LOG_SWTLB(...) do { } while (0)
35 d12d51d5 aliguori
#endif
36 d12d51d5 aliguori
37 d12d51d5 aliguori
38 9a64fbe4 bellard
/*****************************************************************************/
39 9a64fbe4 bellard
/* Exceptions processing helpers */
40 9a64fbe4 bellard
41 64adab3f aurel32
void helper_raise_exception_err (uint32_t exception, uint32_t error_code)
42 9a64fbe4 bellard
{
43 e06fcd75 aurel32
#if 0
44 e06fcd75 aurel32
    printf("Raise exception %3x code : %d\n", exception, error_code);
45 e06fcd75 aurel32
#endif
46 e06fcd75 aurel32
    env->exception_index = exception;
47 e06fcd75 aurel32
    env->error_code = error_code;
48 e06fcd75 aurel32
    cpu_loop_exit();
49 76a66253 j_mayer
}
50 9fddaa0c bellard
51 e06fcd75 aurel32
void helper_raise_exception (uint32_t exception)
52 9fddaa0c bellard
{
53 e06fcd75 aurel32
    helper_raise_exception_err(exception, 0);
54 9a64fbe4 bellard
}
55 9a64fbe4 bellard
56 9a64fbe4 bellard
/*****************************************************************************/
57 76a66253 j_mayer
/* Registers load and stores */
58 a7812ae4 pbrook
target_ulong helper_load_cr (void)
59 76a66253 j_mayer
{
60 e1571908 aurel32
    return (env->crf[0] << 28) |
61 e1571908 aurel32
           (env->crf[1] << 24) |
62 e1571908 aurel32
           (env->crf[2] << 20) |
63 e1571908 aurel32
           (env->crf[3] << 16) |
64 e1571908 aurel32
           (env->crf[4] << 12) |
65 e1571908 aurel32
           (env->crf[5] << 8) |
66 e1571908 aurel32
           (env->crf[6] << 4) |
67 e1571908 aurel32
           (env->crf[7] << 0);
68 76a66253 j_mayer
}
69 76a66253 j_mayer
70 e1571908 aurel32
void helper_store_cr (target_ulong val, uint32_t mask)
71 76a66253 j_mayer
{
72 76a66253 j_mayer
    int i, sh;
73 76a66253 j_mayer
74 36081602 j_mayer
    for (i = 0, sh = 7; i < 8; i++, sh--) {
75 76a66253 j_mayer
        if (mask & (1 << sh))
76 e1571908 aurel32
            env->crf[i] = (val >> (sh * 4)) & 0xFUL;
77 76a66253 j_mayer
    }
78 76a66253 j_mayer
}
79 76a66253 j_mayer
80 45d827d2 aurel32
/*****************************************************************************/
81 45d827d2 aurel32
/* SPR accesses */
82 45d827d2 aurel32
void helper_load_dump_spr (uint32_t sprn)
83 a496775f j_mayer
{
84 93fcfe39 aliguori
    qemu_log("Read SPR %d %03x => " ADDRX "\n",
85 a496775f j_mayer
                sprn, sprn, env->spr[sprn]);
86 a496775f j_mayer
}
87 a496775f j_mayer
88 45d827d2 aurel32
void helper_store_dump_spr (uint32_t sprn)
89 a496775f j_mayer
{
90 93fcfe39 aliguori
    qemu_log("Write SPR %d %03x <= " ADDRX "\n",
91 45d827d2 aurel32
                sprn, sprn, env->spr[sprn]);
92 45d827d2 aurel32
}
93 45d827d2 aurel32
94 45d827d2 aurel32
target_ulong helper_load_tbl (void)
95 45d827d2 aurel32
{
96 45d827d2 aurel32
    return cpu_ppc_load_tbl(env);
97 45d827d2 aurel32
}
98 45d827d2 aurel32
99 45d827d2 aurel32
target_ulong helper_load_tbu (void)
100 45d827d2 aurel32
{
101 45d827d2 aurel32
    return cpu_ppc_load_tbu(env);
102 45d827d2 aurel32
}
103 45d827d2 aurel32
104 45d827d2 aurel32
target_ulong helper_load_atbl (void)
105 45d827d2 aurel32
{
106 45d827d2 aurel32
    return cpu_ppc_load_atbl(env);
107 45d827d2 aurel32
}
108 45d827d2 aurel32
109 45d827d2 aurel32
target_ulong helper_load_atbu (void)
110 45d827d2 aurel32
{
111 45d827d2 aurel32
    return cpu_ppc_load_atbu(env);
112 45d827d2 aurel32
}
113 45d827d2 aurel32
114 45d827d2 aurel32
target_ulong helper_load_601_rtcl (void)
115 45d827d2 aurel32
{
116 45d827d2 aurel32
    return cpu_ppc601_load_rtcl(env);
117 45d827d2 aurel32
}
118 45d827d2 aurel32
119 45d827d2 aurel32
target_ulong helper_load_601_rtcu (void)
120 45d827d2 aurel32
{
121 45d827d2 aurel32
    return cpu_ppc601_load_rtcu(env);
122 45d827d2 aurel32
}
123 45d827d2 aurel32
124 45d827d2 aurel32
#if !defined(CONFIG_USER_ONLY)
125 45d827d2 aurel32
#if defined (TARGET_PPC64)
126 45d827d2 aurel32
void helper_store_asr (target_ulong val)
127 45d827d2 aurel32
{
128 45d827d2 aurel32
    ppc_store_asr(env, val);
129 45d827d2 aurel32
}
130 45d827d2 aurel32
#endif
131 45d827d2 aurel32
132 45d827d2 aurel32
void helper_store_sdr1 (target_ulong val)
133 45d827d2 aurel32
{
134 45d827d2 aurel32
    ppc_store_sdr1(env, val);
135 45d827d2 aurel32
}
136 45d827d2 aurel32
137 45d827d2 aurel32
void helper_store_tbl (target_ulong val)
138 45d827d2 aurel32
{
139 45d827d2 aurel32
    cpu_ppc_store_tbl(env, val);
140 45d827d2 aurel32
}
141 45d827d2 aurel32
142 45d827d2 aurel32
void helper_store_tbu (target_ulong val)
143 45d827d2 aurel32
{
144 45d827d2 aurel32
    cpu_ppc_store_tbu(env, val);
145 45d827d2 aurel32
}
146 45d827d2 aurel32
147 45d827d2 aurel32
void helper_store_atbl (target_ulong val)
148 45d827d2 aurel32
{
149 45d827d2 aurel32
    cpu_ppc_store_atbl(env, val);
150 45d827d2 aurel32
}
151 45d827d2 aurel32
152 45d827d2 aurel32
void helper_store_atbu (target_ulong val)
153 45d827d2 aurel32
{
154 45d827d2 aurel32
    cpu_ppc_store_atbu(env, val);
155 45d827d2 aurel32
}
156 45d827d2 aurel32
157 45d827d2 aurel32
void helper_store_601_rtcl (target_ulong val)
158 45d827d2 aurel32
{
159 45d827d2 aurel32
    cpu_ppc601_store_rtcl(env, val);
160 45d827d2 aurel32
}
161 45d827d2 aurel32
162 45d827d2 aurel32
void helper_store_601_rtcu (target_ulong val)
163 45d827d2 aurel32
{
164 45d827d2 aurel32
    cpu_ppc601_store_rtcu(env, val);
165 45d827d2 aurel32
}
166 45d827d2 aurel32
167 45d827d2 aurel32
target_ulong helper_load_decr (void)
168 45d827d2 aurel32
{
169 45d827d2 aurel32
    return cpu_ppc_load_decr(env);
170 45d827d2 aurel32
}
171 45d827d2 aurel32
172 45d827d2 aurel32
void helper_store_decr (target_ulong val)
173 45d827d2 aurel32
{
174 45d827d2 aurel32
    cpu_ppc_store_decr(env, val);
175 45d827d2 aurel32
}
176 45d827d2 aurel32
177 45d827d2 aurel32
void helper_store_hid0_601 (target_ulong val)
178 45d827d2 aurel32
{
179 45d827d2 aurel32
    target_ulong hid0;
180 45d827d2 aurel32
181 45d827d2 aurel32
    hid0 = env->spr[SPR_HID0];
182 45d827d2 aurel32
    if ((val ^ hid0) & 0x00000008) {
183 45d827d2 aurel32
        /* Change current endianness */
184 45d827d2 aurel32
        env->hflags &= ~(1 << MSR_LE);
185 45d827d2 aurel32
        env->hflags_nmsr &= ~(1 << MSR_LE);
186 45d827d2 aurel32
        env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
187 45d827d2 aurel32
        env->hflags |= env->hflags_nmsr;
188 93fcfe39 aliguori
        qemu_log("%s: set endianness to %c => " ADDRX "\n",
189 45d827d2 aurel32
                    __func__, val & 0x8 ? 'l' : 'b', env->hflags);
190 a496775f j_mayer
    }
191 45d827d2 aurel32
    env->spr[SPR_HID0] = (uint32_t)val;
192 a496775f j_mayer
}
193 a496775f j_mayer
194 45d827d2 aurel32
void helper_store_403_pbr (uint32_t num, target_ulong value)
195 45d827d2 aurel32
{
196 45d827d2 aurel32
    if (likely(env->pb[num] != value)) {
197 45d827d2 aurel32
        env->pb[num] = value;
198 45d827d2 aurel32
        /* Should be optimized */
199 45d827d2 aurel32
        tlb_flush(env, 1);
200 45d827d2 aurel32
    }
201 45d827d2 aurel32
}
202 45d827d2 aurel32
203 45d827d2 aurel32
target_ulong helper_load_40x_pit (void)
204 45d827d2 aurel32
{
205 45d827d2 aurel32
    return load_40x_pit(env);
206 45d827d2 aurel32
}
207 45d827d2 aurel32
208 45d827d2 aurel32
void helper_store_40x_pit (target_ulong val)
209 45d827d2 aurel32
{
210 45d827d2 aurel32
    store_40x_pit(env, val);
211 45d827d2 aurel32
}
212 45d827d2 aurel32
213 45d827d2 aurel32
void helper_store_40x_dbcr0 (target_ulong val)
214 45d827d2 aurel32
{
215 45d827d2 aurel32
    store_40x_dbcr0(env, val);
216 45d827d2 aurel32
}
217 45d827d2 aurel32
218 45d827d2 aurel32
void helper_store_40x_sler (target_ulong val)
219 45d827d2 aurel32
{
220 45d827d2 aurel32
    store_40x_sler(env, val);
221 45d827d2 aurel32
}
222 45d827d2 aurel32
223 45d827d2 aurel32
void helper_store_booke_tcr (target_ulong val)
224 45d827d2 aurel32
{
225 45d827d2 aurel32
    store_booke_tcr(env, val);
226 45d827d2 aurel32
}
227 45d827d2 aurel32
228 45d827d2 aurel32
void helper_store_booke_tsr (target_ulong val)
229 45d827d2 aurel32
{
230 45d827d2 aurel32
    store_booke_tsr(env, val);
231 45d827d2 aurel32
}
232 45d827d2 aurel32
233 45d827d2 aurel32
void helper_store_ibatu (uint32_t nr, target_ulong val)
234 45d827d2 aurel32
{
235 45d827d2 aurel32
    ppc_store_ibatu(env, nr, val);
236 45d827d2 aurel32
}
237 45d827d2 aurel32
238 45d827d2 aurel32
void helper_store_ibatl (uint32_t nr, target_ulong val)
239 45d827d2 aurel32
{
240 45d827d2 aurel32
    ppc_store_ibatl(env, nr, val);
241 45d827d2 aurel32
}
242 45d827d2 aurel32
243 45d827d2 aurel32
void helper_store_dbatu (uint32_t nr, target_ulong val)
244 45d827d2 aurel32
{
245 45d827d2 aurel32
    ppc_store_dbatu(env, nr, val);
246 45d827d2 aurel32
}
247 45d827d2 aurel32
248 45d827d2 aurel32
void helper_store_dbatl (uint32_t nr, target_ulong val)
249 45d827d2 aurel32
{
250 45d827d2 aurel32
    ppc_store_dbatl(env, nr, val);
251 45d827d2 aurel32
}
252 45d827d2 aurel32
253 45d827d2 aurel32
void helper_store_601_batl (uint32_t nr, target_ulong val)
254 45d827d2 aurel32
{
255 45d827d2 aurel32
    ppc_store_ibatl_601(env, nr, val);
256 45d827d2 aurel32
}
257 45d827d2 aurel32
258 45d827d2 aurel32
void helper_store_601_batu (uint32_t nr, target_ulong val)
259 45d827d2 aurel32
{
260 45d827d2 aurel32
    ppc_store_ibatu_601(env, nr, val);
261 45d827d2 aurel32
}
262 45d827d2 aurel32
#endif
263 45d827d2 aurel32
264 76a66253 j_mayer
/*****************************************************************************/
265 ff4a62cd aurel32
/* Memory load and stores */
266 ff4a62cd aurel32
267 76db3ba4 aurel32
static always_inline target_ulong addr_add(target_ulong addr, target_long arg)
268 ff4a62cd aurel32
{
269 ff4a62cd aurel32
#if defined(TARGET_PPC64)
270 76db3ba4 aurel32
        if (!msr_sf)
271 76db3ba4 aurel32
            return (uint32_t)(addr + arg);
272 ff4a62cd aurel32
        else
273 ff4a62cd aurel32
#endif
274 76db3ba4 aurel32
            return addr + arg;
275 ff4a62cd aurel32
}
276 ff4a62cd aurel32
277 ff4a62cd aurel32
void helper_lmw (target_ulong addr, uint32_t reg)
278 ff4a62cd aurel32
{
279 76db3ba4 aurel32
    for (; reg < 32; reg++) {
280 ff4a62cd aurel32
        if (msr_le)
281 76db3ba4 aurel32
            env->gpr[reg] = bswap32(ldl(addr));
282 ff4a62cd aurel32
        else
283 76db3ba4 aurel32
            env->gpr[reg] = ldl(addr);
284 76db3ba4 aurel32
        addr = addr_add(addr, 4);
285 ff4a62cd aurel32
    }
286 ff4a62cd aurel32
}
287 ff4a62cd aurel32
288 ff4a62cd aurel32
void helper_stmw (target_ulong addr, uint32_t reg)
289 ff4a62cd aurel32
{
290 76db3ba4 aurel32
    for (; reg < 32; reg++) {
291 ff4a62cd aurel32
        if (msr_le)
292 76db3ba4 aurel32
            stl(addr, bswap32((uint32_t)env->gpr[reg]));
293 ff4a62cd aurel32
        else
294 76db3ba4 aurel32
            stl(addr, (uint32_t)env->gpr[reg]);
295 76db3ba4 aurel32
        addr = addr_add(addr, 4);
296 ff4a62cd aurel32
    }
297 ff4a62cd aurel32
}
298 ff4a62cd aurel32
299 dfbc799d aurel32
void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg)
300 dfbc799d aurel32
{
301 dfbc799d aurel32
    int sh;
302 76db3ba4 aurel32
    for (; nb > 3; nb -= 4) {
303 76db3ba4 aurel32
        env->gpr[reg] = ldl(addr);
304 dfbc799d aurel32
        reg = (reg + 1) % 32;
305 76db3ba4 aurel32
        addr = addr_add(addr, 4);
306 dfbc799d aurel32
    }
307 dfbc799d aurel32
    if (unlikely(nb > 0)) {
308 dfbc799d aurel32
        env->gpr[reg] = 0;
309 76db3ba4 aurel32
        for (sh = 24; nb > 0; nb--, sh -= 8) {
310 76db3ba4 aurel32
            env->gpr[reg] |= ldub(addr) << sh;
311 76db3ba4 aurel32
            addr = addr_add(addr, 1);
312 dfbc799d aurel32
        }
313 dfbc799d aurel32
    }
314 dfbc799d aurel32
}
315 dfbc799d aurel32
/* PPC32 specification says we must generate an exception if
316 dfbc799d aurel32
 * rA is in the range of registers to be loaded.
317 dfbc799d aurel32
 * In an other hand, IBM says this is valid, but rA won't be loaded.
318 dfbc799d aurel32
 * For now, I'll follow the spec...
319 dfbc799d aurel32
 */
320 dfbc799d aurel32
void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
321 dfbc799d aurel32
{
322 dfbc799d aurel32
    if (likely(xer_bc != 0)) {
323 dfbc799d aurel32
        if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) ||
324 dfbc799d aurel32
                     (reg < rb && (reg + xer_bc) > rb))) {
325 e06fcd75 aurel32
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
326 e06fcd75 aurel32
                                       POWERPC_EXCP_INVAL |
327 e06fcd75 aurel32
                                       POWERPC_EXCP_INVAL_LSWX);
328 dfbc799d aurel32
        } else {
329 dfbc799d aurel32
            helper_lsw(addr, xer_bc, reg);
330 dfbc799d aurel32
        }
331 dfbc799d aurel32
    }
332 dfbc799d aurel32
}
333 dfbc799d aurel32
334 dfbc799d aurel32
void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg)
335 dfbc799d aurel32
{
336 dfbc799d aurel32
    int sh;
337 76db3ba4 aurel32
    for (; nb > 3; nb -= 4) {
338 76db3ba4 aurel32
        stl(addr, env->gpr[reg]);
339 dfbc799d aurel32
        reg = (reg + 1) % 32;
340 76db3ba4 aurel32
        addr = addr_add(addr, 4);
341 dfbc799d aurel32
    }
342 dfbc799d aurel32
    if (unlikely(nb > 0)) {
343 a16b45e7 aurel32
        for (sh = 24; nb > 0; nb--, sh -= 8) {
344 76db3ba4 aurel32
            stb(addr, (env->gpr[reg] >> sh) & 0xFF);
345 a16b45e7 aurel32
            addr = addr_add(addr, 1);
346 a16b45e7 aurel32
        }
347 dfbc799d aurel32
    }
348 dfbc799d aurel32
}
349 dfbc799d aurel32
350 799a8c8d aurel32
static void do_dcbz(target_ulong addr, int dcache_line_size)
351 799a8c8d aurel32
{
352 76db3ba4 aurel32
    addr &= ~(dcache_line_size - 1);
353 799a8c8d aurel32
    int i;
354 799a8c8d aurel32
    for (i = 0 ; i < dcache_line_size ; i += 4) {
355 dcc532c8 aurel32
        stl(addr + i , 0);
356 799a8c8d aurel32
    }
357 76db3ba4 aurel32
    if (env->reserve == addr)
358 799a8c8d aurel32
        env->reserve = (target_ulong)-1ULL;
359 799a8c8d aurel32
}
360 799a8c8d aurel32
361 799a8c8d aurel32
void helper_dcbz(target_ulong addr)
362 799a8c8d aurel32
{
363 799a8c8d aurel32
    do_dcbz(addr, env->dcache_line_size);
364 799a8c8d aurel32
}
365 799a8c8d aurel32
366 799a8c8d aurel32
void helper_dcbz_970(target_ulong addr)
367 799a8c8d aurel32
{
368 799a8c8d aurel32
    if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1)
369 799a8c8d aurel32
        do_dcbz(addr, 32);
370 799a8c8d aurel32
    else
371 799a8c8d aurel32
        do_dcbz(addr, env->dcache_line_size);
372 799a8c8d aurel32
}
373 799a8c8d aurel32
374 37d269df aurel32
void helper_icbi(target_ulong addr)
375 37d269df aurel32
{
376 37d269df aurel32
    uint32_t tmp;
377 37d269df aurel32
378 76db3ba4 aurel32
    addr &= ~(env->dcache_line_size - 1);
379 37d269df aurel32
    /* Invalidate one cache line :
380 37d269df aurel32
     * PowerPC specification says this is to be treated like a load
381 37d269df aurel32
     * (not a fetch) by the MMU. To be sure it will be so,
382 37d269df aurel32
     * do the load "by hand".
383 37d269df aurel32
     */
384 dcc532c8 aurel32
    tmp = ldl(addr);
385 37d269df aurel32
    tb_invalidate_page_range(addr, addr + env->icache_line_size);
386 37d269df aurel32
}
387 37d269df aurel32
388 bdb4b689 aurel32
// XXX: to be tested
389 bdb4b689 aurel32
target_ulong helper_lscbx (target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
390 bdb4b689 aurel32
{
391 bdb4b689 aurel32
    int i, c, d;
392 bdb4b689 aurel32
    d = 24;
393 bdb4b689 aurel32
    for (i = 0; i < xer_bc; i++) {
394 76db3ba4 aurel32
        c = ldub(addr);
395 76db3ba4 aurel32
        addr = addr_add(addr, 1);
396 bdb4b689 aurel32
        /* ra (if not 0) and rb are never modified */
397 bdb4b689 aurel32
        if (likely(reg != rb && (ra == 0 || reg != ra))) {
398 bdb4b689 aurel32
            env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
399 bdb4b689 aurel32
        }
400 bdb4b689 aurel32
        if (unlikely(c == xer_cmp))
401 bdb4b689 aurel32
            break;
402 bdb4b689 aurel32
        if (likely(d != 0)) {
403 bdb4b689 aurel32
            d -= 8;
404 bdb4b689 aurel32
        } else {
405 bdb4b689 aurel32
            d = 24;
406 bdb4b689 aurel32
            reg++;
407 bdb4b689 aurel32
            reg = reg & 0x1F;
408 bdb4b689 aurel32
        }
409 bdb4b689 aurel32
    }
410 bdb4b689 aurel32
    return i;
411 bdb4b689 aurel32
}
412 bdb4b689 aurel32
413 ff4a62cd aurel32
/*****************************************************************************/
414 fdabc366 bellard
/* Fixed point operations helpers */
415 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
416 d9bce9d9 j_mayer
417 74637406 aurel32
/* multiply high word */
418 74637406 aurel32
uint64_t helper_mulhd (uint64_t arg1, uint64_t arg2)
419 fdabc366 bellard
{
420 74637406 aurel32
    uint64_t tl, th;
421 fdabc366 bellard
422 74637406 aurel32
    muls64(&tl, &th, arg1, arg2);
423 74637406 aurel32
    return th;
424 d9bce9d9 j_mayer
}
425 d9bce9d9 j_mayer
426 74637406 aurel32
/* multiply high word unsigned */
427 74637406 aurel32
uint64_t helper_mulhdu (uint64_t arg1, uint64_t arg2)
428 fdabc366 bellard
{
429 74637406 aurel32
    uint64_t tl, th;
430 fdabc366 bellard
431 74637406 aurel32
    mulu64(&tl, &th, arg1, arg2);
432 74637406 aurel32
    return th;
433 fdabc366 bellard
}
434 fdabc366 bellard
435 74637406 aurel32
uint64_t helper_mulldo (uint64_t arg1, uint64_t arg2)
436 fdabc366 bellard
{
437 d9bce9d9 j_mayer
    int64_t th;
438 d9bce9d9 j_mayer
    uint64_t tl;
439 d9bce9d9 j_mayer
440 74637406 aurel32
    muls64(&tl, (uint64_t *)&th, arg1, arg2);
441 88ad920b j_mayer
    /* If th != 0 && th != -1, then we had an overflow */
442 6f2d8978 j_mayer
    if (likely((uint64_t)(th + 1) <= 1)) {
443 3d7b417e aurel32
        env->xer &= ~(1 << XER_OV);
444 fdabc366 bellard
    } else {
445 3d7b417e aurel32
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
446 fdabc366 bellard
    }
447 74637406 aurel32
    return (int64_t)tl;
448 d9bce9d9 j_mayer
}
449 d9bce9d9 j_mayer
#endif
450 d9bce9d9 j_mayer
451 26d67362 aurel32
target_ulong helper_cntlzw (target_ulong t)
452 603fccce j_mayer
{
453 26d67362 aurel32
    return clz32(t);
454 603fccce j_mayer
}
455 603fccce j_mayer
456 603fccce j_mayer
#if defined(TARGET_PPC64)
457 26d67362 aurel32
target_ulong helper_cntlzd (target_ulong t)
458 603fccce j_mayer
{
459 26d67362 aurel32
    return clz64(t);
460 603fccce j_mayer
}
461 603fccce j_mayer
#endif
462 603fccce j_mayer
463 9a64fbe4 bellard
/* shift right arithmetic helper */
464 26d67362 aurel32
target_ulong helper_sraw (target_ulong value, target_ulong shift)
465 9a64fbe4 bellard
{
466 9a64fbe4 bellard
    int32_t ret;
467 9a64fbe4 bellard
468 26d67362 aurel32
    if (likely(!(shift & 0x20))) {
469 26d67362 aurel32
        if (likely((uint32_t)shift != 0)) {
470 26d67362 aurel32
            shift &= 0x1f;
471 26d67362 aurel32
            ret = (int32_t)value >> shift;
472 26d67362 aurel32
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
473 3d7b417e aurel32
                env->xer &= ~(1 << XER_CA);
474 fdabc366 bellard
            } else {
475 3d7b417e aurel32
                env->xer |= (1 << XER_CA);
476 fdabc366 bellard
            }
477 fdabc366 bellard
        } else {
478 26d67362 aurel32
            ret = (int32_t)value;
479 3d7b417e aurel32
            env->xer &= ~(1 << XER_CA);
480 fdabc366 bellard
        }
481 fdabc366 bellard
    } else {
482 26d67362 aurel32
        ret = (int32_t)value >> 31;
483 26d67362 aurel32
        if (ret) {
484 3d7b417e aurel32
            env->xer |= (1 << XER_CA);
485 26d67362 aurel32
        } else {
486 26d67362 aurel32
            env->xer &= ~(1 << XER_CA);
487 76a66253 j_mayer
        }
488 fdabc366 bellard
    }
489 26d67362 aurel32
    return (target_long)ret;
490 9a64fbe4 bellard
}
491 9a64fbe4 bellard
492 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
493 26d67362 aurel32
target_ulong helper_srad (target_ulong value, target_ulong shift)
494 d9bce9d9 j_mayer
{
495 d9bce9d9 j_mayer
    int64_t ret;
496 d9bce9d9 j_mayer
497 26d67362 aurel32
    if (likely(!(shift & 0x40))) {
498 26d67362 aurel32
        if (likely((uint64_t)shift != 0)) {
499 26d67362 aurel32
            shift &= 0x3f;
500 26d67362 aurel32
            ret = (int64_t)value >> shift;
501 26d67362 aurel32
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
502 3d7b417e aurel32
                env->xer &= ~(1 << XER_CA);
503 d9bce9d9 j_mayer
            } else {
504 3d7b417e aurel32
                env->xer |= (1 << XER_CA);
505 d9bce9d9 j_mayer
            }
506 d9bce9d9 j_mayer
        } else {
507 26d67362 aurel32
            ret = (int64_t)value;
508 3d7b417e aurel32
            env->xer &= ~(1 << XER_CA);
509 d9bce9d9 j_mayer
        }
510 d9bce9d9 j_mayer
    } else {
511 26d67362 aurel32
        ret = (int64_t)value >> 63;
512 26d67362 aurel32
        if (ret) {
513 3d7b417e aurel32
            env->xer |= (1 << XER_CA);
514 26d67362 aurel32
        } else {
515 26d67362 aurel32
            env->xer &= ~(1 << XER_CA);
516 d9bce9d9 j_mayer
        }
517 d9bce9d9 j_mayer
    }
518 26d67362 aurel32
    return ret;
519 d9bce9d9 j_mayer
}
520 d9bce9d9 j_mayer
#endif
521 d9bce9d9 j_mayer
522 26d67362 aurel32
target_ulong helper_popcntb (target_ulong val)
523 d9bce9d9 j_mayer
{
524 6176a26d aurel32
    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
525 6176a26d aurel32
    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
526 6176a26d aurel32
    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
527 6176a26d aurel32
    return val;
528 d9bce9d9 j_mayer
}
529 d9bce9d9 j_mayer
530 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
531 26d67362 aurel32
target_ulong helper_popcntb_64 (target_ulong val)
532 d9bce9d9 j_mayer
{
533 6176a26d aurel32
    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
534 6176a26d aurel32
    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
535 6176a26d aurel32
    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
536 6176a26d aurel32
    return val;
537 d9bce9d9 j_mayer
}
538 d9bce9d9 j_mayer
#endif
539 d9bce9d9 j_mayer
540 fdabc366 bellard
/*****************************************************************************/
541 9a64fbe4 bellard
/* Floating point operations helpers */
542 a0d7d5a7 aurel32
uint64_t helper_float32_to_float64(uint32_t arg)
543 a0d7d5a7 aurel32
{
544 a0d7d5a7 aurel32
    CPU_FloatU f;
545 a0d7d5a7 aurel32
    CPU_DoubleU d;
546 a0d7d5a7 aurel32
    f.l = arg;
547 a0d7d5a7 aurel32
    d.d = float32_to_float64(f.f, &env->fp_status);
548 a0d7d5a7 aurel32
    return d.ll;
549 a0d7d5a7 aurel32
}
550 a0d7d5a7 aurel32
551 a0d7d5a7 aurel32
uint32_t helper_float64_to_float32(uint64_t arg)
552 a0d7d5a7 aurel32
{
553 a0d7d5a7 aurel32
    CPU_FloatU f;
554 a0d7d5a7 aurel32
    CPU_DoubleU d;
555 a0d7d5a7 aurel32
    d.ll = arg;
556 a0d7d5a7 aurel32
    f.f = float64_to_float32(d.d, &env->fp_status);
557 a0d7d5a7 aurel32
    return f.l;
558 a0d7d5a7 aurel32
}
559 a0d7d5a7 aurel32
560 0ca9d380 aurel32
static always_inline int isden (float64 d)
561 7c58044c j_mayer
{
562 0ca9d380 aurel32
    CPU_DoubleU u;
563 7c58044c j_mayer
564 0ca9d380 aurel32
    u.d = d;
565 7c58044c j_mayer
566 0ca9d380 aurel32
    return ((u.ll >> 52) & 0x7FF) == 0;
567 7c58044c j_mayer
}
568 7c58044c j_mayer
569 af12906f aurel32
uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
570 7c58044c j_mayer
{
571 af12906f aurel32
    CPU_DoubleU farg;
572 7c58044c j_mayer
    int isneg;
573 af12906f aurel32
    int ret;
574 af12906f aurel32
    farg.ll = arg;
575 f23c346e aurel32
    isneg = float64_is_neg(farg.d);
576 af12906f aurel32
    if (unlikely(float64_is_nan(farg.d))) {
577 af12906f aurel32
        if (float64_is_signaling_nan(farg.d)) {
578 7c58044c j_mayer
            /* Signaling NaN: flags are undefined */
579 af12906f aurel32
            ret = 0x00;
580 7c58044c j_mayer
        } else {
581 7c58044c j_mayer
            /* Quiet NaN */
582 af12906f aurel32
            ret = 0x11;
583 7c58044c j_mayer
        }
584 f23c346e aurel32
    } else if (unlikely(float64_is_infinity(farg.d))) {
585 7c58044c j_mayer
        /* +/- infinity */
586 7c58044c j_mayer
        if (isneg)
587 af12906f aurel32
            ret = 0x09;
588 7c58044c j_mayer
        else
589 af12906f aurel32
            ret = 0x05;
590 7c58044c j_mayer
    } else {
591 f23c346e aurel32
        if (float64_is_zero(farg.d)) {
592 7c58044c j_mayer
            /* +/- zero */
593 7c58044c j_mayer
            if (isneg)
594 af12906f aurel32
                ret = 0x12;
595 7c58044c j_mayer
            else
596 af12906f aurel32
                ret = 0x02;
597 7c58044c j_mayer
        } else {
598 af12906f aurel32
            if (isden(farg.d)) {
599 7c58044c j_mayer
                /* Denormalized numbers */
600 af12906f aurel32
                ret = 0x10;
601 7c58044c j_mayer
            } else {
602 7c58044c j_mayer
                /* Normalized numbers */
603 af12906f aurel32
                ret = 0x00;
604 7c58044c j_mayer
            }
605 7c58044c j_mayer
            if (isneg) {
606 af12906f aurel32
                ret |= 0x08;
607 7c58044c j_mayer
            } else {
608 af12906f aurel32
                ret |= 0x04;
609 7c58044c j_mayer
            }
610 7c58044c j_mayer
        }
611 7c58044c j_mayer
    }
612 7c58044c j_mayer
    if (set_fprf) {
613 7c58044c j_mayer
        /* We update FPSCR_FPRF */
614 7c58044c j_mayer
        env->fpscr &= ~(0x1F << FPSCR_FPRF);
615 af12906f aurel32
        env->fpscr |= ret << FPSCR_FPRF;
616 7c58044c j_mayer
    }
617 7c58044c j_mayer
    /* We just need fpcc to update Rc1 */
618 af12906f aurel32
    return ret & 0xF;
619 7c58044c j_mayer
}
620 7c58044c j_mayer
621 7c58044c j_mayer
/* Floating-point invalid operations exception */
622 af12906f aurel32
static always_inline uint64_t fload_invalid_op_excp (int op)
623 7c58044c j_mayer
{
624 af12906f aurel32
    uint64_t ret = 0;
625 7c58044c j_mayer
    int ve;
626 7c58044c j_mayer
627 7c58044c j_mayer
    ve = fpscr_ve;
628 e0147e41 aurel32
    switch (op) {
629 e0147e41 aurel32
    case POWERPC_EXCP_FP_VXSNAN:
630 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXSNAN;
631 e0147e41 aurel32
        break;
632 e0147e41 aurel32
    case POWERPC_EXCP_FP_VXSOFT:
633 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXSOFT;
634 e0147e41 aurel32
        break;
635 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXISI:
636 7c58044c j_mayer
        /* Magnitude subtraction of infinities */
637 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXISI;
638 7c58044c j_mayer
        goto update_arith;
639 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXIDI:
640 7c58044c j_mayer
        /* Division of infinity by infinity */
641 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXIDI;
642 7c58044c j_mayer
        goto update_arith;
643 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXZDZ:
644 7c58044c j_mayer
        /* Division of zero by zero */
645 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXZDZ;
646 7c58044c j_mayer
        goto update_arith;
647 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXIMZ:
648 7c58044c j_mayer
        /* Multiplication of zero by infinity */
649 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXIMZ;
650 7c58044c j_mayer
        goto update_arith;
651 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXVC:
652 7c58044c j_mayer
        /* Ordered comparison of NaN */
653 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXVC;
654 7c58044c j_mayer
        env->fpscr &= ~(0xF << FPSCR_FPCC);
655 7c58044c j_mayer
        env->fpscr |= 0x11 << FPSCR_FPCC;
656 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
657 7c58044c j_mayer
        if (ve != 0) {
658 7c58044c j_mayer
            env->exception_index = POWERPC_EXCP_PROGRAM;
659 7c58044c j_mayer
            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
660 7c58044c j_mayer
            /* Update the floating-point enabled exception summary */
661 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FEX;
662 7c58044c j_mayer
            /* Exception is differed */
663 7c58044c j_mayer
            ve = 0;
664 7c58044c j_mayer
        }
665 7c58044c j_mayer
        break;
666 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXSQRT:
667 7c58044c j_mayer
        /* Square root of a negative number */
668 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXSQRT;
669 7c58044c j_mayer
    update_arith:
670 7c58044c j_mayer
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
671 7c58044c j_mayer
        if (ve == 0) {
672 7c58044c j_mayer
            /* Set the result to quiet NaN */
673 e0147e41 aurel32
            ret = 0xFFF8000000000000ULL;
674 7c58044c j_mayer
            env->fpscr &= ~(0xF << FPSCR_FPCC);
675 7c58044c j_mayer
            env->fpscr |= 0x11 << FPSCR_FPCC;
676 7c58044c j_mayer
        }
677 7c58044c j_mayer
        break;
678 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXCVI:
679 7c58044c j_mayer
        /* Invalid conversion */
680 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXCVI;
681 7c58044c j_mayer
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
682 7c58044c j_mayer
        if (ve == 0) {
683 7c58044c j_mayer
            /* Set the result to quiet NaN */
684 e0147e41 aurel32
            ret = 0xFFF8000000000000ULL;
685 7c58044c j_mayer
            env->fpscr &= ~(0xF << FPSCR_FPCC);
686 7c58044c j_mayer
            env->fpscr |= 0x11 << FPSCR_FPCC;
687 7c58044c j_mayer
        }
688 7c58044c j_mayer
        break;
689 7c58044c j_mayer
    }
690 7c58044c j_mayer
    /* Update the floating-point invalid operation summary */
691 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_VX;
692 7c58044c j_mayer
    /* Update the floating-point exception summary */
693 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
694 7c58044c j_mayer
    if (ve != 0) {
695 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
696 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
697 7c58044c j_mayer
        if (msr_fe0 != 0 || msr_fe1 != 0)
698 e06fcd75 aurel32
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
699 7c58044c j_mayer
    }
700 af12906f aurel32
    return ret;
701 7c58044c j_mayer
}
702 7c58044c j_mayer
703 e33e94f9 aurel32
static always_inline void float_zero_divide_excp (void)
704 7c58044c j_mayer
{
705 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_ZX;
706 7c58044c j_mayer
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
707 7c58044c j_mayer
    /* Update the floating-point exception summary */
708 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
709 7c58044c j_mayer
    if (fpscr_ze != 0) {
710 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
711 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
712 7c58044c j_mayer
        if (msr_fe0 != 0 || msr_fe1 != 0) {
713 e06fcd75 aurel32
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
714 e06fcd75 aurel32
                                       POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
715 7c58044c j_mayer
        }
716 7c58044c j_mayer
    }
717 7c58044c j_mayer
}
718 7c58044c j_mayer
719 7c58044c j_mayer
static always_inline void float_overflow_excp (void)
720 7c58044c j_mayer
{
721 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_OX;
722 7c58044c j_mayer
    /* Update the floating-point exception summary */
723 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
724 7c58044c j_mayer
    if (fpscr_oe != 0) {
725 7c58044c j_mayer
        /* XXX: should adjust the result */
726 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
727 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
728 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
729 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
730 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
731 7c58044c j_mayer
    } else {
732 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_XX;
733 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FI;
734 7c58044c j_mayer
    }
735 7c58044c j_mayer
}
736 7c58044c j_mayer
737 7c58044c j_mayer
static always_inline void float_underflow_excp (void)
738 7c58044c j_mayer
{
739 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_UX;
740 7c58044c j_mayer
    /* Update the floating-point exception summary */
741 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
742 7c58044c j_mayer
    if (fpscr_ue != 0) {
743 7c58044c j_mayer
        /* XXX: should adjust the result */
744 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
745 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
746 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
747 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
748 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
749 7c58044c j_mayer
    }
750 7c58044c j_mayer
}
751 7c58044c j_mayer
752 7c58044c j_mayer
static always_inline void float_inexact_excp (void)
753 7c58044c j_mayer
{
754 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_XX;
755 7c58044c j_mayer
    /* Update the floating-point exception summary */
756 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
757 7c58044c j_mayer
    if (fpscr_xe != 0) {
758 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
759 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
760 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
761 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
762 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
763 7c58044c j_mayer
    }
764 7c58044c j_mayer
}
765 7c58044c j_mayer
766 7c58044c j_mayer
static always_inline void fpscr_set_rounding_mode (void)
767 7c58044c j_mayer
{
768 7c58044c j_mayer
    int rnd_type;
769 7c58044c j_mayer
770 7c58044c j_mayer
    /* Set rounding mode */
771 7c58044c j_mayer
    switch (fpscr_rn) {
772 7c58044c j_mayer
    case 0:
773 7c58044c j_mayer
        /* Best approximation (round to nearest) */
774 7c58044c j_mayer
        rnd_type = float_round_nearest_even;
775 7c58044c j_mayer
        break;
776 7c58044c j_mayer
    case 1:
777 7c58044c j_mayer
        /* Smaller magnitude (round toward zero) */
778 7c58044c j_mayer
        rnd_type = float_round_to_zero;
779 7c58044c j_mayer
        break;
780 7c58044c j_mayer
    case 2:
781 7c58044c j_mayer
        /* Round toward +infinite */
782 7c58044c j_mayer
        rnd_type = float_round_up;
783 7c58044c j_mayer
        break;
784 7c58044c j_mayer
    default:
785 7c58044c j_mayer
    case 3:
786 7c58044c j_mayer
        /* Round toward -infinite */
787 7c58044c j_mayer
        rnd_type = float_round_down;
788 7c58044c j_mayer
        break;
789 7c58044c j_mayer
    }
790 7c58044c j_mayer
    set_float_rounding_mode(rnd_type, &env->fp_status);
791 7c58044c j_mayer
}
792 7c58044c j_mayer
793 6e35d524 aurel32
void helper_fpscr_clrbit (uint32_t bit)
794 6e35d524 aurel32
{
795 6e35d524 aurel32
    int prev;
796 6e35d524 aurel32
797 6e35d524 aurel32
    prev = (env->fpscr >> bit) & 1;
798 6e35d524 aurel32
    env->fpscr &= ~(1 << bit);
799 6e35d524 aurel32
    if (prev == 1) {
800 6e35d524 aurel32
        switch (bit) {
801 6e35d524 aurel32
        case FPSCR_RN1:
802 6e35d524 aurel32
        case FPSCR_RN:
803 6e35d524 aurel32
            fpscr_set_rounding_mode();
804 6e35d524 aurel32
            break;
805 6e35d524 aurel32
        default:
806 6e35d524 aurel32
            break;
807 6e35d524 aurel32
        }
808 6e35d524 aurel32
    }
809 6e35d524 aurel32
}
810 6e35d524 aurel32
811 af12906f aurel32
void helper_fpscr_setbit (uint32_t bit)
812 7c58044c j_mayer
{
813 7c58044c j_mayer
    int prev;
814 7c58044c j_mayer
815 7c58044c j_mayer
    prev = (env->fpscr >> bit) & 1;
816 7c58044c j_mayer
    env->fpscr |= 1 << bit;
817 7c58044c j_mayer
    if (prev == 0) {
818 7c58044c j_mayer
        switch (bit) {
819 7c58044c j_mayer
        case FPSCR_VX:
820 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
821 7c58044c j_mayer
            if (fpscr_ve)
822 7c58044c j_mayer
                goto raise_ve;
823 7c58044c j_mayer
        case FPSCR_OX:
824 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
825 7c58044c j_mayer
            if (fpscr_oe)
826 7c58044c j_mayer
                goto raise_oe;
827 7c58044c j_mayer
            break;
828 7c58044c j_mayer
        case FPSCR_UX:
829 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
830 7c58044c j_mayer
            if (fpscr_ue)
831 7c58044c j_mayer
                goto raise_ue;
832 7c58044c j_mayer
            break;
833 7c58044c j_mayer
        case FPSCR_ZX:
834 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
835 7c58044c j_mayer
            if (fpscr_ze)
836 7c58044c j_mayer
                goto raise_ze;
837 7c58044c j_mayer
            break;
838 7c58044c j_mayer
        case FPSCR_XX:
839 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
840 7c58044c j_mayer
            if (fpscr_xe)
841 7c58044c j_mayer
                goto raise_xe;
842 7c58044c j_mayer
            break;
843 7c58044c j_mayer
        case FPSCR_VXSNAN:
844 7c58044c j_mayer
        case FPSCR_VXISI:
845 7c58044c j_mayer
        case FPSCR_VXIDI:
846 7c58044c j_mayer
        case FPSCR_VXZDZ:
847 7c58044c j_mayer
        case FPSCR_VXIMZ:
848 7c58044c j_mayer
        case FPSCR_VXVC:
849 7c58044c j_mayer
        case FPSCR_VXSOFT:
850 7c58044c j_mayer
        case FPSCR_VXSQRT:
851 7c58044c j_mayer
        case FPSCR_VXCVI:
852 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_VX;
853 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
854 7c58044c j_mayer
            if (fpscr_ve != 0)
855 7c58044c j_mayer
                goto raise_ve;
856 7c58044c j_mayer
            break;
857 7c58044c j_mayer
        case FPSCR_VE:
858 7c58044c j_mayer
            if (fpscr_vx != 0) {
859 7c58044c j_mayer
            raise_ve:
860 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP;
861 7c58044c j_mayer
                if (fpscr_vxsnan)
862 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXSNAN;
863 7c58044c j_mayer
                if (fpscr_vxisi)
864 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXISI;
865 7c58044c j_mayer
                if (fpscr_vxidi)
866 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXIDI;
867 7c58044c j_mayer
                if (fpscr_vxzdz)
868 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXZDZ;
869 7c58044c j_mayer
                if (fpscr_vximz)
870 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXIMZ;
871 7c58044c j_mayer
                if (fpscr_vxvc)
872 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXVC;
873 7c58044c j_mayer
                if (fpscr_vxsoft)
874 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXSOFT;
875 7c58044c j_mayer
                if (fpscr_vxsqrt)
876 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXSQRT;
877 7c58044c j_mayer
                if (fpscr_vxcvi)
878 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXCVI;
879 7c58044c j_mayer
                goto raise_excp;
880 7c58044c j_mayer
            }
881 7c58044c j_mayer
            break;
882 7c58044c j_mayer
        case FPSCR_OE:
883 7c58044c j_mayer
            if (fpscr_ox != 0) {
884 7c58044c j_mayer
            raise_oe:
885 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
886 7c58044c j_mayer
                goto raise_excp;
887 7c58044c j_mayer
            }
888 7c58044c j_mayer
            break;
889 7c58044c j_mayer
        case FPSCR_UE:
890 7c58044c j_mayer
            if (fpscr_ux != 0) {
891 7c58044c j_mayer
            raise_ue:
892 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
893 7c58044c j_mayer
                goto raise_excp;
894 7c58044c j_mayer
            }
895 7c58044c j_mayer
            break;
896 7c58044c j_mayer
        case FPSCR_ZE:
897 7c58044c j_mayer
            if (fpscr_zx != 0) {
898 7c58044c j_mayer
            raise_ze:
899 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
900 7c58044c j_mayer
                goto raise_excp;
901 7c58044c j_mayer
            }
902 7c58044c j_mayer
            break;
903 7c58044c j_mayer
        case FPSCR_XE:
904 7c58044c j_mayer
            if (fpscr_xx != 0) {
905 7c58044c j_mayer
            raise_xe:
906 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
907 7c58044c j_mayer
                goto raise_excp;
908 7c58044c j_mayer
            }
909 7c58044c j_mayer
            break;
910 7c58044c j_mayer
        case FPSCR_RN1:
911 7c58044c j_mayer
        case FPSCR_RN:
912 7c58044c j_mayer
            fpscr_set_rounding_mode();
913 7c58044c j_mayer
            break;
914 7c58044c j_mayer
        default:
915 7c58044c j_mayer
            break;
916 7c58044c j_mayer
        raise_excp:
917 7c58044c j_mayer
            /* Update the floating-point enabled exception summary */
918 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FEX;
919 7c58044c j_mayer
                /* We have to update Rc1 before raising the exception */
920 7c58044c j_mayer
            env->exception_index = POWERPC_EXCP_PROGRAM;
921 7c58044c j_mayer
            break;
922 7c58044c j_mayer
        }
923 7c58044c j_mayer
    }
924 7c58044c j_mayer
}
925 7c58044c j_mayer
926 af12906f aurel32
void helper_store_fpscr (uint64_t arg, uint32_t mask)
927 7c58044c j_mayer
{
928 7c58044c j_mayer
    /*
929 7c58044c j_mayer
     * We use only the 32 LSB of the incoming fpr
930 7c58044c j_mayer
     */
931 7c58044c j_mayer
    uint32_t prev, new;
932 7c58044c j_mayer
    int i;
933 7c58044c j_mayer
934 7c58044c j_mayer
    prev = env->fpscr;
935 af12906f aurel32
    new = (uint32_t)arg;
936 27ee5df0 aurel32
    new &= ~0x60000000;
937 27ee5df0 aurel32
    new |= prev & 0x60000000;
938 27ee5df0 aurel32
    for (i = 0; i < 8; i++) {
939 7c58044c j_mayer
        if (mask & (1 << i)) {
940 7c58044c j_mayer
            env->fpscr &= ~(0xF << (4 * i));
941 7c58044c j_mayer
            env->fpscr |= new & (0xF << (4 * i));
942 7c58044c j_mayer
        }
943 7c58044c j_mayer
    }
944 7c58044c j_mayer
    /* Update VX and FEX */
945 7c58044c j_mayer
    if (fpscr_ix != 0)
946 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VX;
947 5567025f aurel32
    else
948 5567025f aurel32
        env->fpscr &= ~(1 << FPSCR_VX);
949 7c58044c j_mayer
    if ((fpscr_ex & fpscr_eex) != 0) {
950 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
951 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
952 7c58044c j_mayer
        /* XXX: we should compute it properly */
953 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP;
954 7c58044c j_mayer
    }
955 5567025f aurel32
    else
956 5567025f aurel32
        env->fpscr &= ~(1 << FPSCR_FEX);
957 7c58044c j_mayer
    fpscr_set_rounding_mode();
958 7c58044c j_mayer
}
959 7c58044c j_mayer
960 af12906f aurel32
void helper_float_check_status (void)
961 7c58044c j_mayer
{
962 af12906f aurel32
#ifdef CONFIG_SOFTFLOAT
963 7c58044c j_mayer
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
964 7c58044c j_mayer
        (env->error_code & POWERPC_EXCP_FP)) {
965 7c58044c j_mayer
        /* Differred floating-point exception after target FPR update */
966 7c58044c j_mayer
        if (msr_fe0 != 0 || msr_fe1 != 0)
967 e06fcd75 aurel32
            helper_raise_exception_err(env->exception_index, env->error_code);
968 be94c952 aurel32
    } else {
969 be94c952 aurel32
        int status = get_float_exception_flags(&env->fp_status);
970 e33e94f9 aurel32
        if (status & float_flag_divbyzero) {
971 e33e94f9 aurel32
            float_zero_divide_excp();
972 e33e94f9 aurel32
        } else if (status & float_flag_overflow) {
973 be94c952 aurel32
            float_overflow_excp();
974 be94c952 aurel32
        } else if (status & float_flag_underflow) {
975 be94c952 aurel32
            float_underflow_excp();
976 be94c952 aurel32
        } else if (status & float_flag_inexact) {
977 be94c952 aurel32
            float_inexact_excp();
978 be94c952 aurel32
        }
979 7c58044c j_mayer
    }
980 af12906f aurel32
#else
981 af12906f aurel32
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
982 af12906f aurel32
        (env->error_code & POWERPC_EXCP_FP)) {
983 af12906f aurel32
        /* Differred floating-point exception after target FPR update */
984 af12906f aurel32
        if (msr_fe0 != 0 || msr_fe1 != 0)
985 e06fcd75 aurel32
            helper_raise_exception_err(env->exception_index, env->error_code);
986 af12906f aurel32
    }
987 af12906f aurel32
#endif
988 af12906f aurel32
}
989 af12906f aurel32
990 af12906f aurel32
#ifdef CONFIG_SOFTFLOAT
991 af12906f aurel32
void helper_reset_fpstatus (void)
992 af12906f aurel32
{
993 be94c952 aurel32
    set_float_exception_flags(0, &env->fp_status);
994 7c58044c j_mayer
}
995 7c58044c j_mayer
#endif
996 7c58044c j_mayer
997 af12906f aurel32
/* fadd - fadd. */
998 af12906f aurel32
uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
999 7c58044c j_mayer
{
1000 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1001 af12906f aurel32
1002 af12906f aurel32
    farg1.ll = arg1;
1003 af12906f aurel32
    farg2.ll = arg2;
1004 af12906f aurel32
#if USE_PRECISE_EMULATION
1005 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1006 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1007 7c58044c j_mayer
        /* sNaN addition */
1008 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1009 17218d1f aurel32
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1010 17218d1f aurel32
                      float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
1011 7c58044c j_mayer
        /* Magnitude subtraction of infinities */
1012 cf1cf21e aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1013 17218d1f aurel32
    } else {
1014 17218d1f aurel32
        farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
1015 7c58044c j_mayer
    }
1016 af12906f aurel32
#else
1017 af12906f aurel32
    farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
1018 af12906f aurel32
#endif
1019 af12906f aurel32
    return farg1.ll;
1020 7c58044c j_mayer
}
1021 7c58044c j_mayer
1022 af12906f aurel32
/* fsub - fsub. */
1023 af12906f aurel32
uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
1024 af12906f aurel32
{
1025 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1026 af12906f aurel32
1027 af12906f aurel32
    farg1.ll = arg1;
1028 af12906f aurel32
    farg2.ll = arg2;
1029 af12906f aurel32
#if USE_PRECISE_EMULATION
1030 7c58044c j_mayer
{
1031 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1032 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1033 7c58044c j_mayer
        /* sNaN subtraction */
1034 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1035 17218d1f aurel32
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1036 17218d1f aurel32
                      float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
1037 7c58044c j_mayer
        /* Magnitude subtraction of infinities */
1038 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1039 17218d1f aurel32
    } else {
1040 17218d1f aurel32
        farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1041 7c58044c j_mayer
    }
1042 7c58044c j_mayer
}
1043 af12906f aurel32
#else
1044 af12906f aurel32
    farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1045 af12906f aurel32
#endif
1046 af12906f aurel32
    return farg1.ll;
1047 af12906f aurel32
}
1048 7c58044c j_mayer
1049 af12906f aurel32
/* fmul - fmul. */
1050 af12906f aurel32
uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
1051 7c58044c j_mayer
{
1052 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1053 af12906f aurel32
1054 af12906f aurel32
    farg1.ll = arg1;
1055 af12906f aurel32
    farg2.ll = arg2;
1056 af12906f aurel32
#if USE_PRECISE_EMULATION
1057 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1058 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1059 7c58044c j_mayer
        /* sNaN multiplication */
1060 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1061 f23c346e aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1062 f23c346e aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1063 7c58044c j_mayer
        /* Multiplication of zero by infinity */
1064 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1065 7c58044c j_mayer
    } else {
1066 af12906f aurel32
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1067 7c58044c j_mayer
    }
1068 af12906f aurel32
#else
1069 af12906f aurel32
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1070 af12906f aurel32
#endif
1071 af12906f aurel32
    return farg1.ll;
1072 af12906f aurel32
}
1073 7c58044c j_mayer
1074 af12906f aurel32
/* fdiv - fdiv. */
1075 af12906f aurel32
uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
1076 7c58044c j_mayer
{
1077 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1078 af12906f aurel32
1079 af12906f aurel32
    farg1.ll = arg1;
1080 af12906f aurel32
    farg2.ll = arg2;
1081 af12906f aurel32
#if USE_PRECISE_EMULATION
1082 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1083 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1084 7c58044c j_mayer
        /* sNaN division */
1085 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1086 f23c346e aurel32
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
1087 7c58044c j_mayer
        /* Division of infinity by infinity */
1088 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
1089 e33e94f9 aurel32
    } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
1090 e33e94f9 aurel32
        /* Division of zero by zero */
1091 e33e94f9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
1092 7c58044c j_mayer
    } else {
1093 af12906f aurel32
        farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1094 7c58044c j_mayer
    }
1095 af12906f aurel32
#else
1096 af12906f aurel32
    farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1097 af12906f aurel32
#endif
1098 af12906f aurel32
    return farg1.ll;
1099 7c58044c j_mayer
}
1100 7c58044c j_mayer
1101 af12906f aurel32
/* fabs */
1102 af12906f aurel32
uint64_t helper_fabs (uint64_t arg)
1103 9a64fbe4 bellard
{
1104 af12906f aurel32
    CPU_DoubleU farg;
1105 9a64fbe4 bellard
1106 af12906f aurel32
    farg.ll = arg;
1107 af12906f aurel32
    farg.d = float64_abs(farg.d);
1108 af12906f aurel32
    return farg.ll;
1109 af12906f aurel32
}
1110 af12906f aurel32
1111 af12906f aurel32
/* fnabs */
1112 af12906f aurel32
uint64_t helper_fnabs (uint64_t arg)
1113 af12906f aurel32
{
1114 af12906f aurel32
    CPU_DoubleU farg;
1115 af12906f aurel32
1116 af12906f aurel32
    farg.ll = arg;
1117 af12906f aurel32
    farg.d = float64_abs(farg.d);
1118 af12906f aurel32
    farg.d = float64_chs(farg.d);
1119 af12906f aurel32
    return farg.ll;
1120 af12906f aurel32
}
1121 af12906f aurel32
1122 af12906f aurel32
/* fneg */
1123 af12906f aurel32
uint64_t helper_fneg (uint64_t arg)
1124 af12906f aurel32
{
1125 af12906f aurel32
    CPU_DoubleU farg;
1126 af12906f aurel32
1127 af12906f aurel32
    farg.ll = arg;
1128 af12906f aurel32
    farg.d = float64_chs(farg.d);
1129 af12906f aurel32
    return farg.ll;
1130 af12906f aurel32
}
1131 af12906f aurel32
1132 af12906f aurel32
/* fctiw - fctiw. */
1133 af12906f aurel32
uint64_t helper_fctiw (uint64_t arg)
1134 af12906f aurel32
{
1135 af12906f aurel32
    CPU_DoubleU farg;
1136 af12906f aurel32
    farg.ll = arg;
1137 af12906f aurel32
1138 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1139 7c58044c j_mayer
        /* sNaN conversion */
1140 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1141 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1142 7c58044c j_mayer
        /* qNan / infinity conversion */
1143 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1144 7c58044c j_mayer
    } else {
1145 af12906f aurel32
        farg.ll = float64_to_int32(farg.d, &env->fp_status);
1146 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1147 7c58044c j_mayer
        /* XXX: higher bits are not supposed to be significant.
1148 7c58044c j_mayer
         *     to make tests easier, return the same as a real PowerPC 750
1149 7c58044c j_mayer
         */
1150 af12906f aurel32
        farg.ll |= 0xFFF80000ULL << 32;
1151 e864cabd j_mayer
#endif
1152 7c58044c j_mayer
    }
1153 af12906f aurel32
    return farg.ll;
1154 9a64fbe4 bellard
}
1155 9a64fbe4 bellard
1156 af12906f aurel32
/* fctiwz - fctiwz. */
1157 af12906f aurel32
uint64_t helper_fctiwz (uint64_t arg)
1158 9a64fbe4 bellard
{
1159 af12906f aurel32
    CPU_DoubleU farg;
1160 af12906f aurel32
    farg.ll = arg;
1161 4ecc3190 bellard
1162 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1163 7c58044c j_mayer
        /* sNaN conversion */
1164 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1165 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1166 7c58044c j_mayer
        /* qNan / infinity conversion */
1167 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1168 7c58044c j_mayer
    } else {
1169 af12906f aurel32
        farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
1170 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1171 7c58044c j_mayer
        /* XXX: higher bits are not supposed to be significant.
1172 7c58044c j_mayer
         *     to make tests easier, return the same as a real PowerPC 750
1173 7c58044c j_mayer
         */
1174 af12906f aurel32
        farg.ll |= 0xFFF80000ULL << 32;
1175 e864cabd j_mayer
#endif
1176 7c58044c j_mayer
    }
1177 af12906f aurel32
    return farg.ll;
1178 9a64fbe4 bellard
}
1179 9a64fbe4 bellard
1180 426613db j_mayer
#if defined(TARGET_PPC64)
1181 af12906f aurel32
/* fcfid - fcfid. */
1182 af12906f aurel32
uint64_t helper_fcfid (uint64_t arg)
1183 426613db j_mayer
{
1184 af12906f aurel32
    CPU_DoubleU farg;
1185 af12906f aurel32
    farg.d = int64_to_float64(arg, &env->fp_status);
1186 af12906f aurel32
    return farg.ll;
1187 426613db j_mayer
}
1188 426613db j_mayer
1189 af12906f aurel32
/* fctid - fctid. */
1190 af12906f aurel32
uint64_t helper_fctid (uint64_t arg)
1191 426613db j_mayer
{
1192 af12906f aurel32
    CPU_DoubleU farg;
1193 af12906f aurel32
    farg.ll = arg;
1194 426613db j_mayer
1195 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1196 7c58044c j_mayer
        /* sNaN conversion */
1197 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1198 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1199 7c58044c j_mayer
        /* qNan / infinity conversion */
1200 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1201 7c58044c j_mayer
    } else {
1202 af12906f aurel32
        farg.ll = float64_to_int64(farg.d, &env->fp_status);
1203 7c58044c j_mayer
    }
1204 af12906f aurel32
    return farg.ll;
1205 426613db j_mayer
}
1206 426613db j_mayer
1207 af12906f aurel32
/* fctidz - fctidz. */
1208 af12906f aurel32
uint64_t helper_fctidz (uint64_t arg)
1209 426613db j_mayer
{
1210 af12906f aurel32
    CPU_DoubleU farg;
1211 af12906f aurel32
    farg.ll = arg;
1212 426613db j_mayer
1213 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1214 7c58044c j_mayer
        /* sNaN conversion */
1215 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1216 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1217 7c58044c j_mayer
        /* qNan / infinity conversion */
1218 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1219 7c58044c j_mayer
    } else {
1220 af12906f aurel32
        farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
1221 7c58044c j_mayer
    }
1222 af12906f aurel32
    return farg.ll;
1223 426613db j_mayer
}
1224 426613db j_mayer
1225 426613db j_mayer
#endif
1226 426613db j_mayer
1227 af12906f aurel32
static always_inline uint64_t do_fri (uint64_t arg, int rounding_mode)
1228 d7e4b87e j_mayer
{
1229 af12906f aurel32
    CPU_DoubleU farg;
1230 af12906f aurel32
    farg.ll = arg;
1231 af12906f aurel32
1232 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1233 7c58044c j_mayer
        /* sNaN round */
1234 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1235 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1236 7c58044c j_mayer
        /* qNan / infinity round */
1237 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1238 7c58044c j_mayer
    } else {
1239 7c58044c j_mayer
        set_float_rounding_mode(rounding_mode, &env->fp_status);
1240 af12906f aurel32
        farg.ll = float64_round_to_int(farg.d, &env->fp_status);
1241 7c58044c j_mayer
        /* Restore rounding mode from FPSCR */
1242 7c58044c j_mayer
        fpscr_set_rounding_mode();
1243 7c58044c j_mayer
    }
1244 af12906f aurel32
    return farg.ll;
1245 d7e4b87e j_mayer
}
1246 d7e4b87e j_mayer
1247 af12906f aurel32
uint64_t helper_frin (uint64_t arg)
1248 d7e4b87e j_mayer
{
1249 af12906f aurel32
    return do_fri(arg, float_round_nearest_even);
1250 d7e4b87e j_mayer
}
1251 d7e4b87e j_mayer
1252 af12906f aurel32
uint64_t helper_friz (uint64_t arg)
1253 d7e4b87e j_mayer
{
1254 af12906f aurel32
    return do_fri(arg, float_round_to_zero);
1255 d7e4b87e j_mayer
}
1256 d7e4b87e j_mayer
1257 af12906f aurel32
uint64_t helper_frip (uint64_t arg)
1258 d7e4b87e j_mayer
{
1259 af12906f aurel32
    return do_fri(arg, float_round_up);
1260 d7e4b87e j_mayer
}
1261 d7e4b87e j_mayer
1262 af12906f aurel32
uint64_t helper_frim (uint64_t arg)
1263 d7e4b87e j_mayer
{
1264 af12906f aurel32
    return do_fri(arg, float_round_down);
1265 d7e4b87e j_mayer
}
1266 d7e4b87e j_mayer
1267 af12906f aurel32
/* fmadd - fmadd. */
1268 af12906f aurel32
uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1269 e864cabd j_mayer
{
1270 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1271 af12906f aurel32
1272 af12906f aurel32
    farg1.ll = arg1;
1273 af12906f aurel32
    farg2.ll = arg2;
1274 af12906f aurel32
    farg3.ll = arg3;
1275 af12906f aurel32
#if USE_PRECISE_EMULATION
1276 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1277 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1278 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1279 7c58044c j_mayer
        /* sNaN operation */
1280 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1281 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1282 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1283 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1284 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1285 7c58044c j_mayer
    } else {
1286 e864cabd j_mayer
#ifdef FLOAT128
1287 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1288 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1289 7c58044c j_mayer
1290 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1291 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1292 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1293 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1294 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1295 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1296 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1297 da1e7ac9 aurel32
        } else {
1298 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1299 da1e7ac9 aurel32
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1300 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1301 da1e7ac9 aurel32
        }
1302 e864cabd j_mayer
#else
1303 7c58044c j_mayer
        /* This is OK on x86 hosts */
1304 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) + farg3.d;
1305 e864cabd j_mayer
#endif
1306 7c58044c j_mayer
    }
1307 af12906f aurel32
#else
1308 af12906f aurel32
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1309 af12906f aurel32
    farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1310 af12906f aurel32
#endif
1311 af12906f aurel32
    return farg1.ll;
1312 e864cabd j_mayer
}
1313 e864cabd j_mayer
1314 af12906f aurel32
/* fmsub - fmsub. */
1315 af12906f aurel32
uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1316 e864cabd j_mayer
{
1317 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1318 af12906f aurel32
1319 af12906f aurel32
    farg1.ll = arg1;
1320 af12906f aurel32
    farg2.ll = arg2;
1321 af12906f aurel32
    farg3.ll = arg3;
1322 af12906f aurel32
#if USE_PRECISE_EMULATION
1323 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1324 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1325 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1326 7c58044c j_mayer
        /* sNaN operation */
1327 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1328 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1329 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1330 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1331 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1332 7c58044c j_mayer
    } else {
1333 e864cabd j_mayer
#ifdef FLOAT128
1334 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1335 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1336 7c58044c j_mayer
1337 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1338 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1339 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1340 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1341 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1342 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1343 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1344 da1e7ac9 aurel32
        } else {
1345 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1346 da1e7ac9 aurel32
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1347 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1348 da1e7ac9 aurel32
        }
1349 e864cabd j_mayer
#else
1350 7c58044c j_mayer
        /* This is OK on x86 hosts */
1351 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) - farg3.d;
1352 e864cabd j_mayer
#endif
1353 7c58044c j_mayer
    }
1354 af12906f aurel32
#else
1355 af12906f aurel32
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1356 af12906f aurel32
    farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1357 af12906f aurel32
#endif
1358 af12906f aurel32
    return farg1.ll;
1359 e864cabd j_mayer
}
1360 e864cabd j_mayer
1361 af12906f aurel32
/* fnmadd - fnmadd. */
1362 af12906f aurel32
uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1363 4b3686fa bellard
{
1364 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1365 af12906f aurel32
1366 af12906f aurel32
    farg1.ll = arg1;
1367 af12906f aurel32
    farg2.ll = arg2;
1368 af12906f aurel32
    farg3.ll = arg3;
1369 af12906f aurel32
1370 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1371 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1372 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1373 7c58044c j_mayer
        /* sNaN operation */
1374 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1375 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1376 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1377 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1378 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1379 7c58044c j_mayer
    } else {
1380 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1381 e864cabd j_mayer
#ifdef FLOAT128
1382 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1383 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1384 7c58044c j_mayer
1385 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1386 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1387 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1388 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1389 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1390 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1391 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1392 da1e7ac9 aurel32
        } else {
1393 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1394 da1e7ac9 aurel32
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1395 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1396 da1e7ac9 aurel32
        }
1397 e864cabd j_mayer
#else
1398 7c58044c j_mayer
        /* This is OK on x86 hosts */
1399 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) + farg3.d;
1400 e864cabd j_mayer
#endif
1401 e864cabd j_mayer
#else
1402 af12906f aurel32
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1403 af12906f aurel32
        farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1404 e864cabd j_mayer
#endif
1405 a44d2ce1 aurel32
        if (likely(!float64_is_nan(farg1.d)))
1406 af12906f aurel32
            farg1.d = float64_chs(farg1.d);
1407 7c58044c j_mayer
    }
1408 af12906f aurel32
    return farg1.ll;
1409 4b3686fa bellard
}
1410 4b3686fa bellard
1411 af12906f aurel32
/* fnmsub - fnmsub. */
1412 af12906f aurel32
uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1413 4b3686fa bellard
{
1414 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1415 af12906f aurel32
1416 af12906f aurel32
    farg1.ll = arg1;
1417 af12906f aurel32
    farg2.ll = arg2;
1418 af12906f aurel32
    farg3.ll = arg3;
1419 af12906f aurel32
1420 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1421 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1422 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1423 7c58044c j_mayer
        /* sNaN operation */
1424 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1425 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1426 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1427 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1428 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1429 7c58044c j_mayer
    } else {
1430 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1431 e864cabd j_mayer
#ifdef FLOAT128
1432 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1433 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1434 7c58044c j_mayer
1435 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1436 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1437 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1438 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1439 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1440 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1441 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1442 da1e7ac9 aurel32
        } else {
1443 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1444 da1e7ac9 aurel32
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1445 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1446 da1e7ac9 aurel32
        }
1447 e864cabd j_mayer
#else
1448 7c58044c j_mayer
        /* This is OK on x86 hosts */
1449 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) - farg3.d;
1450 e864cabd j_mayer
#endif
1451 e864cabd j_mayer
#else
1452 af12906f aurel32
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1453 af12906f aurel32
        farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1454 e864cabd j_mayer
#endif
1455 a44d2ce1 aurel32
        if (likely(!float64_is_nan(farg1.d)))
1456 af12906f aurel32
            farg1.d = float64_chs(farg1.d);
1457 7c58044c j_mayer
    }
1458 af12906f aurel32
    return farg1.ll;
1459 1ef59d0a bellard
}
1460 1ef59d0a bellard
1461 af12906f aurel32
/* frsp - frsp. */
1462 af12906f aurel32
uint64_t helper_frsp (uint64_t arg)
1463 7c58044c j_mayer
{
1464 af12906f aurel32
    CPU_DoubleU farg;
1465 6ad193ed aurel32
    float32 f32;
1466 af12906f aurel32
    farg.ll = arg;
1467 af12906f aurel32
1468 af12906f aurel32
#if USE_PRECISE_EMULATION
1469 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1470 7c58044c j_mayer
        /* sNaN square root */
1471 af12906f aurel32
       farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1472 7c58044c j_mayer
    } else {
1473 6ad193ed aurel32
       f32 = float64_to_float32(farg.d, &env->fp_status);
1474 6ad193ed aurel32
       farg.d = float32_to_float64(f32, &env->fp_status);
1475 7c58044c j_mayer
    }
1476 af12906f aurel32
#else
1477 6ad193ed aurel32
    f32 = float64_to_float32(farg.d, &env->fp_status);
1478 6ad193ed aurel32
    farg.d = float32_to_float64(f32, &env->fp_status);
1479 af12906f aurel32
#endif
1480 af12906f aurel32
    return farg.ll;
1481 7c58044c j_mayer
}
1482 7c58044c j_mayer
1483 af12906f aurel32
/* fsqrt - fsqrt. */
1484 af12906f aurel32
uint64_t helper_fsqrt (uint64_t arg)
1485 9a64fbe4 bellard
{
1486 af12906f aurel32
    CPU_DoubleU farg;
1487 af12906f aurel32
    farg.ll = arg;
1488 af12906f aurel32
1489 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1490 7c58044c j_mayer
        /* sNaN square root */
1491 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1492 f23c346e aurel32
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1493 7c58044c j_mayer
        /* Square root of a negative nonzero number */
1494 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1495 7c58044c j_mayer
    } else {
1496 af12906f aurel32
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1497 7c58044c j_mayer
    }
1498 af12906f aurel32
    return farg.ll;
1499 9a64fbe4 bellard
}
1500 9a64fbe4 bellard
1501 af12906f aurel32
/* fre - fre. */
1502 af12906f aurel32
uint64_t helper_fre (uint64_t arg)
1503 d7e4b87e j_mayer
{
1504 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 d72a19f7 aurel32
           ~((target_ulong)0xFFFF0000), 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 d72a19f7 aurel32
           ~((target_ulong)0xFFFF0000), 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 d72a19f7 aurel32
           ~((target_ulong)0xFFFF0000), 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 35cf7c7e aurel32
void helper_vmaddfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2292 35cf7c7e aurel32
{
2293 35cf7c7e aurel32
    int i;
2294 35cf7c7e aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2295 35cf7c7e aurel32
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2296 35cf7c7e aurel32
            /* Need to do the computation in higher precision and round
2297 35cf7c7e aurel32
             * once at the end.  */
2298 35cf7c7e aurel32
            float64 af, bf, cf, t;
2299 35cf7c7e aurel32
            af = float32_to_float64(a->f[i], &env->vec_status);
2300 35cf7c7e aurel32
            bf = float32_to_float64(b->f[i], &env->vec_status);
2301 35cf7c7e aurel32
            cf = float32_to_float64(c->f[i], &env->vec_status);
2302 35cf7c7e aurel32
            t = float64_mul(af, cf, &env->vec_status);
2303 35cf7c7e aurel32
            t = float64_add(t, bf, &env->vec_status);
2304 35cf7c7e aurel32
            r->f[i] = float64_to_float32(t, &env->vec_status);
2305 35cf7c7e aurel32
        }
2306 35cf7c7e aurel32
    }
2307 35cf7c7e aurel32
}
2308 35cf7c7e aurel32
2309 b161ae27 aurel32
void helper_vmhaddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2310 b161ae27 aurel32
{
2311 b161ae27 aurel32
    int sat = 0;
2312 b161ae27 aurel32
    int i;
2313 b161ae27 aurel32
2314 b161ae27 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2315 b161ae27 aurel32
        int32_t prod = a->s16[i] * b->s16[i];
2316 b161ae27 aurel32
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2317 b161ae27 aurel32
        r->s16[i] = cvtswsh (t, &sat);
2318 b161ae27 aurel32
    }
2319 b161ae27 aurel32
2320 b161ae27 aurel32
    if (sat) {
2321 b161ae27 aurel32
        env->vscr |= (1 << VSCR_SAT);
2322 b161ae27 aurel32
    }
2323 b161ae27 aurel32
}
2324 b161ae27 aurel32
2325 b161ae27 aurel32
void helper_vmhraddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2326 b161ae27 aurel32
{
2327 b161ae27 aurel32
    int sat = 0;
2328 b161ae27 aurel32
    int i;
2329 b161ae27 aurel32
2330 b161ae27 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2331 b161ae27 aurel32
        int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
2332 b161ae27 aurel32
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2333 b161ae27 aurel32
        r->s16[i] = cvtswsh (t, &sat);
2334 b161ae27 aurel32
    }
2335 b161ae27 aurel32
2336 b161ae27 aurel32
    if (sat) {
2337 b161ae27 aurel32
        env->vscr |= (1 << VSCR_SAT);
2338 b161ae27 aurel32
    }
2339 b161ae27 aurel32
}
2340 b161ae27 aurel32
2341 e4039339 aurel32
#define VMINMAX_DO(name, compare, element)                              \
2342 e4039339 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2343 e4039339 aurel32
    {                                                                   \
2344 e4039339 aurel32
        int i;                                                          \
2345 e4039339 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2346 e4039339 aurel32
            if (a->element[i] compare b->element[i]) {                  \
2347 e4039339 aurel32
                r->element[i] = b->element[i];                          \
2348 e4039339 aurel32
            } else {                                                    \
2349 e4039339 aurel32
                r->element[i] = a->element[i];                          \
2350 e4039339 aurel32
            }                                                           \
2351 e4039339 aurel32
        }                                                               \
2352 e4039339 aurel32
    }
2353 e4039339 aurel32
#define VMINMAX(suffix, element)                \
2354 e4039339 aurel32
  VMINMAX_DO(min##suffix, >, element)           \
2355 e4039339 aurel32
  VMINMAX_DO(max##suffix, <, element)
2356 e4039339 aurel32
VMINMAX(sb, s8)
2357 e4039339 aurel32
VMINMAX(sh, s16)
2358 e4039339 aurel32
VMINMAX(sw, s32)
2359 e4039339 aurel32
VMINMAX(ub, u8)
2360 e4039339 aurel32
VMINMAX(uh, u16)
2361 e4039339 aurel32
VMINMAX(uw, u32)
2362 e4039339 aurel32
#undef VMINMAX_DO
2363 e4039339 aurel32
#undef VMINMAX
2364 e4039339 aurel32
2365 1536ff64 aurel32
#define VMINMAXFP(suffix, rT, rF)                                       \
2366 1536ff64 aurel32
    void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
2367 1536ff64 aurel32
    {                                                                   \
2368 1536ff64 aurel32
        int i;                                                          \
2369 1536ff64 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2370 1536ff64 aurel32
            HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
2371 1536ff64 aurel32
                if (float32_lt_quiet(a->f[i], b->f[i], &env->vec_status)) { \
2372 1536ff64 aurel32
                    r->f[i] = rT->f[i];                                 \
2373 1536ff64 aurel32
                } else {                                                \
2374 1536ff64 aurel32
                    r->f[i] = rF->f[i];                                 \
2375 1536ff64 aurel32
                }                                                       \
2376 1536ff64 aurel32
            }                                                           \
2377 1536ff64 aurel32
        }                                                               \
2378 1536ff64 aurel32
    }
2379 1536ff64 aurel32
VMINMAXFP(minfp, a, b)
2380 1536ff64 aurel32
VMINMAXFP(maxfp, b, a)
2381 1536ff64 aurel32
#undef VMINMAXFP
2382 1536ff64 aurel32
2383 bcd2ee23 aurel32
void helper_vmladduhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2384 bcd2ee23 aurel32
{
2385 bcd2ee23 aurel32
    int i;
2386 bcd2ee23 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2387 bcd2ee23 aurel32
        int32_t prod = a->s16[i] * b->s16[i];
2388 bcd2ee23 aurel32
        r->s16[i] = (int16_t) (prod + c->s16[i]);
2389 bcd2ee23 aurel32
    }
2390 bcd2ee23 aurel32
}
2391 bcd2ee23 aurel32
2392 3b430048 aurel32
#define VMRG_DO(name, element, highp)                                   \
2393 3b430048 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2394 3b430048 aurel32
    {                                                                   \
2395 3b430048 aurel32
        ppc_avr_t result;                                               \
2396 3b430048 aurel32
        int i;                                                          \
2397 3b430048 aurel32
        size_t n_elems = ARRAY_SIZE(r->element);                        \
2398 3b430048 aurel32
        for (i = 0; i < n_elems/2; i++) {                               \
2399 3b430048 aurel32
            if (highp) {                                                \
2400 3b430048 aurel32
                result.element[i*2+HI_IDX] = a->element[i];             \
2401 3b430048 aurel32
                result.element[i*2+LO_IDX] = b->element[i];             \
2402 3b430048 aurel32
            } else {                                                    \
2403 3b430048 aurel32
                result.element[n_elems - i*2 - (1+HI_IDX)] = b->element[n_elems - i - 1]; \
2404 3b430048 aurel32
                result.element[n_elems - i*2 - (1+LO_IDX)] = a->element[n_elems - i - 1]; \
2405 3b430048 aurel32
            }                                                           \
2406 3b430048 aurel32
        }                                                               \
2407 3b430048 aurel32
        *r = result;                                                    \
2408 3b430048 aurel32
    }
2409 3b430048 aurel32
#if defined(WORDS_BIGENDIAN)
2410 3b430048 aurel32
#define MRGHI 0
2411 b392e756 aurel32
#define MRGLO 1
2412 3b430048 aurel32
#else
2413 3b430048 aurel32
#define MRGHI 1
2414 3b430048 aurel32
#define MRGLO 0
2415 3b430048 aurel32
#endif
2416 3b430048 aurel32
#define VMRG(suffix, element)                   \
2417 3b430048 aurel32
  VMRG_DO(mrgl##suffix, element, MRGHI)         \
2418 3b430048 aurel32
  VMRG_DO(mrgh##suffix, element, MRGLO)
2419 3b430048 aurel32
VMRG(b, u8)
2420 3b430048 aurel32
VMRG(h, u16)
2421 3b430048 aurel32
VMRG(w, u32)
2422 3b430048 aurel32
#undef VMRG_DO
2423 3b430048 aurel32
#undef VMRG
2424 3b430048 aurel32
#undef MRGHI
2425 3b430048 aurel32
#undef MRGLO
2426 3b430048 aurel32
2427 b04ae981 aurel32
void helper_vmsummbm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2428 b04ae981 aurel32
{
2429 b04ae981 aurel32
    int32_t prod[16];
2430 b04ae981 aurel32
    int i;
2431 b04ae981 aurel32
2432 b04ae981 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
2433 b04ae981 aurel32
        prod[i] = (int32_t)a->s8[i] * b->u8[i];
2434 b04ae981 aurel32
    }
2435 b04ae981 aurel32
2436 b04ae981 aurel32
    VECTOR_FOR_INORDER_I(i, s32) {
2437 b04ae981 aurel32
        r->s32[i] = c->s32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2438 b04ae981 aurel32
    }
2439 b04ae981 aurel32
}
2440 b04ae981 aurel32
2441 eae07261 aurel32
void helper_vmsumshm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2442 eae07261 aurel32
{
2443 eae07261 aurel32
    int32_t prod[8];
2444 eae07261 aurel32
    int i;
2445 eae07261 aurel32
2446 eae07261 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2447 eae07261 aurel32
        prod[i] = a->s16[i] * b->s16[i];
2448 eae07261 aurel32
    }
2449 eae07261 aurel32
2450 eae07261 aurel32
    VECTOR_FOR_INORDER_I(i, s32) {
2451 eae07261 aurel32
        r->s32[i] = c->s32[i] + prod[2*i] + prod[2*i+1];
2452 eae07261 aurel32
    }
2453 eae07261 aurel32
}
2454 eae07261 aurel32
2455 eae07261 aurel32
void helper_vmsumshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2456 eae07261 aurel32
{
2457 eae07261 aurel32
    int32_t prod[8];
2458 eae07261 aurel32
    int i;
2459 eae07261 aurel32
    int sat = 0;
2460 eae07261 aurel32
2461 eae07261 aurel32
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2462 eae07261 aurel32
        prod[i] = (int32_t)a->s16[i] * b->s16[i];
2463 eae07261 aurel32
    }
2464 eae07261 aurel32
2465 eae07261 aurel32
    VECTOR_FOR_INORDER_I (i, s32) {
2466 eae07261 aurel32
        int64_t t = (int64_t)c->s32[i] + prod[2*i] + prod[2*i+1];
2467 eae07261 aurel32
        r->u32[i] = cvtsdsw(t, &sat);
2468 eae07261 aurel32
    }
2469 eae07261 aurel32
2470 eae07261 aurel32
    if (sat) {
2471 eae07261 aurel32
        env->vscr |= (1 << VSCR_SAT);
2472 eae07261 aurel32
    }
2473 eae07261 aurel32
}
2474 eae07261 aurel32
2475 b04ae981 aurel32
void helper_vmsumubm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2476 b04ae981 aurel32
{
2477 b04ae981 aurel32
    uint16_t prod[16];
2478 b04ae981 aurel32
    int i;
2479 b04ae981 aurel32
2480 b04ae981 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2481 b04ae981 aurel32
        prod[i] = a->u8[i] * b->u8[i];
2482 b04ae981 aurel32
    }
2483 b04ae981 aurel32
2484 b04ae981 aurel32
    VECTOR_FOR_INORDER_I(i, u32) {
2485 b04ae981 aurel32
        r->u32[i] = c->u32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2486 b04ae981 aurel32
    }
2487 b04ae981 aurel32
}
2488 b04ae981 aurel32
2489 4d9903b6 aurel32
void helper_vmsumuhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2490 4d9903b6 aurel32
{
2491 4d9903b6 aurel32
    uint32_t prod[8];
2492 4d9903b6 aurel32
    int i;
2493 4d9903b6 aurel32
2494 4d9903b6 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2495 4d9903b6 aurel32
        prod[i] = a->u16[i] * b->u16[i];
2496 4d9903b6 aurel32
    }
2497 4d9903b6 aurel32
2498 4d9903b6 aurel32
    VECTOR_FOR_INORDER_I(i, u32) {
2499 4d9903b6 aurel32
        r->u32[i] = c->u32[i] + prod[2*i] + prod[2*i+1];
2500 4d9903b6 aurel32
    }
2501 4d9903b6 aurel32
}
2502 4d9903b6 aurel32
2503 4d9903b6 aurel32
void helper_vmsumuhs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2504 4d9903b6 aurel32
{
2505 4d9903b6 aurel32
    uint32_t prod[8];
2506 4d9903b6 aurel32
    int i;
2507 4d9903b6 aurel32
    int sat = 0;
2508 4d9903b6 aurel32
2509 4d9903b6 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2510 4d9903b6 aurel32
        prod[i] = a->u16[i] * b->u16[i];
2511 4d9903b6 aurel32
    }
2512 4d9903b6 aurel32
2513 4d9903b6 aurel32
    VECTOR_FOR_INORDER_I (i, s32) {
2514 4d9903b6 aurel32
        uint64_t t = (uint64_t)c->u32[i] + prod[2*i] + prod[2*i+1];
2515 4d9903b6 aurel32
        r->u32[i] = cvtuduw(t, &sat);
2516 4d9903b6 aurel32
    }
2517 4d9903b6 aurel32
2518 4d9903b6 aurel32
    if (sat) {
2519 4d9903b6 aurel32
        env->vscr |= (1 << VSCR_SAT);
2520 4d9903b6 aurel32
    }
2521 4d9903b6 aurel32
}
2522 4d9903b6 aurel32
2523 2c277908 aurel32
#define VMUL_DO(name, mul_element, prod_element, evenp)                 \
2524 2c277908 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2525 2c277908 aurel32
    {                                                                   \
2526 2c277908 aurel32
        int i;                                                          \
2527 2c277908 aurel32
        VECTOR_FOR_INORDER_I(i, prod_element) {                         \
2528 2c277908 aurel32
            if (evenp) {                                                \
2529 2c277908 aurel32
                r->prod_element[i] = a->mul_element[i*2+HI_IDX] * b->mul_element[i*2+HI_IDX]; \
2530 2c277908 aurel32
            } else {                                                    \
2531 2c277908 aurel32
                r->prod_element[i] = a->mul_element[i*2+LO_IDX] * b->mul_element[i*2+LO_IDX]; \
2532 2c277908 aurel32
            }                                                           \
2533 2c277908 aurel32
        }                                                               \
2534 2c277908 aurel32
    }
2535 2c277908 aurel32
#define VMUL(suffix, mul_element, prod_element) \
2536 2c277908 aurel32
  VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
2537 2c277908 aurel32
  VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
2538 2c277908 aurel32
VMUL(sb, s8, s16)
2539 2c277908 aurel32
VMUL(sh, s16, s32)
2540 2c277908 aurel32
VMUL(ub, u8, u16)
2541 2c277908 aurel32
VMUL(uh, u16, u32)
2542 2c277908 aurel32
#undef VMUL_DO
2543 2c277908 aurel32
#undef VMUL
2544 2c277908 aurel32
2545 35cf7c7e aurel32
void helper_vnmsubfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2546 35cf7c7e aurel32
{
2547 35cf7c7e aurel32
    int i;
2548 35cf7c7e aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2549 35cf7c7e aurel32
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2550 35cf7c7e aurel32
            /* Need to do the computation is higher precision and round
2551 35cf7c7e aurel32
             * once at the end.  */
2552 35cf7c7e aurel32
            float64 af, bf, cf, t;
2553 35cf7c7e aurel32
            af = float32_to_float64(a->f[i], &env->vec_status);
2554 35cf7c7e aurel32
            bf = float32_to_float64(b->f[i], &env->vec_status);
2555 35cf7c7e aurel32
            cf = float32_to_float64(c->f[i], &env->vec_status);
2556 35cf7c7e aurel32
            t = float64_mul(af, cf, &env->vec_status);
2557 35cf7c7e aurel32
            t = float64_sub(t, bf, &env->vec_status);
2558 35cf7c7e aurel32
            t = float64_chs(t);
2559 35cf7c7e aurel32
            r->f[i] = float64_to_float32(t, &env->vec_status);
2560 35cf7c7e aurel32
        }
2561 35cf7c7e aurel32
    }
2562 35cf7c7e aurel32
}
2563 35cf7c7e aurel32
2564 d1258698 aurel32
void helper_vperm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2565 d1258698 aurel32
{
2566 d1258698 aurel32
    ppc_avr_t result;
2567 d1258698 aurel32
    int i;
2568 d1258698 aurel32
    VECTOR_FOR_INORDER_I (i, u8) {
2569 d1258698 aurel32
        int s = c->u8[i] & 0x1f;
2570 d1258698 aurel32
#if defined(WORDS_BIGENDIAN)
2571 d1258698 aurel32
        int index = s & 0xf;
2572 d1258698 aurel32
#else
2573 d1258698 aurel32
        int index = 15 - (s & 0xf);
2574 d1258698 aurel32
#endif
2575 d1258698 aurel32
        if (s & 0x10) {
2576 d1258698 aurel32
            result.u8[i] = b->u8[index];
2577 d1258698 aurel32
        } else {
2578 d1258698 aurel32
            result.u8[i] = a->u8[index];
2579 d1258698 aurel32
        }
2580 d1258698 aurel32
    }
2581 d1258698 aurel32
    *r = result;
2582 d1258698 aurel32
}
2583 d1258698 aurel32
2584 5335a145 aurel32
#if defined(WORDS_BIGENDIAN)
2585 5335a145 aurel32
#define PKBIG 1
2586 5335a145 aurel32
#else
2587 5335a145 aurel32
#define PKBIG 0
2588 5335a145 aurel32
#endif
2589 1dd9ffb9 aurel32
void helper_vpkpx (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2590 1dd9ffb9 aurel32
{
2591 1dd9ffb9 aurel32
    int i, j;
2592 1dd9ffb9 aurel32
    ppc_avr_t result;
2593 1dd9ffb9 aurel32
#if defined(WORDS_BIGENDIAN)
2594 1dd9ffb9 aurel32
    const ppc_avr_t *x[2] = { a, b };
2595 1dd9ffb9 aurel32
#else
2596 1dd9ffb9 aurel32
    const ppc_avr_t *x[2] = { b, a };
2597 1dd9ffb9 aurel32
#endif
2598 1dd9ffb9 aurel32
2599 1dd9ffb9 aurel32
    VECTOR_FOR_INORDER_I (i, u64) {
2600 1dd9ffb9 aurel32
        VECTOR_FOR_INORDER_I (j, u32){
2601 1dd9ffb9 aurel32
            uint32_t e = x[i]->u32[j];
2602 1dd9ffb9 aurel32
            result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
2603 1dd9ffb9 aurel32
                                 ((e >> 6) & 0x3e0) |
2604 1dd9ffb9 aurel32
                                 ((e >> 3) & 0x1f));
2605 1dd9ffb9 aurel32
        }
2606 1dd9ffb9 aurel32
    }
2607 1dd9ffb9 aurel32
    *r = result;
2608 1dd9ffb9 aurel32
}
2609 1dd9ffb9 aurel32
2610 5335a145 aurel32
#define VPK(suffix, from, to, cvt, dosat)       \
2611 5335a145 aurel32
    void helper_vpk##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2612 5335a145 aurel32
    {                                                                   \
2613 5335a145 aurel32
        int i;                                                          \
2614 5335a145 aurel32
        int sat = 0;                                                    \
2615 5335a145 aurel32
        ppc_avr_t result;                                               \
2616 5335a145 aurel32
        ppc_avr_t *a0 = PKBIG ? a : b;                                  \
2617 5335a145 aurel32
        ppc_avr_t *a1 = PKBIG ? b : a;                                  \
2618 5335a145 aurel32
        VECTOR_FOR_INORDER_I (i, from) {                                \
2619 5335a145 aurel32
            result.to[i] = cvt(a0->from[i], &sat);                      \
2620 5335a145 aurel32
            result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);  \
2621 5335a145 aurel32
        }                                                               \
2622 5335a145 aurel32
        *r = result;                                                    \
2623 5335a145 aurel32
        if (dosat && sat) {                                             \
2624 5335a145 aurel32
            env->vscr |= (1 << VSCR_SAT);                               \
2625 5335a145 aurel32
        }                                                               \
2626 5335a145 aurel32
    }
2627 5335a145 aurel32
#define I(x, y) (x)
2628 5335a145 aurel32
VPK(shss, s16, s8, cvtshsb, 1)
2629 5335a145 aurel32
VPK(shus, s16, u8, cvtshub, 1)
2630 5335a145 aurel32
VPK(swss, s32, s16, cvtswsh, 1)
2631 5335a145 aurel32
VPK(swus, s32, u16, cvtswuh, 1)
2632 5335a145 aurel32
VPK(uhus, u16, u8, cvtuhub, 1)
2633 5335a145 aurel32
VPK(uwus, u32, u16, cvtuwuh, 1)
2634 5335a145 aurel32
VPK(uhum, u16, u8, I, 0)
2635 5335a145 aurel32
VPK(uwum, u32, u16, I, 0)
2636 5335a145 aurel32
#undef I
2637 5335a145 aurel32
#undef VPK
2638 5335a145 aurel32
#undef PKBIG
2639 5335a145 aurel32
2640 f6b19645 aurel32
#define VRFI(suffix, rounding)                                          \
2641 f6b19645 aurel32
    void helper_vrfi##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
2642 f6b19645 aurel32
    {                                                                   \
2643 f6b19645 aurel32
        int i;                                                          \
2644 f6b19645 aurel32
        float_status s = env->vec_status;                               \
2645 f6b19645 aurel32
        set_float_rounding_mode(rounding, &s);                          \
2646 f6b19645 aurel32
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2647 f6b19645 aurel32
            HANDLE_NAN1(r->f[i], b->f[i]) {                             \
2648 f6b19645 aurel32
                r->f[i] = float32_round_to_int (b->f[i], &s);           \
2649 f6b19645 aurel32
            }                                                           \
2650 f6b19645 aurel32
        }                                                               \
2651 f6b19645 aurel32
    }
2652 f6b19645 aurel32
VRFI(n, float_round_nearest_even)
2653 f6b19645 aurel32
VRFI(m, float_round_down)
2654 f6b19645 aurel32
VRFI(p, float_round_up)
2655 f6b19645 aurel32
VRFI(z, float_round_to_zero)
2656 f6b19645 aurel32
#undef VRFI
2657 f6b19645 aurel32
2658 5e1d0985 aurel32
#define VROTATE(suffix, element)                                        \
2659 5e1d0985 aurel32
    void helper_vrl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2660 5e1d0985 aurel32
    {                                                                   \
2661 5e1d0985 aurel32
        int i;                                                          \
2662 5e1d0985 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2663 5e1d0985 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2664 5e1d0985 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2665 5e1d0985 aurel32
            r->element[i] = (a->element[i] << shift) | (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
2666 5e1d0985 aurel32
        }                                                               \
2667 5e1d0985 aurel32
    }
2668 5e1d0985 aurel32
VROTATE(b, u8)
2669 5e1d0985 aurel32
VROTATE(h, u16)
2670 5e1d0985 aurel32
VROTATE(w, u32)
2671 5e1d0985 aurel32
#undef VROTATE
2672 5e1d0985 aurel32
2673 d1258698 aurel32
void helper_vsel (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2674 d1258698 aurel32
{
2675 d1258698 aurel32
    r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
2676 d1258698 aurel32
    r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
2677 d1258698 aurel32
}
2678 d1258698 aurel32
2679 b580763f aurel32
void helper_vlogefp (ppc_avr_t *r, ppc_avr_t *b)
2680 f586ce09 aurel32
{
2681 f586ce09 aurel32
    int i;
2682 f586ce09 aurel32
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2683 f586ce09 aurel32
        HANDLE_NAN1(r->f[i], b->f[i]) {
2684 f586ce09 aurel32
            r->f[i] = float32_log2(b->f[i], &env->vec_status);
2685 f586ce09 aurel32
        }
2686 f586ce09 aurel32
    }
2687 f586ce09 aurel32
}
2688 f586ce09 aurel32
2689 d9430add aurel32
#if defined(WORDS_BIGENDIAN)
2690 d9430add aurel32
#define LEFT 0
2691 d9430add aurel32
#define RIGHT 1
2692 d9430add aurel32
#else
2693 d9430add aurel32
#define LEFT 1
2694 d9430add aurel32
#define RIGHT 0
2695 d9430add aurel32
#endif
2696 d9430add aurel32
/* The specification says that the results are undefined if all of the
2697 d9430add aurel32
 * shift counts are not identical.  We check to make sure that they are
2698 d9430add aurel32
 * to conform to what real hardware appears to do.  */
2699 d9430add aurel32
#define VSHIFT(suffix, leftp)                                           \
2700 d9430add aurel32
    void helper_vs##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
2701 d9430add aurel32
    {                                                                   \
2702 d9430add aurel32
        int shift = b->u8[LO_IDX*0x15] & 0x7;                           \
2703 d9430add aurel32
        int doit = 1;                                                   \
2704 d9430add aurel32
        int i;                                                          \
2705 d9430add aurel32
        for (i = 0; i < ARRAY_SIZE(r->u8); i++) {                       \
2706 d9430add aurel32
            doit = doit && ((b->u8[i] & 0x7) == shift);                 \
2707 d9430add aurel32
        }                                                               \
2708 d9430add aurel32
        if (doit) {                                                     \
2709 d9430add aurel32
            if (shift == 0) {                                           \
2710 d9430add aurel32
                *r = *a;                                                \
2711 d9430add aurel32
            } else if (leftp) {                                         \
2712 d9430add aurel32
                uint64_t carry = a->u64[LO_IDX] >> (64 - shift);        \
2713 d9430add aurel32
                r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry;     \
2714 d9430add aurel32
                r->u64[LO_IDX] = a->u64[LO_IDX] << shift;               \
2715 d9430add aurel32
            } else {                                                    \
2716 d9430add aurel32
                uint64_t carry = a->u64[HI_IDX] << (64 - shift);        \
2717 d9430add aurel32
                r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry;     \
2718 d9430add aurel32
                r->u64[HI_IDX] = a->u64[HI_IDX] >> shift;               \
2719 d9430add aurel32
            }                                                           \
2720 d9430add aurel32
        }                                                               \
2721 d9430add aurel32
    }
2722 d9430add aurel32
VSHIFT(l, LEFT)
2723 d9430add aurel32
VSHIFT(r, RIGHT)
2724 d9430add aurel32
#undef VSHIFT
2725 d9430add aurel32
#undef LEFT
2726 d9430add aurel32
#undef RIGHT
2727 d9430add aurel32
2728 d79f0809 aurel32
#define VSL(suffix, element)                                            \
2729 d79f0809 aurel32
    void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2730 d79f0809 aurel32
    {                                                                   \
2731 d79f0809 aurel32
        int i;                                                          \
2732 d79f0809 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2733 d79f0809 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2734 d79f0809 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2735 d79f0809 aurel32
            r->element[i] = a->element[i] << shift;                     \
2736 d79f0809 aurel32
        }                                                               \
2737 d79f0809 aurel32
    }
2738 d79f0809 aurel32
VSL(b, u8)
2739 d79f0809 aurel32
VSL(h, u16)
2740 d79f0809 aurel32
VSL(w, u32)
2741 d79f0809 aurel32
#undef VSL
2742 d79f0809 aurel32
2743 cd633b10 aurel32
void helper_vsldoi (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
2744 cd633b10 aurel32
{
2745 cd633b10 aurel32
    int sh = shift & 0xf;
2746 cd633b10 aurel32
    int i;
2747 cd633b10 aurel32
    ppc_avr_t result;
2748 cd633b10 aurel32
2749 cd633b10 aurel32
#if defined(WORDS_BIGENDIAN)
2750 cd633b10 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2751 cd633b10 aurel32
        int index = sh + i;
2752 cd633b10 aurel32
        if (index > 0xf) {
2753 cd633b10 aurel32
            result.u8[i] = b->u8[index-0x10];
2754 cd633b10 aurel32
        } else {
2755 cd633b10 aurel32
            result.u8[i] = a->u8[index];
2756 cd633b10 aurel32
        }
2757 cd633b10 aurel32
    }
2758 cd633b10 aurel32
#else
2759 cd633b10 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2760 cd633b10 aurel32
        int index = (16 - sh) + i;
2761 cd633b10 aurel32
        if (index > 0xf) {
2762 cd633b10 aurel32
            result.u8[i] = a->u8[index-0x10];
2763 cd633b10 aurel32
        } else {
2764 cd633b10 aurel32
            result.u8[i] = b->u8[index];
2765 cd633b10 aurel32
        }
2766 cd633b10 aurel32
    }
2767 cd633b10 aurel32
#endif
2768 cd633b10 aurel32
    *r = result;
2769 cd633b10 aurel32
}
2770 cd633b10 aurel32
2771 7b239bec aurel32
void helper_vslo (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2772 7b239bec aurel32
{
2773 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2774 7b239bec aurel32
2775 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2776 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2777 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2778 7b239bec aurel32
#else
2779 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2780 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2781 7b239bec aurel32
#endif
2782 7b239bec aurel32
}
2783 7b239bec aurel32
2784 e4e6bee7 aurel32
/* Experimental testing shows that hardware masks the immediate.  */
2785 e4e6bee7 aurel32
#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
2786 e4e6bee7 aurel32
#if defined(WORDS_BIGENDIAN)
2787 e4e6bee7 aurel32
#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
2788 e4e6bee7 aurel32
#else
2789 e4e6bee7 aurel32
#define SPLAT_ELEMENT(element) (ARRAY_SIZE(r->element)-1 - _SPLAT_MASKED(element))
2790 e4e6bee7 aurel32
#endif
2791 e4e6bee7 aurel32
#define VSPLT(suffix, element)                                          \
2792 e4e6bee7 aurel32
    void helper_vsplt##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
2793 e4e6bee7 aurel32
    {                                                                   \
2794 e4e6bee7 aurel32
        uint32_t s = b->element[SPLAT_ELEMENT(element)];                \
2795 e4e6bee7 aurel32
        int i;                                                          \
2796 e4e6bee7 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2797 e4e6bee7 aurel32
            r->element[i] = s;                                          \
2798 e4e6bee7 aurel32
        }                                                               \
2799 e4e6bee7 aurel32
    }
2800 e4e6bee7 aurel32
VSPLT(b, u8)
2801 e4e6bee7 aurel32
VSPLT(h, u16)
2802 e4e6bee7 aurel32
VSPLT(w, u32)
2803 e4e6bee7 aurel32
#undef VSPLT
2804 e4e6bee7 aurel32
#undef SPLAT_ELEMENT
2805 e4e6bee7 aurel32
#undef _SPLAT_MASKED
2806 e4e6bee7 aurel32
2807 c026766b aurel32
#define VSPLTI(suffix, element, splat_type)                     \
2808 c026766b aurel32
    void helper_vspltis##suffix (ppc_avr_t *r, uint32_t splat)  \
2809 c026766b aurel32
    {                                                           \
2810 c026766b aurel32
        splat_type x = (int8_t)(splat << 3) >> 3;               \
2811 c026766b aurel32
        int i;                                                  \
2812 c026766b aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {          \
2813 c026766b aurel32
            r->element[i] = x;                                  \
2814 c026766b aurel32
        }                                                       \
2815 c026766b aurel32
    }
2816 c026766b aurel32
VSPLTI(b, s8, int8_t)
2817 c026766b aurel32
VSPLTI(h, s16, int16_t)
2818 c026766b aurel32
VSPLTI(w, s32, int32_t)
2819 c026766b aurel32
#undef VSPLTI
2820 c026766b aurel32
2821 07ef34c3 aurel32
#define VSR(suffix, element)                                            \
2822 07ef34c3 aurel32
    void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2823 07ef34c3 aurel32
    {                                                                   \
2824 07ef34c3 aurel32
        int i;                                                          \
2825 07ef34c3 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2826 07ef34c3 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2827 07ef34c3 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2828 07ef34c3 aurel32
            r->element[i] = a->element[i] >> shift;                     \
2829 07ef34c3 aurel32
        }                                                               \
2830 07ef34c3 aurel32
    }
2831 07ef34c3 aurel32
VSR(ab, s8)
2832 07ef34c3 aurel32
VSR(ah, s16)
2833 07ef34c3 aurel32
VSR(aw, s32)
2834 07ef34c3 aurel32
VSR(b, u8)
2835 07ef34c3 aurel32
VSR(h, u16)
2836 07ef34c3 aurel32
VSR(w, u32)
2837 07ef34c3 aurel32
#undef VSR
2838 07ef34c3 aurel32
2839 7b239bec aurel32
void helper_vsro (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2840 7b239bec aurel32
{
2841 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2842 7b239bec aurel32
2843 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2844 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2845 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2846 7b239bec aurel32
#else
2847 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2848 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2849 7b239bec aurel32
#endif
2850 7b239bec aurel32
}
2851 7b239bec aurel32
2852 e343da72 aurel32
void helper_vsubcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2853 e343da72 aurel32
{
2854 e343da72 aurel32
    int i;
2855 e343da72 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2856 e343da72 aurel32
        r->u32[i] = a->u32[i] >= b->u32[i];
2857 e343da72 aurel32
    }
2858 e343da72 aurel32
}
2859 e343da72 aurel32
2860 8142cddd aurel32
void helper_vsumsws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2861 8142cddd aurel32
{
2862 8142cddd aurel32
    int64_t t;
2863 8142cddd aurel32
    int i, upper;
2864 8142cddd aurel32
    ppc_avr_t result;
2865 8142cddd aurel32
    int sat = 0;
2866 8142cddd aurel32
2867 8142cddd aurel32
#if defined(WORDS_BIGENDIAN)
2868 8142cddd aurel32
    upper = ARRAY_SIZE(r->s32)-1;
2869 8142cddd aurel32
#else
2870 8142cddd aurel32
    upper = 0;
2871 8142cddd aurel32
#endif
2872 8142cddd aurel32
    t = (int64_t)b->s32[upper];
2873 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2874 8142cddd aurel32
        t += a->s32[i];
2875 8142cddd aurel32
        result.s32[i] = 0;
2876 8142cddd aurel32
    }
2877 8142cddd aurel32
    result.s32[upper] = cvtsdsw(t, &sat);
2878 8142cddd aurel32
    *r = result;
2879 8142cddd aurel32
2880 8142cddd aurel32
    if (sat) {
2881 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2882 8142cddd aurel32
    }
2883 8142cddd aurel32
}
2884 8142cddd aurel32
2885 8142cddd aurel32
void helper_vsum2sws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2886 8142cddd aurel32
{
2887 8142cddd aurel32
    int i, j, upper;
2888 8142cddd aurel32
    ppc_avr_t result;
2889 8142cddd aurel32
    int sat = 0;
2890 8142cddd aurel32
2891 8142cddd aurel32
#if defined(WORDS_BIGENDIAN)
2892 8142cddd aurel32
    upper = 1;
2893 8142cddd aurel32
#else
2894 8142cddd aurel32
    upper = 0;
2895 8142cddd aurel32
#endif
2896 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
2897 8142cddd aurel32
        int64_t t = (int64_t)b->s32[upper+i*2];
2898 8142cddd aurel32
        result.u64[i] = 0;
2899 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
2900 8142cddd aurel32
            t += a->s32[2*i+j];
2901 8142cddd aurel32
        }
2902 8142cddd aurel32
        result.s32[upper+i*2] = cvtsdsw(t, &sat);
2903 8142cddd aurel32
    }
2904 8142cddd aurel32
2905 8142cddd aurel32
    *r = result;
2906 8142cddd aurel32
    if (sat) {
2907 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2908 8142cddd aurel32
    }
2909 8142cddd aurel32
}
2910 8142cddd aurel32
2911 8142cddd aurel32
void helper_vsum4sbs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2912 8142cddd aurel32
{
2913 8142cddd aurel32
    int i, j;
2914 8142cddd aurel32
    int sat = 0;
2915 8142cddd aurel32
2916 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2917 8142cddd aurel32
        int64_t t = (int64_t)b->s32[i];
2918 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
2919 8142cddd aurel32
            t += a->s8[4*i+j];
2920 8142cddd aurel32
        }
2921 8142cddd aurel32
        r->s32[i] = cvtsdsw(t, &sat);
2922 8142cddd aurel32
    }
2923 8142cddd aurel32
2924 8142cddd aurel32
    if (sat) {
2925 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2926 8142cddd aurel32
    }
2927 8142cddd aurel32
}
2928 8142cddd aurel32
2929 8142cddd aurel32
void helper_vsum4shs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2930 8142cddd aurel32
{
2931 8142cddd aurel32
    int sat = 0;
2932 8142cddd aurel32
    int i;
2933 8142cddd aurel32
2934 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2935 8142cddd aurel32
        int64_t t = (int64_t)b->s32[i];
2936 8142cddd aurel32
        t += a->s16[2*i] + a->s16[2*i+1];
2937 8142cddd aurel32
        r->s32[i] = cvtsdsw(t, &sat);
2938 8142cddd aurel32
    }
2939 8142cddd aurel32
2940 8142cddd aurel32
    if (sat) {
2941 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2942 8142cddd aurel32
    }
2943 8142cddd aurel32
}
2944 8142cddd aurel32
2945 8142cddd aurel32
void helper_vsum4ubs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2946 8142cddd aurel32
{
2947 8142cddd aurel32
    int i, j;
2948 8142cddd aurel32
    int sat = 0;
2949 8142cddd aurel32
2950 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2951 8142cddd aurel32
        uint64_t t = (uint64_t)b->u32[i];
2952 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
2953 8142cddd aurel32
            t += a->u8[4*i+j];
2954 8142cddd aurel32
        }
2955 8142cddd aurel32
        r->u32[i] = cvtuduw(t, &sat);
2956 8142cddd aurel32
    }
2957 8142cddd aurel32
2958 8142cddd aurel32
    if (sat) {
2959 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2960 8142cddd aurel32
    }
2961 8142cddd aurel32
}
2962 8142cddd aurel32
2963 79f85c3a aurel32
#if defined(WORDS_BIGENDIAN)
2964 79f85c3a aurel32
#define UPKHI 1
2965 79f85c3a aurel32
#define UPKLO 0
2966 79f85c3a aurel32
#else
2967 79f85c3a aurel32
#define UPKHI 0
2968 79f85c3a aurel32
#define UPKLO 1
2969 79f85c3a aurel32
#endif
2970 79f85c3a aurel32
#define VUPKPX(suffix, hi)                                      \
2971 79f85c3a aurel32
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)       \
2972 79f85c3a aurel32
    {                                                           \
2973 79f85c3a aurel32
        int i;                                                  \
2974 79f85c3a aurel32
        ppc_avr_t result;                                       \
2975 79f85c3a aurel32
        for (i = 0; i < ARRAY_SIZE(r->u32); i++) {              \
2976 79f85c3a aurel32
            uint16_t e = b->u16[hi ? i : i+4];                  \
2977 79f85c3a aurel32
            uint8_t a = (e >> 15) ? 0xff : 0;                   \
2978 79f85c3a aurel32
            uint8_t r = (e >> 10) & 0x1f;                       \
2979 79f85c3a aurel32
            uint8_t g = (e >> 5) & 0x1f;                        \
2980 79f85c3a aurel32
            uint8_t b = e & 0x1f;                               \
2981 79f85c3a aurel32
            result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
2982 79f85c3a aurel32
        }                                                               \
2983 79f85c3a aurel32
        *r = result;                                                    \
2984 79f85c3a aurel32
    }
2985 79f85c3a aurel32
VUPKPX(lpx, UPKLO)
2986 79f85c3a aurel32
VUPKPX(hpx, UPKHI)
2987 79f85c3a aurel32
#undef VUPKPX
2988 79f85c3a aurel32
2989 6cf1c6e5 aurel32
#define VUPK(suffix, unpacked, packee, hi)                              \
2990 6cf1c6e5 aurel32
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
2991 6cf1c6e5 aurel32
    {                                                                   \
2992 6cf1c6e5 aurel32
        int i;                                                          \
2993 6cf1c6e5 aurel32
        ppc_avr_t result;                                               \
2994 6cf1c6e5 aurel32
        if (hi) {                                                       \
2995 6cf1c6e5 aurel32
            for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
2996 6cf1c6e5 aurel32
                result.unpacked[i] = b->packee[i];                      \
2997 6cf1c6e5 aurel32
            }                                                           \
2998 6cf1c6e5 aurel32
        } else {                                                        \
2999 6cf1c6e5 aurel32
            for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); i++) { \
3000 6cf1c6e5 aurel32
                result.unpacked[i-ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
3001 6cf1c6e5 aurel32
            }                                                           \
3002 6cf1c6e5 aurel32
        }                                                               \
3003 6cf1c6e5 aurel32
        *r = result;                                                    \
3004 6cf1c6e5 aurel32
    }
3005 6cf1c6e5 aurel32
VUPK(hsb, s16, s8, UPKHI)
3006 6cf1c6e5 aurel32
VUPK(hsh, s32, s16, UPKHI)
3007 6cf1c6e5 aurel32
VUPK(lsb, s16, s8, UPKLO)
3008 6cf1c6e5 aurel32
VUPK(lsh, s32, s16, UPKLO)
3009 6cf1c6e5 aurel32
#undef VUPK
3010 79f85c3a aurel32
#undef UPKHI
3011 79f85c3a aurel32
#undef UPKLO
3012 79f85c3a aurel32
3013 34ba2857 aurel32
#undef DO_HANDLE_NAN
3014 34ba2857 aurel32
#undef HANDLE_NAN1
3015 34ba2857 aurel32
#undef HANDLE_NAN2
3016 34ba2857 aurel32
#undef HANDLE_NAN3
3017 d6a46fe8 aurel32
#undef VECTOR_FOR_INORDER_I
3018 d6a46fe8 aurel32
#undef HI_IDX
3019 d6a46fe8 aurel32
#undef LO_IDX
3020 d6a46fe8 aurel32
3021 d6a46fe8 aurel32
/*****************************************************************************/
3022 0487d6a8 j_mayer
/* SPE extension helpers */
3023 0487d6a8 j_mayer
/* Use a table to make this quicker */
3024 0487d6a8 j_mayer
static uint8_t hbrev[16] = {
3025 0487d6a8 j_mayer
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
3026 0487d6a8 j_mayer
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
3027 0487d6a8 j_mayer
};
3028 0487d6a8 j_mayer
3029 b068d6a7 j_mayer
static always_inline uint8_t byte_reverse (uint8_t val)
3030 0487d6a8 j_mayer
{
3031 0487d6a8 j_mayer
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
3032 0487d6a8 j_mayer
}
3033 0487d6a8 j_mayer
3034 b068d6a7 j_mayer
static always_inline uint32_t word_reverse (uint32_t val)
3035 0487d6a8 j_mayer
{
3036 0487d6a8 j_mayer
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
3037 0487d6a8 j_mayer
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
3038 0487d6a8 j_mayer
}
3039 0487d6a8 j_mayer
3040 3cd7d1dd j_mayer
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
3041 57951c27 aurel32
target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
3042 0487d6a8 j_mayer
{
3043 0487d6a8 j_mayer
    uint32_t a, b, d, mask;
3044 0487d6a8 j_mayer
3045 3cd7d1dd j_mayer
    mask = UINT32_MAX >> (32 - MASKBITS);
3046 57951c27 aurel32
    a = arg1 & mask;
3047 57951c27 aurel32
    b = arg2 & mask;
3048 3cd7d1dd j_mayer
    d = word_reverse(1 + word_reverse(a | ~b));
3049 57951c27 aurel32
    return (arg1 & ~mask) | (d & b);
3050 0487d6a8 j_mayer
}
3051 0487d6a8 j_mayer
3052 57951c27 aurel32
uint32_t helper_cntlsw32 (uint32_t val)
3053 0487d6a8 j_mayer
{
3054 0487d6a8 j_mayer
    if (val & 0x80000000)
3055 603fccce j_mayer
        return clz32(~val);
3056 0487d6a8 j_mayer
    else
3057 603fccce j_mayer
        return clz32(val);
3058 0487d6a8 j_mayer
}
3059 0487d6a8 j_mayer
3060 57951c27 aurel32
uint32_t helper_cntlzw32 (uint32_t val)
3061 0487d6a8 j_mayer
{
3062 603fccce j_mayer
    return clz32(val);
3063 0487d6a8 j_mayer
}
3064 0487d6a8 j_mayer
3065 1c97856d aurel32
/* Single-precision floating-point conversions */
3066 1c97856d aurel32
static always_inline uint32_t efscfsi (uint32_t val)
3067 0487d6a8 j_mayer
{
3068 0ca9d380 aurel32
    CPU_FloatU u;
3069 0487d6a8 j_mayer
3070 fbd265b6 aurel32
    u.f = int32_to_float32(val, &env->vec_status);
3071 0487d6a8 j_mayer
3072 0ca9d380 aurel32
    return u.l;
3073 0487d6a8 j_mayer
}
3074 0487d6a8 j_mayer
3075 1c97856d aurel32
static always_inline uint32_t efscfui (uint32_t val)
3076 0487d6a8 j_mayer
{
3077 0ca9d380 aurel32
    CPU_FloatU u;
3078 0487d6a8 j_mayer
3079 fbd265b6 aurel32
    u.f = uint32_to_float32(val, &env->vec_status);
3080 0487d6a8 j_mayer
3081 0ca9d380 aurel32
    return u.l;
3082 0487d6a8 j_mayer
}
3083 0487d6a8 j_mayer
3084 1c97856d aurel32
static always_inline int32_t efsctsi (uint32_t val)
3085 0487d6a8 j_mayer
{
3086 0ca9d380 aurel32
    CPU_FloatU u;
3087 0487d6a8 j_mayer
3088 0ca9d380 aurel32
    u.l = val;
3089 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3090 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3091 0487d6a8 j_mayer
        return 0;
3092 0487d6a8 j_mayer
3093 fbd265b6 aurel32
    return float32_to_int32(u.f, &env->vec_status);
3094 0487d6a8 j_mayer
}
3095 0487d6a8 j_mayer
3096 1c97856d aurel32
static always_inline uint32_t efsctui (uint32_t val)
3097 0487d6a8 j_mayer
{
3098 0ca9d380 aurel32
    CPU_FloatU u;
3099 0487d6a8 j_mayer
3100 0ca9d380 aurel32
    u.l = val;
3101 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3102 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3103 0487d6a8 j_mayer
        return 0;
3104 0487d6a8 j_mayer
3105 fbd265b6 aurel32
    return float32_to_uint32(u.f, &env->vec_status);
3106 0487d6a8 j_mayer
}
3107 0487d6a8 j_mayer
3108 1c97856d aurel32
static always_inline uint32_t efsctsiz (uint32_t val)
3109 0487d6a8 j_mayer
{
3110 0ca9d380 aurel32
    CPU_FloatU u;
3111 0487d6a8 j_mayer
3112 0ca9d380 aurel32
    u.l = val;
3113 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3114 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3115 0487d6a8 j_mayer
        return 0;
3116 0487d6a8 j_mayer
3117 fbd265b6 aurel32
    return float32_to_int32_round_to_zero(u.f, &env->vec_status);
3118 0487d6a8 j_mayer
}
3119 0487d6a8 j_mayer
3120 1c97856d aurel32
static always_inline uint32_t efsctuiz (uint32_t val)
3121 0487d6a8 j_mayer
{
3122 0ca9d380 aurel32
    CPU_FloatU u;
3123 0487d6a8 j_mayer
3124 0ca9d380 aurel32
    u.l = val;
3125 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3126 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3127 0487d6a8 j_mayer
        return 0;
3128 0487d6a8 j_mayer
3129 fbd265b6 aurel32
    return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
3130 0487d6a8 j_mayer
}
3131 0487d6a8 j_mayer
3132 1c97856d aurel32
static always_inline uint32_t efscfsf (uint32_t val)
3133 0487d6a8 j_mayer
{
3134 0ca9d380 aurel32
    CPU_FloatU u;
3135 0487d6a8 j_mayer
    float32 tmp;
3136 0487d6a8 j_mayer
3137 fbd265b6 aurel32
    u.f = int32_to_float32(val, &env->vec_status);
3138 fbd265b6 aurel32
    tmp = int64_to_float32(1ULL << 32, &env->vec_status);
3139 fbd265b6 aurel32
    u.f = float32_div(u.f, tmp, &env->vec_status);
3140 0487d6a8 j_mayer
3141 0ca9d380 aurel32
    return u.l;
3142 0487d6a8 j_mayer
}
3143 0487d6a8 j_mayer
3144 1c97856d aurel32
static always_inline uint32_t efscfuf (uint32_t val)
3145 0487d6a8 j_mayer
{
3146 0ca9d380 aurel32
    CPU_FloatU u;
3147 0487d6a8 j_mayer
    float32 tmp;
3148 0487d6a8 j_mayer
3149 fbd265b6 aurel32
    u.f = uint32_to_float32(val, &env->vec_status);
3150 fbd265b6 aurel32
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3151 fbd265b6 aurel32
    u.f = float32_div(u.f, tmp, &env->vec_status);
3152 0487d6a8 j_mayer
3153 0ca9d380 aurel32
    return u.l;
3154 0487d6a8 j_mayer
}
3155 0487d6a8 j_mayer
3156 1c97856d aurel32
static always_inline uint32_t efsctsf (uint32_t val)
3157 0487d6a8 j_mayer
{
3158 0ca9d380 aurel32
    CPU_FloatU u;
3159 0487d6a8 j_mayer
    float32 tmp;
3160 0487d6a8 j_mayer
3161 0ca9d380 aurel32
    u.l = val;
3162 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3163 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3164 0487d6a8 j_mayer
        return 0;
3165 fbd265b6 aurel32
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3166 fbd265b6 aurel32
    u.f = float32_mul(u.f, tmp, &env->vec_status);
3167 0487d6a8 j_mayer
3168 fbd265b6 aurel32
    return float32_to_int32(u.f, &env->vec_status);
3169 0487d6a8 j_mayer
}
3170 0487d6a8 j_mayer
3171 1c97856d aurel32
static always_inline uint32_t efsctuf (uint32_t val)
3172 0487d6a8 j_mayer
{
3173 0ca9d380 aurel32
    CPU_FloatU u;
3174 0487d6a8 j_mayer
    float32 tmp;
3175 0487d6a8 j_mayer
3176 0ca9d380 aurel32
    u.l = val;
3177 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3178 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
3179 0487d6a8 j_mayer
        return 0;
3180 fbd265b6 aurel32
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3181 fbd265b6 aurel32
    u.f = float32_mul(u.f, tmp, &env->vec_status);
3182 0487d6a8 j_mayer
3183 fbd265b6 aurel32
    return float32_to_uint32(u.f, &env->vec_status);
3184 0487d6a8 j_mayer
}
3185 0487d6a8 j_mayer
3186 1c97856d aurel32
#define HELPER_SPE_SINGLE_CONV(name)                                          \
3187 1c97856d aurel32
uint32_t helper_e##name (uint32_t val)                                        \
3188 1c97856d aurel32
{                                                                             \
3189 1c97856d aurel32
    return e##name(val);                                                      \
3190 1c97856d aurel32
}
3191 1c97856d aurel32
/* efscfsi */
3192 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsi);
3193 1c97856d aurel32
/* efscfui */
3194 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfui);
3195 1c97856d aurel32
/* efscfuf */
3196 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfuf);
3197 1c97856d aurel32
/* efscfsf */
3198 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsf);
3199 1c97856d aurel32
/* efsctsi */
3200 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsi);
3201 1c97856d aurel32
/* efsctui */
3202 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctui);
3203 1c97856d aurel32
/* efsctsiz */
3204 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsiz);
3205 1c97856d aurel32
/* efsctuiz */
3206 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuiz);
3207 1c97856d aurel32
/* efsctsf */
3208 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsf);
3209 1c97856d aurel32
/* efsctuf */
3210 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuf);
3211 1c97856d aurel32
3212 1c97856d aurel32
#define HELPER_SPE_VECTOR_CONV(name)                                          \
3213 1c97856d aurel32
uint64_t helper_ev##name (uint64_t val)                                       \
3214 1c97856d aurel32
{                                                                             \
3215 1c97856d aurel32
    return ((uint64_t)e##name(val >> 32) << 32) |                             \
3216 1c97856d aurel32
            (uint64_t)e##name(val);                                           \
3217 0487d6a8 j_mayer
}
3218 1c97856d aurel32
/* evfscfsi */
3219 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsi);
3220 1c97856d aurel32
/* evfscfui */
3221 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfui);
3222 1c97856d aurel32
/* evfscfuf */
3223 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfuf);
3224 1c97856d aurel32
/* evfscfsf */
3225 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsf);
3226 1c97856d aurel32
/* evfsctsi */
3227 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsi);
3228 1c97856d aurel32
/* evfsctui */
3229 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctui);
3230 1c97856d aurel32
/* evfsctsiz */
3231 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsiz);
3232 1c97856d aurel32
/* evfsctuiz */
3233 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuiz);
3234 1c97856d aurel32
/* evfsctsf */
3235 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsf);
3236 1c97856d aurel32
/* evfsctuf */
3237 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuf);
3238 0487d6a8 j_mayer
3239 1c97856d aurel32
/* Single-precision floating-point arithmetic */
3240 1c97856d aurel32
static always_inline uint32_t efsadd (uint32_t op1, uint32_t op2)
3241 0487d6a8 j_mayer
{
3242 1c97856d aurel32
    CPU_FloatU u1, u2;
3243 1c97856d aurel32
    u1.l = op1;
3244 1c97856d aurel32
    u2.l = op2;
3245 fbd265b6 aurel32
    u1.f = float32_add(u1.f, u2.f, &env->vec_status);
3246 1c97856d aurel32
    return u1.l;
3247 0487d6a8 j_mayer
}
3248 0487d6a8 j_mayer
3249 1c97856d aurel32
static always_inline uint32_t efssub (uint32_t op1, uint32_t op2)
3250 0487d6a8 j_mayer
{
3251 1c97856d aurel32
    CPU_FloatU u1, u2;
3252 1c97856d aurel32
    u1.l = op1;
3253 1c97856d aurel32
    u2.l = op2;
3254 fbd265b6 aurel32
    u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
3255 1c97856d aurel32
    return u1.l;
3256 0487d6a8 j_mayer
}
3257 0487d6a8 j_mayer
3258 1c97856d aurel32
static always_inline uint32_t efsmul (uint32_t op1, uint32_t op2)
3259 0487d6a8 j_mayer
{
3260 1c97856d aurel32
    CPU_FloatU u1, u2;
3261 1c97856d aurel32
    u1.l = op1;
3262 1c97856d aurel32
    u2.l = op2;
3263 fbd265b6 aurel32
    u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
3264 1c97856d aurel32
    return u1.l;
3265 0487d6a8 j_mayer
}
3266 0487d6a8 j_mayer
3267 1c97856d aurel32
static always_inline uint32_t efsdiv (uint32_t op1, uint32_t op2)
3268 0487d6a8 j_mayer
{
3269 1c97856d aurel32
    CPU_FloatU u1, u2;
3270 1c97856d aurel32
    u1.l = op1;
3271 1c97856d aurel32
    u2.l = op2;
3272 fbd265b6 aurel32
    u1.f = float32_div(u1.f, u2.f, &env->vec_status);
3273 1c97856d aurel32
    return u1.l;
3274 0487d6a8 j_mayer
}
3275 0487d6a8 j_mayer
3276 1c97856d aurel32
#define HELPER_SPE_SINGLE_ARITH(name)                                         \
3277 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
3278 1c97856d aurel32
{                                                                             \
3279 1c97856d aurel32
    return e##name(op1, op2);                                                 \
3280 1c97856d aurel32
}
3281 1c97856d aurel32
/* efsadd */
3282 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsadd);
3283 1c97856d aurel32
/* efssub */
3284 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fssub);
3285 1c97856d aurel32
/* efsmul */
3286 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsmul);
3287 1c97856d aurel32
/* efsdiv */
3288 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsdiv);
3289 1c97856d aurel32
3290 1c97856d aurel32
#define HELPER_SPE_VECTOR_ARITH(name)                                         \
3291 1c97856d aurel32
uint64_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3292 1c97856d aurel32
{                                                                             \
3293 1c97856d aurel32
    return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |                  \
3294 1c97856d aurel32
            (uint64_t)e##name(op1, op2);                                      \
3295 1c97856d aurel32
}
3296 1c97856d aurel32
/* evfsadd */
3297 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsadd);
3298 1c97856d aurel32
/* evfssub */
3299 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fssub);
3300 1c97856d aurel32
/* evfsmul */
3301 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsmul);
3302 1c97856d aurel32
/* evfsdiv */
3303 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsdiv);
3304 1c97856d aurel32
3305 1c97856d aurel32
/* Single-precision floating-point comparisons */
3306 1c97856d aurel32
static always_inline uint32_t efststlt (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
    return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3312 0487d6a8 j_mayer
}
3313 0487d6a8 j_mayer
3314 1c97856d aurel32
static always_inline uint32_t efststgt (uint32_t op1, uint32_t op2)
3315 0487d6a8 j_mayer
{
3316 1c97856d aurel32
    CPU_FloatU u1, u2;
3317 1c97856d aurel32
    u1.l = op1;
3318 1c97856d aurel32
    u2.l = op2;
3319 fbd265b6 aurel32
    return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
3320 0487d6a8 j_mayer
}
3321 0487d6a8 j_mayer
3322 1c97856d aurel32
static always_inline uint32_t efststeq (uint32_t op1, uint32_t op2)
3323 0487d6a8 j_mayer
{
3324 1c97856d aurel32
    CPU_FloatU u1, u2;
3325 1c97856d aurel32
    u1.l = op1;
3326 1c97856d aurel32
    u2.l = op2;
3327 fbd265b6 aurel32
    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3328 0487d6a8 j_mayer
}
3329 0487d6a8 j_mayer
3330 1c97856d aurel32
static always_inline uint32_t efscmplt (uint32_t op1, uint32_t op2)
3331 0487d6a8 j_mayer
{
3332 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3333 1c97856d aurel32
    return efststlt(op1, op2);
3334 0487d6a8 j_mayer
}
3335 0487d6a8 j_mayer
3336 1c97856d aurel32
static always_inline uint32_t efscmpgt (uint32_t op1, uint32_t op2)
3337 0487d6a8 j_mayer
{
3338 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3339 1c97856d aurel32
    return efststgt(op1, op2);
3340 0487d6a8 j_mayer
}
3341 0487d6a8 j_mayer
3342 1c97856d aurel32
static always_inline uint32_t efscmpeq (uint32_t op1, uint32_t op2)
3343 0487d6a8 j_mayer
{
3344 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3345 1c97856d aurel32
    return efststeq(op1, op2);
3346 0487d6a8 j_mayer
}
3347 0487d6a8 j_mayer
3348 1c97856d aurel32
#define HELPER_SINGLE_SPE_CMP(name)                                           \
3349 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
3350 1c97856d aurel32
{                                                                             \
3351 1c97856d aurel32
    return e##name(op1, op2) << 2;                                            \
3352 1c97856d aurel32
}
3353 1c97856d aurel32
/* efststlt */
3354 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststlt);
3355 1c97856d aurel32
/* efststgt */
3356 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststgt);
3357 1c97856d aurel32
/* efststeq */
3358 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststeq);
3359 1c97856d aurel32
/* efscmplt */
3360 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmplt);
3361 1c97856d aurel32
/* efscmpgt */
3362 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpgt);
3363 1c97856d aurel32
/* efscmpeq */
3364 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpeq);
3365 1c97856d aurel32
3366 1c97856d aurel32
static always_inline uint32_t evcmp_merge (int t0, int t1)
3367 0487d6a8 j_mayer
{
3368 1c97856d aurel32
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
3369 0487d6a8 j_mayer
}
3370 0487d6a8 j_mayer
3371 1c97856d aurel32
#define HELPER_VECTOR_SPE_CMP(name)                                           \
3372 1c97856d aurel32
uint32_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3373 1c97856d aurel32
{                                                                             \
3374 1c97856d aurel32
    return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2));     \
3375 0487d6a8 j_mayer
}
3376 1c97856d aurel32
/* evfststlt */
3377 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststlt);
3378 1c97856d aurel32
/* evfststgt */
3379 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststgt);
3380 1c97856d aurel32
/* evfststeq */
3381 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststeq);
3382 1c97856d aurel32
/* evfscmplt */
3383 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmplt);
3384 1c97856d aurel32
/* evfscmpgt */
3385 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpgt);
3386 1c97856d aurel32
/* evfscmpeq */
3387 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpeq);
3388 0487d6a8 j_mayer
3389 1c97856d aurel32
/* Double-precision floating-point conversion */
3390 1c97856d aurel32
uint64_t helper_efdcfsi (uint32_t val)
3391 0487d6a8 j_mayer
{
3392 1c97856d aurel32
    CPU_DoubleU u;
3393 1c97856d aurel32
3394 fbd265b6 aurel32
    u.d = int32_to_float64(val, &env->vec_status);
3395 1c97856d aurel32
3396 1c97856d aurel32
    return u.ll;
3397 0487d6a8 j_mayer
}
3398 0487d6a8 j_mayer
3399 1c97856d aurel32
uint64_t helper_efdcfsid (uint64_t val)
3400 0487d6a8 j_mayer
{
3401 0ca9d380 aurel32
    CPU_DoubleU u;
3402 0487d6a8 j_mayer
3403 fbd265b6 aurel32
    u.d = int64_to_float64(val, &env->vec_status);
3404 0487d6a8 j_mayer
3405 0ca9d380 aurel32
    return u.ll;
3406 0487d6a8 j_mayer
}
3407 0487d6a8 j_mayer
3408 1c97856d aurel32
uint64_t helper_efdcfui (uint32_t val)
3409 1c97856d aurel32
{
3410 1c97856d aurel32
    CPU_DoubleU u;
3411 1c97856d aurel32
3412 fbd265b6 aurel32
    u.d = uint32_to_float64(val, &env->vec_status);
3413 1c97856d aurel32
3414 1c97856d aurel32
    return u.ll;
3415 1c97856d aurel32
}
3416 1c97856d aurel32
3417 1c97856d aurel32
uint64_t helper_efdcfuid (uint64_t val)
3418 0487d6a8 j_mayer
{
3419 0ca9d380 aurel32
    CPU_DoubleU u;
3420 0487d6a8 j_mayer
3421 fbd265b6 aurel32
    u.d = uint64_to_float64(val, &env->vec_status);
3422 0487d6a8 j_mayer
3423 0ca9d380 aurel32
    return u.ll;
3424 0487d6a8 j_mayer
}
3425 0487d6a8 j_mayer
3426 1c97856d aurel32
uint32_t helper_efdctsi (uint64_t val)
3427 0487d6a8 j_mayer
{
3428 0ca9d380 aurel32
    CPU_DoubleU u;
3429 0487d6a8 j_mayer
3430 0ca9d380 aurel32
    u.ll = val;
3431 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3432 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3433 0487d6a8 j_mayer
        return 0;
3434 0487d6a8 j_mayer
3435 fbd265b6 aurel32
    return float64_to_int32(u.d, &env->vec_status);
3436 0487d6a8 j_mayer
}
3437 0487d6a8 j_mayer
3438 1c97856d aurel32
uint32_t helper_efdctui (uint64_t val)
3439 0487d6a8 j_mayer
{
3440 0ca9d380 aurel32
    CPU_DoubleU u;
3441 0487d6a8 j_mayer
3442 0ca9d380 aurel32
    u.ll = val;
3443 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3444 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3445 0487d6a8 j_mayer
        return 0;
3446 0487d6a8 j_mayer
3447 fbd265b6 aurel32
    return float64_to_uint32(u.d, &env->vec_status);
3448 0487d6a8 j_mayer
}
3449 0487d6a8 j_mayer
3450 1c97856d aurel32
uint32_t helper_efdctsiz (uint64_t val)
3451 0487d6a8 j_mayer
{
3452 0ca9d380 aurel32
    CPU_DoubleU u;
3453 0487d6a8 j_mayer
3454 0ca9d380 aurel32
    u.ll = val;
3455 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3456 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3457 0487d6a8 j_mayer
        return 0;
3458 0487d6a8 j_mayer
3459 fbd265b6 aurel32
    return float64_to_int32_round_to_zero(u.d, &env->vec_status);
3460 0487d6a8 j_mayer
}
3461 0487d6a8 j_mayer
3462 1c97856d aurel32
uint64_t helper_efdctsidz (uint64_t val)
3463 0487d6a8 j_mayer
{
3464 0ca9d380 aurel32
    CPU_DoubleU u;
3465 0487d6a8 j_mayer
3466 0ca9d380 aurel32
    u.ll = val;
3467 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3468 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3469 0487d6a8 j_mayer
        return 0;
3470 0487d6a8 j_mayer
3471 fbd265b6 aurel32
    return float64_to_int64_round_to_zero(u.d, &env->vec_status);
3472 0487d6a8 j_mayer
}
3473 0487d6a8 j_mayer
3474 1c97856d aurel32
uint32_t helper_efdctuiz (uint64_t val)
3475 0487d6a8 j_mayer
{
3476 1c97856d aurel32
    CPU_DoubleU u;
3477 0487d6a8 j_mayer
3478 1c97856d aurel32
    u.ll = val;
3479 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
3480 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3481 1c97856d aurel32
        return 0;
3482 0487d6a8 j_mayer
3483 fbd265b6 aurel32
    return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
3484 0487d6a8 j_mayer
}
3485 0487d6a8 j_mayer
3486 1c97856d aurel32
uint64_t helper_efdctuidz (uint64_t val)
3487 0487d6a8 j_mayer
{
3488 1c97856d aurel32
    CPU_DoubleU u;
3489 0487d6a8 j_mayer
3490 1c97856d aurel32
    u.ll = val;
3491 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
3492 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3493 1c97856d aurel32
        return 0;
3494 0487d6a8 j_mayer
3495 fbd265b6 aurel32
    return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
3496 0487d6a8 j_mayer
}
3497 0487d6a8 j_mayer
3498 1c97856d aurel32
uint64_t helper_efdcfsf (uint32_t val)
3499 0487d6a8 j_mayer
{
3500 0ca9d380 aurel32
    CPU_DoubleU u;
3501 0487d6a8 j_mayer
    float64 tmp;
3502 0487d6a8 j_mayer
3503 fbd265b6 aurel32
    u.d = int32_to_float64(val, &env->vec_status);
3504 fbd265b6 aurel32
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3505 fbd265b6 aurel32
    u.d = float64_div(u.d, tmp, &env->vec_status);
3506 0487d6a8 j_mayer
3507 0ca9d380 aurel32
    return u.ll;
3508 0487d6a8 j_mayer
}
3509 0487d6a8 j_mayer
3510 1c97856d aurel32
uint64_t helper_efdcfuf (uint32_t val)
3511 0487d6a8 j_mayer
{
3512 0ca9d380 aurel32
    CPU_DoubleU u;
3513 0487d6a8 j_mayer
    float64 tmp;
3514 0487d6a8 j_mayer
3515 fbd265b6 aurel32
    u.d = uint32_to_float64(val, &env->vec_status);
3516 fbd265b6 aurel32
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3517 fbd265b6 aurel32
    u.d = float64_div(u.d, tmp, &env->vec_status);
3518 0487d6a8 j_mayer
3519 0ca9d380 aurel32
    return u.ll;
3520 0487d6a8 j_mayer
}
3521 0487d6a8 j_mayer
3522 1c97856d aurel32
uint32_t helper_efdctsf (uint64_t val)
3523 0487d6a8 j_mayer
{
3524 0ca9d380 aurel32
    CPU_DoubleU u;
3525 0487d6a8 j_mayer
    float64 tmp;
3526 0487d6a8 j_mayer
3527 0ca9d380 aurel32
    u.ll = val;
3528 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3529 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3530 0487d6a8 j_mayer
        return 0;
3531 fbd265b6 aurel32
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3532 fbd265b6 aurel32
    u.d = float64_mul(u.d, tmp, &env->vec_status);
3533 0487d6a8 j_mayer
3534 fbd265b6 aurel32
    return float64_to_int32(u.d, &env->vec_status);
3535 0487d6a8 j_mayer
}
3536 0487d6a8 j_mayer
3537 1c97856d aurel32
uint32_t helper_efdctuf (uint64_t val)
3538 0487d6a8 j_mayer
{
3539 0ca9d380 aurel32
    CPU_DoubleU u;
3540 0487d6a8 j_mayer
    float64 tmp;
3541 0487d6a8 j_mayer
3542 0ca9d380 aurel32
    u.ll = val;
3543 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3544 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3545 0487d6a8 j_mayer
        return 0;
3546 fbd265b6 aurel32
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3547 fbd265b6 aurel32
    u.d = float64_mul(u.d, tmp, &env->vec_status);
3548 0487d6a8 j_mayer
3549 fbd265b6 aurel32
    return float64_to_uint32(u.d, &env->vec_status);
3550 0487d6a8 j_mayer
}
3551 0487d6a8 j_mayer
3552 1c97856d aurel32
uint32_t helper_efscfd (uint64_t val)
3553 0487d6a8 j_mayer
{
3554 0ca9d380 aurel32
    CPU_DoubleU u1;
3555 0ca9d380 aurel32
    CPU_FloatU u2;
3556 0487d6a8 j_mayer
3557 0ca9d380 aurel32
    u1.ll = val;
3558 fbd265b6 aurel32
    u2.f = float64_to_float32(u1.d, &env->vec_status);
3559 0487d6a8 j_mayer
3560 0ca9d380 aurel32
    return u2.l;
3561 0487d6a8 j_mayer
}
3562 0487d6a8 j_mayer
3563 1c97856d aurel32
uint64_t helper_efdcfs (uint32_t val)
3564 0487d6a8 j_mayer
{
3565 0ca9d380 aurel32
    CPU_DoubleU u2;
3566 0ca9d380 aurel32
    CPU_FloatU u1;
3567 0487d6a8 j_mayer
3568 0ca9d380 aurel32
    u1.l = val;
3569 fbd265b6 aurel32
    u2.d = float32_to_float64(u1.f, &env->vec_status);
3570 0487d6a8 j_mayer
3571 0ca9d380 aurel32
    return u2.ll;
3572 0487d6a8 j_mayer
}
3573 0487d6a8 j_mayer
3574 1c97856d aurel32
/* Double precision fixed-point arithmetic */
3575 1c97856d aurel32
uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
3576 0487d6a8 j_mayer
{
3577 1c97856d aurel32
    CPU_DoubleU u1, u2;
3578 1c97856d aurel32
    u1.ll = op1;
3579 1c97856d aurel32
    u2.ll = op2;
3580 fbd265b6 aurel32
    u1.d = float64_add(u1.d, u2.d, &env->vec_status);
3581 1c97856d aurel32
    return u1.ll;
3582 0487d6a8 j_mayer
}
3583 0487d6a8 j_mayer
3584 1c97856d aurel32
uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
3585 0487d6a8 j_mayer
{
3586 1c97856d aurel32
    CPU_DoubleU u1, u2;
3587 1c97856d aurel32
    u1.ll = op1;
3588 1c97856d aurel32
    u2.ll = op2;
3589 fbd265b6 aurel32
    u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
3590 1c97856d aurel32
    return u1.ll;
3591 0487d6a8 j_mayer
}
3592 0487d6a8 j_mayer
3593 1c97856d aurel32
uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
3594 0487d6a8 j_mayer
{
3595 1c97856d aurel32
    CPU_DoubleU u1, u2;
3596 1c97856d aurel32
    u1.ll = op1;
3597 1c97856d aurel32
    u2.ll = op2;
3598 fbd265b6 aurel32
    u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
3599 1c97856d aurel32
    return u1.ll;
3600 0487d6a8 j_mayer
}
3601 0487d6a8 j_mayer
3602 1c97856d aurel32
uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
3603 0487d6a8 j_mayer
{
3604 1c97856d aurel32
    CPU_DoubleU u1, u2;
3605 1c97856d aurel32
    u1.ll = op1;
3606 1c97856d aurel32
    u2.ll = op2;
3607 fbd265b6 aurel32
    u1.d = float64_div(u1.d, u2.d, &env->vec_status);
3608 1c97856d aurel32
    return u1.ll;
3609 0487d6a8 j_mayer
}
3610 0487d6a8 j_mayer
3611 1c97856d aurel32
/* Double precision floating point helpers */
3612 1c97856d aurel32
uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
3613 0487d6a8 j_mayer
{
3614 1c97856d aurel32
    CPU_DoubleU u1, u2;
3615 1c97856d aurel32
    u1.ll = op1;
3616 1c97856d aurel32
    u2.ll = op2;
3617 fbd265b6 aurel32
    return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3618 0487d6a8 j_mayer
}
3619 0487d6a8 j_mayer
3620 1c97856d aurel32
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
3621 0487d6a8 j_mayer
{
3622 1c97856d aurel32
    CPU_DoubleU u1, u2;
3623 1c97856d aurel32
    u1.ll = op1;
3624 1c97856d aurel32
    u2.ll = op2;
3625 fbd265b6 aurel32
    return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
3626 0487d6a8 j_mayer
}
3627 0487d6a8 j_mayer
3628 1c97856d aurel32
uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
3629 0487d6a8 j_mayer
{
3630 1c97856d aurel32
    CPU_DoubleU u1, u2;
3631 1c97856d aurel32
    u1.ll = op1;
3632 1c97856d aurel32
    u2.ll = op2;
3633 fbd265b6 aurel32
    return float64_eq(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3634 0487d6a8 j_mayer
}
3635 0487d6a8 j_mayer
3636 1c97856d aurel32
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
3637 0487d6a8 j_mayer
{
3638 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3639 1c97856d aurel32
    return helper_efdtstlt(op1, op2);
3640 0487d6a8 j_mayer
}
3641 0487d6a8 j_mayer
3642 1c97856d aurel32
uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
3643 1c97856d aurel32
{
3644 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3645 1c97856d aurel32
    return helper_efdtstgt(op1, op2);
3646 1c97856d aurel32
}
3647 0487d6a8 j_mayer
3648 1c97856d aurel32
uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
3649 1c97856d aurel32
{
3650 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3651 1c97856d aurel32
    return helper_efdtsteq(op1, op2);
3652 1c97856d aurel32
}
3653 0487d6a8 j_mayer
3654 fdabc366 bellard
/*****************************************************************************/
3655 fdabc366 bellard
/* Softmmu support */
3656 fdabc366 bellard
#if !defined (CONFIG_USER_ONLY)
3657 fdabc366 bellard
3658 fdabc366 bellard
#define MMUSUFFIX _mmu
3659 fdabc366 bellard
3660 fdabc366 bellard
#define SHIFT 0
3661 fdabc366 bellard
#include "softmmu_template.h"
3662 fdabc366 bellard
3663 fdabc366 bellard
#define SHIFT 1
3664 fdabc366 bellard
#include "softmmu_template.h"
3665 fdabc366 bellard
3666 fdabc366 bellard
#define SHIFT 2
3667 fdabc366 bellard
#include "softmmu_template.h"
3668 fdabc366 bellard
3669 fdabc366 bellard
#define SHIFT 3
3670 fdabc366 bellard
#include "softmmu_template.h"
3671 fdabc366 bellard
3672 fdabc366 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
3673 fdabc366 bellard
   NULL, it means that the function was called in C code (i.e. not
3674 fdabc366 bellard
   from generated code or from helper.c) */
3675 fdabc366 bellard
/* XXX: fix it to restore all registers */
3676 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3677 fdabc366 bellard
{
3678 fdabc366 bellard
    TranslationBlock *tb;
3679 fdabc366 bellard
    CPUState *saved_env;
3680 44f8625d bellard
    unsigned long pc;
3681 fdabc366 bellard
    int ret;
3682 fdabc366 bellard
3683 fdabc366 bellard
    /* XXX: hack to restore env in all cases, even if not called from
3684 fdabc366 bellard
       generated code */
3685 fdabc366 bellard
    saved_env = env;
3686 fdabc366 bellard
    env = cpu_single_env;
3687 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3688 76a66253 j_mayer
    if (unlikely(ret != 0)) {
3689 fdabc366 bellard
        if (likely(retaddr)) {
3690 fdabc366 bellard
            /* now we have a real cpu fault */
3691 44f8625d bellard
            pc = (unsigned long)retaddr;
3692 fdabc366 bellard
            tb = tb_find_pc(pc);
3693 fdabc366 bellard
            if (likely(tb)) {
3694 fdabc366 bellard
                /* the PC is inside the translated code. It means that we have
3695 fdabc366 bellard
                   a virtual CPU fault */
3696 fdabc366 bellard
                cpu_restore_state(tb, env, pc, NULL);
3697 76a66253 j_mayer
            }
3698 fdabc366 bellard
        }
3699 e06fcd75 aurel32
        helper_raise_exception_err(env->exception_index, env->error_code);
3700 fdabc366 bellard
    }
3701 fdabc366 bellard
    env = saved_env;
3702 9a64fbe4 bellard
}
3703 9a64fbe4 bellard
3704 74d37793 aurel32
/* Segment registers load and store */
3705 74d37793 aurel32
target_ulong helper_load_sr (target_ulong sr_num)
3706 74d37793 aurel32
{
3707 74d37793 aurel32
    return env->sr[sr_num];
3708 74d37793 aurel32
}
3709 74d37793 aurel32
3710 74d37793 aurel32
void helper_store_sr (target_ulong sr_num, target_ulong val)
3711 74d37793 aurel32
{
3712 45d827d2 aurel32
    ppc_store_sr(env, sr_num, val);
3713 74d37793 aurel32
}
3714 74d37793 aurel32
3715 74d37793 aurel32
/* SLB management */
3716 74d37793 aurel32
#if defined(TARGET_PPC64)
3717 74d37793 aurel32
target_ulong helper_load_slb (target_ulong slb_nr)
3718 74d37793 aurel32
{
3719 74d37793 aurel32
    return ppc_load_slb(env, slb_nr);
3720 74d37793 aurel32
}
3721 74d37793 aurel32
3722 74d37793 aurel32
void helper_store_slb (target_ulong slb_nr, target_ulong rs)
3723 74d37793 aurel32
{
3724 74d37793 aurel32
    ppc_store_slb(env, slb_nr, rs);
3725 74d37793 aurel32
}
3726 74d37793 aurel32
3727 74d37793 aurel32
void helper_slbia (void)
3728 74d37793 aurel32
{
3729 74d37793 aurel32
    ppc_slb_invalidate_all(env);
3730 74d37793 aurel32
}
3731 74d37793 aurel32
3732 74d37793 aurel32
void helper_slbie (target_ulong addr)
3733 74d37793 aurel32
{
3734 74d37793 aurel32
    ppc_slb_invalidate_one(env, addr);
3735 74d37793 aurel32
}
3736 74d37793 aurel32
3737 74d37793 aurel32
#endif /* defined(TARGET_PPC64) */
3738 74d37793 aurel32
3739 74d37793 aurel32
/* TLB management */
3740 74d37793 aurel32
void helper_tlbia (void)
3741 74d37793 aurel32
{
3742 74d37793 aurel32
    ppc_tlb_invalidate_all(env);
3743 74d37793 aurel32
}
3744 74d37793 aurel32
3745 74d37793 aurel32
void helper_tlbie (target_ulong addr)
3746 74d37793 aurel32
{
3747 74d37793 aurel32
    ppc_tlb_invalidate_one(env, addr);
3748 74d37793 aurel32
}
3749 74d37793 aurel32
3750 76a66253 j_mayer
/* Software driven TLBs management */
3751 76a66253 j_mayer
/* PowerPC 602/603 software TLB load instructions helpers */
3752 74d37793 aurel32
static void do_6xx_tlb (target_ulong new_EPN, int is_code)
3753 76a66253 j_mayer
{
3754 76a66253 j_mayer
    target_ulong RPN, CMP, EPN;
3755 76a66253 j_mayer
    int way;
3756 d9bce9d9 j_mayer
3757 76a66253 j_mayer
    RPN = env->spr[SPR_RPA];
3758 76a66253 j_mayer
    if (is_code) {
3759 76a66253 j_mayer
        CMP = env->spr[SPR_ICMP];
3760 76a66253 j_mayer
        EPN = env->spr[SPR_IMISS];
3761 76a66253 j_mayer
    } else {
3762 76a66253 j_mayer
        CMP = env->spr[SPR_DCMP];
3763 76a66253 j_mayer
        EPN = env->spr[SPR_DMISS];
3764 76a66253 j_mayer
    }
3765 76a66253 j_mayer
    way = (env->spr[SPR_SRR1] >> 17) & 1;
3766 d12d51d5 aliguori
    LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3767 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
3768 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
3769 76a66253 j_mayer
    /* Store this TLB */
3770 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3771 d9bce9d9 j_mayer
                     way, is_code, CMP, RPN);
3772 76a66253 j_mayer
}
3773 76a66253 j_mayer
3774 74d37793 aurel32
void helper_6xx_tlbd (target_ulong EPN)
3775 0f3955e2 aurel32
{
3776 74d37793 aurel32
    do_6xx_tlb(EPN, 0);
3777 0f3955e2 aurel32
}
3778 0f3955e2 aurel32
3779 74d37793 aurel32
void helper_6xx_tlbi (target_ulong EPN)
3780 0f3955e2 aurel32
{
3781 74d37793 aurel32
    do_6xx_tlb(EPN, 1);
3782 0f3955e2 aurel32
}
3783 0f3955e2 aurel32
3784 0f3955e2 aurel32
/* PowerPC 74xx software TLB load instructions helpers */
3785 74d37793 aurel32
static void do_74xx_tlb (target_ulong new_EPN, int is_code)
3786 7dbe11ac j_mayer
{
3787 7dbe11ac j_mayer
    target_ulong RPN, CMP, EPN;
3788 7dbe11ac j_mayer
    int way;
3789 7dbe11ac j_mayer
3790 7dbe11ac j_mayer
    RPN = env->spr[SPR_PTELO];
3791 7dbe11ac j_mayer
    CMP = env->spr[SPR_PTEHI];
3792 7dbe11ac j_mayer
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
3793 7dbe11ac j_mayer
    way = env->spr[SPR_TLBMISS] & 0x3;
3794 d12d51d5 aliguori
    LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3795 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
3796 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
3797 7dbe11ac j_mayer
    /* Store this TLB */
3798 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3799 7dbe11ac j_mayer
                     way, is_code, CMP, RPN);
3800 7dbe11ac j_mayer
}
3801 7dbe11ac j_mayer
3802 74d37793 aurel32
void helper_74xx_tlbd (target_ulong EPN)
3803 0f3955e2 aurel32
{
3804 74d37793 aurel32
    do_74xx_tlb(EPN, 0);
3805 0f3955e2 aurel32
}
3806 0f3955e2 aurel32
3807 74d37793 aurel32
void helper_74xx_tlbi (target_ulong EPN)
3808 0f3955e2 aurel32
{
3809 74d37793 aurel32
    do_74xx_tlb(EPN, 1);
3810 0f3955e2 aurel32
}
3811 0f3955e2 aurel32
3812 a11b8151 j_mayer
static always_inline target_ulong booke_tlb_to_page_size (int size)
3813 a8dea12f j_mayer
{
3814 a8dea12f j_mayer
    return 1024 << (2 * size);
3815 a8dea12f j_mayer
}
3816 a8dea12f j_mayer
3817 a11b8151 j_mayer
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
3818 a8dea12f j_mayer
{
3819 a8dea12f j_mayer
    int size;
3820 a8dea12f j_mayer
3821 a8dea12f j_mayer
    switch (page_size) {
3822 a8dea12f j_mayer
    case 0x00000400UL:
3823 a8dea12f j_mayer
        size = 0x0;
3824 a8dea12f j_mayer
        break;
3825 a8dea12f j_mayer
    case 0x00001000UL:
3826 a8dea12f j_mayer
        size = 0x1;
3827 a8dea12f j_mayer
        break;
3828 a8dea12f j_mayer
    case 0x00004000UL:
3829 a8dea12f j_mayer
        size = 0x2;
3830 a8dea12f j_mayer
        break;
3831 a8dea12f j_mayer
    case 0x00010000UL:
3832 a8dea12f j_mayer
        size = 0x3;
3833 a8dea12f j_mayer
        break;
3834 a8dea12f j_mayer
    case 0x00040000UL:
3835 a8dea12f j_mayer
        size = 0x4;
3836 a8dea12f j_mayer
        break;
3837 a8dea12f j_mayer
    case 0x00100000UL:
3838 a8dea12f j_mayer
        size = 0x5;
3839 a8dea12f j_mayer
        break;
3840 a8dea12f j_mayer
    case 0x00400000UL:
3841 a8dea12f j_mayer
        size = 0x6;
3842 a8dea12f j_mayer
        break;
3843 a8dea12f j_mayer
    case 0x01000000UL:
3844 a8dea12f j_mayer
        size = 0x7;
3845 a8dea12f j_mayer
        break;
3846 a8dea12f j_mayer
    case 0x04000000UL:
3847 a8dea12f j_mayer
        size = 0x8;
3848 a8dea12f j_mayer
        break;
3849 a8dea12f j_mayer
    case 0x10000000UL:
3850 a8dea12f j_mayer
        size = 0x9;
3851 a8dea12f j_mayer
        break;
3852 a8dea12f j_mayer
    case 0x40000000UL:
3853 a8dea12f j_mayer
        size = 0xA;
3854 a8dea12f j_mayer
        break;
3855 a8dea12f j_mayer
#if defined (TARGET_PPC64)
3856 a8dea12f j_mayer
    case 0x000100000000ULL:
3857 a8dea12f j_mayer
        size = 0xB;
3858 a8dea12f j_mayer
        break;
3859 a8dea12f j_mayer
    case 0x000400000000ULL:
3860 a8dea12f j_mayer
        size = 0xC;
3861 a8dea12f j_mayer
        break;
3862 a8dea12f j_mayer
    case 0x001000000000ULL:
3863 a8dea12f j_mayer
        size = 0xD;
3864 a8dea12f j_mayer
        break;
3865 a8dea12f j_mayer
    case 0x004000000000ULL:
3866 a8dea12f j_mayer
        size = 0xE;
3867 a8dea12f j_mayer
        break;
3868 a8dea12f j_mayer
    case 0x010000000000ULL:
3869 a8dea12f j_mayer
        size = 0xF;
3870 a8dea12f j_mayer
        break;
3871 a8dea12f j_mayer
#endif
3872 a8dea12f j_mayer
    default:
3873 a8dea12f j_mayer
        size = -1;
3874 a8dea12f j_mayer
        break;
3875 a8dea12f j_mayer
    }
3876 a8dea12f j_mayer
3877 a8dea12f j_mayer
    return size;
3878 a8dea12f j_mayer
}
3879 a8dea12f j_mayer
3880 76a66253 j_mayer
/* Helpers for 4xx TLB management */
3881 74d37793 aurel32
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
3882 76a66253 j_mayer
{
3883 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3884 74d37793 aurel32
    target_ulong ret;
3885 a8dea12f j_mayer
    int size;
3886 76a66253 j_mayer
3887 74d37793 aurel32
    entry &= 0x3F;
3888 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3889 74d37793 aurel32
    ret = tlb->EPN;
3890 a8dea12f j_mayer
    if (tlb->prot & PAGE_VALID)
3891 74d37793 aurel32
        ret |= 0x400;
3892 a8dea12f j_mayer
    size = booke_page_size_to_tlb(tlb->size);
3893 a8dea12f j_mayer
    if (size < 0 || size > 0x7)
3894 a8dea12f j_mayer
        size = 1;
3895 74d37793 aurel32
    ret |= size << 7;
3896 a8dea12f j_mayer
    env->spr[SPR_40x_PID] = tlb->PID;
3897 74d37793 aurel32
    return ret;
3898 76a66253 j_mayer
}
3899 76a66253 j_mayer
3900 74d37793 aurel32
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
3901 76a66253 j_mayer
{
3902 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3903 74d37793 aurel32
    target_ulong ret;
3904 76a66253 j_mayer
3905 74d37793 aurel32
    entry &= 0x3F;
3906 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3907 74d37793 aurel32
    ret = tlb->RPN;
3908 a8dea12f j_mayer
    if (tlb->prot & PAGE_EXEC)
3909 74d37793 aurel32
        ret |= 0x200;
3910 a8dea12f j_mayer
    if (tlb->prot & PAGE_WRITE)
3911 74d37793 aurel32
        ret |= 0x100;
3912 74d37793 aurel32
    return ret;
3913 76a66253 j_mayer
}
3914 76a66253 j_mayer
3915 74d37793 aurel32
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
3916 76a66253 j_mayer
{
3917 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3918 76a66253 j_mayer
    target_ulong page, end;
3919 76a66253 j_mayer
3920 d12d51d5 aliguori
    LOG_SWTLB("%s entry %d val " ADDRX "\n", __func__, (int)entry, val);
3921 74d37793 aurel32
    entry &= 0x3F;
3922 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3923 76a66253 j_mayer
    /* Invalidate previous TLB (if it's valid) */
3924 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
3925 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
3926 d12d51d5 aliguori
        LOG_SWTLB("%s: invalidate old TLB %d start " ADDRX
3927 74d37793 aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3928 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3929 76a66253 j_mayer
            tlb_flush_page(env, page);
3930 76a66253 j_mayer
    }
3931 74d37793 aurel32
    tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
3932 c294fc58 j_mayer
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
3933 c294fc58 j_mayer
     * If this ever occurs, one should use the ppcemb target instead
3934 c294fc58 j_mayer
     * of the ppc or ppc64 one
3935 c294fc58 j_mayer
     */
3936 74d37793 aurel32
    if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
3937 71c8b8fd j_mayer
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
3938 71c8b8fd j_mayer
                  "are not supported (%d)\n",
3939 74d37793 aurel32
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
3940 c294fc58 j_mayer
    }
3941 74d37793 aurel32
    tlb->EPN = val & ~(tlb->size - 1);
3942 74d37793 aurel32
    if (val & 0x40)
3943 76a66253 j_mayer
        tlb->prot |= PAGE_VALID;
3944 76a66253 j_mayer
    else
3945 76a66253 j_mayer
        tlb->prot &= ~PAGE_VALID;
3946 74d37793 aurel32
    if (val & 0x20) {
3947 c294fc58 j_mayer
        /* XXX: TO BE FIXED */
3948 c294fc58 j_mayer
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
3949 c294fc58 j_mayer
    }
3950 c55e9aef j_mayer
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
3951 74d37793 aurel32
    tlb->attr = val & 0xFF;
3952 d12d51d5 aliguori
    LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3953 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3954 0e69805a aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3955 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
3956 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3957 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3958 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3959 76a66253 j_mayer
    /* Invalidate new TLB (if valid) */
3960 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
3961 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
3962 d12d51d5 aliguori
        LOG_SWTLB("%s: invalidate TLB %d start " ADDRX
3963 0e69805a aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3964 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3965 76a66253 j_mayer
            tlb_flush_page(env, page);
3966 76a66253 j_mayer
    }
3967 76a66253 j_mayer
}
3968 76a66253 j_mayer
3969 74d37793 aurel32
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
3970 76a66253 j_mayer
{
3971 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3972 76a66253 j_mayer
3973 d12d51d5 aliguori
    LOG_SWTLB("%s entry %i val " ADDRX "\n", __func__, (int)entry, val);
3974 74d37793 aurel32
    entry &= 0x3F;
3975 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3976 74d37793 aurel32
    tlb->RPN = val & 0xFFFFFC00;
3977 76a66253 j_mayer
    tlb->prot = PAGE_READ;
3978 74d37793 aurel32
    if (val & 0x200)
3979 76a66253 j_mayer
        tlb->prot |= PAGE_EXEC;
3980 74d37793 aurel32
    if (val & 0x100)
3981 76a66253 j_mayer
        tlb->prot |= PAGE_WRITE;
3982 d12d51d5 aliguori
    LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3983 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3984 74d37793 aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3985 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
3986 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3987 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3988 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3989 76a66253 j_mayer
}
3990 5eb7995e j_mayer
3991 74d37793 aurel32
target_ulong helper_4xx_tlbsx (target_ulong address)
3992 74d37793 aurel32
{
3993 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
3994 74d37793 aurel32
}
3995 74d37793 aurel32
3996 a4bb6c3e j_mayer
/* PowerPC 440 TLB management */
3997 74d37793 aurel32
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
3998 5eb7995e j_mayer
{
3999 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
4000 a4bb6c3e j_mayer
    target_ulong EPN, RPN, size;
4001 5eb7995e j_mayer
    int do_flush_tlbs;
4002 5eb7995e j_mayer
4003 d12d51d5 aliguori
    LOG_SWTLB("%s word %d entry %d value " ADDRX "\n",
4004 0e69805a aurel32
                __func__, word, (int)entry, value);
4005 5eb7995e j_mayer
    do_flush_tlbs = 0;
4006 74d37793 aurel32
    entry &= 0x3F;
4007 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
4008 a4bb6c3e j_mayer
    switch (word) {
4009 a4bb6c3e j_mayer
    default:
4010 a4bb6c3e j_mayer
        /* Just here to please gcc */
4011 a4bb6c3e j_mayer
    case 0:
4012 74d37793 aurel32
        EPN = value & 0xFFFFFC00;
4013 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
4014 5eb7995e j_mayer
            do_flush_tlbs = 1;
4015 a4bb6c3e j_mayer
        tlb->EPN = EPN;
4016 74d37793 aurel32
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
4017 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
4018 a4bb6c3e j_mayer
            do_flush_tlbs = 1;
4019 a4bb6c3e j_mayer
        tlb->size = size;
4020 a4bb6c3e j_mayer
        tlb->attr &= ~0x1;
4021 74d37793 aurel32
        tlb->attr |= (value >> 8) & 1;
4022 74d37793 aurel32
        if (value & 0x200) {
4023 a4bb6c3e j_mayer
            tlb->prot |= PAGE_VALID;
4024 a4bb6c3e j_mayer
        } else {
4025 a4bb6c3e j_mayer
            if (tlb->prot & PAGE_VALID) {
4026 a4bb6c3e j_mayer
                tlb->prot &= ~PAGE_VALID;
4027 a4bb6c3e j_mayer
                do_flush_tlbs = 1;
4028 a4bb6c3e j_mayer
            }
4029 5eb7995e j_mayer
        }
4030 a4bb6c3e j_mayer
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
4031 a4bb6c3e j_mayer
        if (do_flush_tlbs)
4032 a4bb6c3e j_mayer
            tlb_flush(env, 1);
4033 a4bb6c3e j_mayer
        break;
4034 a4bb6c3e j_mayer
    case 1:
4035 74d37793 aurel32
        RPN = value & 0xFFFFFC0F;
4036 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
4037 a4bb6c3e j_mayer
            tlb_flush(env, 1);
4038 a4bb6c3e j_mayer
        tlb->RPN = RPN;
4039 a4bb6c3e j_mayer
        break;
4040 a4bb6c3e j_mayer
    case 2:
4041 74d37793 aurel32
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
4042 a4bb6c3e j_mayer
        tlb->prot = tlb->prot & PAGE_VALID;
4043 74d37793 aurel32
        if (value & 0x1)
4044 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ << 4;
4045 74d37793 aurel32
        if (value & 0x2)
4046 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE << 4;
4047 74d37793 aurel32
        if (value & 0x4)
4048 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC << 4;
4049 74d37793 aurel32
        if (value & 0x8)
4050 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ;
4051 74d37793 aurel32
        if (value & 0x10)
4052 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE;
4053 74d37793 aurel32
        if (value & 0x20)
4054 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC;
4055 a4bb6c3e j_mayer
        break;
4056 5eb7995e j_mayer
    }
4057 5eb7995e j_mayer
}
4058 5eb7995e j_mayer
4059 74d37793 aurel32
target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
4060 5eb7995e j_mayer
{
4061 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
4062 74d37793 aurel32
    target_ulong ret;
4063 5eb7995e j_mayer
    int size;
4064 5eb7995e j_mayer
4065 74d37793 aurel32
    entry &= 0x3F;
4066 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
4067 a4bb6c3e j_mayer
    switch (word) {
4068 a4bb6c3e j_mayer
    default:
4069 a4bb6c3e j_mayer
        /* Just here to please gcc */
4070 a4bb6c3e j_mayer
    case 0:
4071 74d37793 aurel32
        ret = tlb->EPN;
4072 a4bb6c3e j_mayer
        size = booke_page_size_to_tlb(tlb->size);
4073 a4bb6c3e j_mayer
        if (size < 0 || size > 0xF)
4074 a4bb6c3e j_mayer
            size = 1;
4075 74d37793 aurel32
        ret |= size << 4;
4076 a4bb6c3e j_mayer
        if (tlb->attr & 0x1)
4077 74d37793 aurel32
            ret |= 0x100;
4078 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_VALID)
4079 74d37793 aurel32
            ret |= 0x200;
4080 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
4081 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] |= tlb->PID;
4082 a4bb6c3e j_mayer
        break;
4083 a4bb6c3e j_mayer
    case 1:
4084 74d37793 aurel32
        ret = tlb->RPN;
4085 a4bb6c3e j_mayer
        break;
4086 a4bb6c3e j_mayer
    case 2:
4087 74d37793 aurel32
        ret = tlb->attr & ~0x1;
4088 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_READ << 4))
4089 74d37793 aurel32
            ret |= 0x1;
4090 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_WRITE << 4))
4091 74d37793 aurel32
            ret |= 0x2;
4092 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_EXEC << 4))
4093 74d37793 aurel32
            ret |= 0x4;
4094 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_READ)
4095 74d37793 aurel32
            ret |= 0x8;
4096 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_WRITE)
4097 74d37793 aurel32
            ret |= 0x10;
4098 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_EXEC)
4099 74d37793 aurel32
            ret |= 0x20;
4100 a4bb6c3e j_mayer
        break;
4101 a4bb6c3e j_mayer
    }
4102 74d37793 aurel32
    return ret;
4103 5eb7995e j_mayer
}
4104 74d37793 aurel32
4105 74d37793 aurel32
target_ulong helper_440_tlbsx (target_ulong address)
4106 74d37793 aurel32
{
4107 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
4108 74d37793 aurel32
}
4109 74d37793 aurel32
4110 76a66253 j_mayer
#endif /* !CONFIG_USER_ONLY */