Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ c026766b

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