Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 1add6e23

History | View | Annotate | Download (109.4 kB)

1 9a64fbe4 bellard
/*
2 3fc6c082 bellard
 *  PowerPC emulation helpers for qemu.
3 5fafdf24 ths
 *
4 76a66253 j_mayer
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5 9a64fbe4 bellard
 *
6 9a64fbe4 bellard
 * This library is free software; you can redistribute it and/or
7 9a64fbe4 bellard
 * modify it under the terms of the GNU Lesser General Public
8 9a64fbe4 bellard
 * License as published by the Free Software Foundation; either
9 9a64fbe4 bellard
 * version 2 of the License, or (at your option) any later version.
10 9a64fbe4 bellard
 *
11 9a64fbe4 bellard
 * This library is distributed in the hope that it will be useful,
12 9a64fbe4 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 9a64fbe4 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 9a64fbe4 bellard
 * Lesser General Public License for more details.
15 9a64fbe4 bellard
 *
16 9a64fbe4 bellard
 * You should have received a copy of the GNU Lesser General Public
17 9a64fbe4 bellard
 * License along with this library; if not, write to the Free Software
18 fad6cb1a aurel32
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19 9a64fbe4 bellard
 */
20 7b239bec aurel32
#include <string.h>
21 9a64fbe4 bellard
#include "exec.h"
22 603fccce j_mayer
#include "host-utils.h"
23 a7812ae4 pbrook
#include "helper.h"
24 9a64fbe4 bellard
25 0411a972 j_mayer
#include "helper_regs.h"
26 0487d6a8 j_mayer
27 fdabc366 bellard
//#define DEBUG_OP
28 fdabc366 bellard
//#define DEBUG_EXCEPTIONS
29 76a66253 j_mayer
//#define DEBUG_SOFTWARE_TLB
30 fdabc366 bellard
31 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 d79f0809 aurel32
#define VSL(suffix, element)                                            \
2456 d79f0809 aurel32
    void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2457 d79f0809 aurel32
    {                                                                   \
2458 d79f0809 aurel32
        int i;                                                          \
2459 d79f0809 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2460 d79f0809 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2461 d79f0809 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2462 d79f0809 aurel32
            r->element[i] = a->element[i] << shift;                     \
2463 d79f0809 aurel32
        }                                                               \
2464 d79f0809 aurel32
    }
2465 d79f0809 aurel32
VSL(b, u8)
2466 d79f0809 aurel32
VSL(h, u16)
2467 d79f0809 aurel32
VSL(w, u32)
2468 d79f0809 aurel32
#undef VSL
2469 d79f0809 aurel32
2470 cd633b10 aurel32
void helper_vsldoi (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
2471 cd633b10 aurel32
{
2472 cd633b10 aurel32
    int sh = shift & 0xf;
2473 cd633b10 aurel32
    int i;
2474 cd633b10 aurel32
    ppc_avr_t result;
2475 cd633b10 aurel32
2476 cd633b10 aurel32
#if defined(WORDS_BIGENDIAN)
2477 cd633b10 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2478 cd633b10 aurel32
        int index = sh + i;
2479 cd633b10 aurel32
        if (index > 0xf) {
2480 cd633b10 aurel32
            result.u8[i] = b->u8[index-0x10];
2481 cd633b10 aurel32
        } else {
2482 cd633b10 aurel32
            result.u8[i] = a->u8[index];
2483 cd633b10 aurel32
        }
2484 cd633b10 aurel32
    }
2485 cd633b10 aurel32
#else
2486 cd633b10 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2487 cd633b10 aurel32
        int index = (16 - sh) + i;
2488 cd633b10 aurel32
        if (index > 0xf) {
2489 cd633b10 aurel32
            result.u8[i] = a->u8[index-0x10];
2490 cd633b10 aurel32
        } else {
2491 cd633b10 aurel32
            result.u8[i] = b->u8[index];
2492 cd633b10 aurel32
        }
2493 cd633b10 aurel32
    }
2494 cd633b10 aurel32
#endif
2495 cd633b10 aurel32
    *r = result;
2496 cd633b10 aurel32
}
2497 cd633b10 aurel32
2498 7b239bec aurel32
void helper_vslo (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2499 7b239bec aurel32
{
2500 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2501 7b239bec aurel32
2502 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2503 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2504 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2505 7b239bec aurel32
#else
2506 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2507 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2508 7b239bec aurel32
#endif
2509 7b239bec aurel32
}
2510 7b239bec aurel32
2511 e4e6bee7 aurel32
/* Experimental testing shows that hardware masks the immediate.  */
2512 e4e6bee7 aurel32
#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
2513 e4e6bee7 aurel32
#if defined(WORDS_BIGENDIAN)
2514 e4e6bee7 aurel32
#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
2515 e4e6bee7 aurel32
#else
2516 e4e6bee7 aurel32
#define SPLAT_ELEMENT(element) (ARRAY_SIZE(r->element)-1 - _SPLAT_MASKED(element))
2517 e4e6bee7 aurel32
#endif
2518 e4e6bee7 aurel32
#define VSPLT(suffix, element)                                          \
2519 e4e6bee7 aurel32
    void helper_vsplt##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
2520 e4e6bee7 aurel32
    {                                                                   \
2521 e4e6bee7 aurel32
        uint32_t s = b->element[SPLAT_ELEMENT(element)];                \
2522 e4e6bee7 aurel32
        int i;                                                          \
2523 e4e6bee7 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2524 e4e6bee7 aurel32
            r->element[i] = s;                                          \
2525 e4e6bee7 aurel32
        }                                                               \
2526 e4e6bee7 aurel32
    }
2527 e4e6bee7 aurel32
VSPLT(b, u8)
2528 e4e6bee7 aurel32
VSPLT(h, u16)
2529 e4e6bee7 aurel32
VSPLT(w, u32)
2530 e4e6bee7 aurel32
#undef VSPLT
2531 e4e6bee7 aurel32
#undef SPLAT_ELEMENT
2532 e4e6bee7 aurel32
#undef _SPLAT_MASKED
2533 e4e6bee7 aurel32
2534 07ef34c3 aurel32
#define VSR(suffix, element)                                            \
2535 07ef34c3 aurel32
    void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2536 07ef34c3 aurel32
    {                                                                   \
2537 07ef34c3 aurel32
        int i;                                                          \
2538 07ef34c3 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2539 07ef34c3 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2540 07ef34c3 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2541 07ef34c3 aurel32
            r->element[i] = a->element[i] >> shift;                     \
2542 07ef34c3 aurel32
        }                                                               \
2543 07ef34c3 aurel32
    }
2544 07ef34c3 aurel32
VSR(ab, s8)
2545 07ef34c3 aurel32
VSR(ah, s16)
2546 07ef34c3 aurel32
VSR(aw, s32)
2547 07ef34c3 aurel32
VSR(b, u8)
2548 07ef34c3 aurel32
VSR(h, u16)
2549 07ef34c3 aurel32
VSR(w, u32)
2550 07ef34c3 aurel32
#undef VSR
2551 07ef34c3 aurel32
2552 7b239bec aurel32
void helper_vsro (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2553 7b239bec aurel32
{
2554 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2555 7b239bec aurel32
2556 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2557 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2558 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2559 7b239bec aurel32
#else
2560 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2561 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2562 7b239bec aurel32
#endif
2563 7b239bec aurel32
}
2564 7b239bec aurel32
2565 e343da72 aurel32
void helper_vsubcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2566 e343da72 aurel32
{
2567 e343da72 aurel32
    int i;
2568 e343da72 aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2569 e343da72 aurel32
        r->u32[i] = a->u32[i] >= b->u32[i];
2570 e343da72 aurel32
    }
2571 e343da72 aurel32
}
2572 e343da72 aurel32
2573 8142cddd aurel32
void helper_vsumsws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2574 8142cddd aurel32
{
2575 8142cddd aurel32
    int64_t t;
2576 8142cddd aurel32
    int i, upper;
2577 8142cddd aurel32
    ppc_avr_t result;
2578 8142cddd aurel32
    int sat = 0;
2579 8142cddd aurel32
2580 8142cddd aurel32
#if defined(WORDS_BIGENDIAN)
2581 8142cddd aurel32
    upper = ARRAY_SIZE(r->s32)-1;
2582 8142cddd aurel32
#else
2583 8142cddd aurel32
    upper = 0;
2584 8142cddd aurel32
#endif
2585 8142cddd aurel32
    t = (int64_t)b->s32[upper];
2586 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2587 8142cddd aurel32
        t += a->s32[i];
2588 8142cddd aurel32
        result.s32[i] = 0;
2589 8142cddd aurel32
    }
2590 8142cddd aurel32
    result.s32[upper] = cvtsdsw(t, &sat);
2591 8142cddd aurel32
    *r = result;
2592 8142cddd aurel32
2593 8142cddd aurel32
    if (sat) {
2594 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2595 8142cddd aurel32
    }
2596 8142cddd aurel32
}
2597 8142cddd aurel32
2598 8142cddd aurel32
void helper_vsum2sws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2599 8142cddd aurel32
{
2600 8142cddd aurel32
    int i, j, upper;
2601 8142cddd aurel32
    ppc_avr_t result;
2602 8142cddd aurel32
    int sat = 0;
2603 8142cddd aurel32
2604 8142cddd aurel32
#if defined(WORDS_BIGENDIAN)
2605 8142cddd aurel32
    upper = 1;
2606 8142cddd aurel32
#else
2607 8142cddd aurel32
    upper = 0;
2608 8142cddd aurel32
#endif
2609 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
2610 8142cddd aurel32
        int64_t t = (int64_t)b->s32[upper+i*2];
2611 8142cddd aurel32
        result.u64[i] = 0;
2612 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
2613 8142cddd aurel32
            t += a->s32[2*i+j];
2614 8142cddd aurel32
        }
2615 8142cddd aurel32
        result.s32[upper+i*2] = cvtsdsw(t, &sat);
2616 8142cddd aurel32
    }
2617 8142cddd aurel32
2618 8142cddd aurel32
    *r = result;
2619 8142cddd aurel32
    if (sat) {
2620 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2621 8142cddd aurel32
    }
2622 8142cddd aurel32
}
2623 8142cddd aurel32
2624 8142cddd aurel32
void helper_vsum4sbs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2625 8142cddd aurel32
{
2626 8142cddd aurel32
    int i, j;
2627 8142cddd aurel32
    int sat = 0;
2628 8142cddd aurel32
2629 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2630 8142cddd aurel32
        int64_t t = (int64_t)b->s32[i];
2631 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
2632 8142cddd aurel32
            t += a->s8[4*i+j];
2633 8142cddd aurel32
        }
2634 8142cddd aurel32
        r->s32[i] = cvtsdsw(t, &sat);
2635 8142cddd aurel32
    }
2636 8142cddd aurel32
2637 8142cddd aurel32
    if (sat) {
2638 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2639 8142cddd aurel32
    }
2640 8142cddd aurel32
}
2641 8142cddd aurel32
2642 8142cddd aurel32
void helper_vsum4shs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2643 8142cddd aurel32
{
2644 8142cddd aurel32
    int sat = 0;
2645 8142cddd aurel32
    int i;
2646 8142cddd aurel32
2647 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2648 8142cddd aurel32
        int64_t t = (int64_t)b->s32[i];
2649 8142cddd aurel32
        t += a->s16[2*i] + a->s16[2*i+1];
2650 8142cddd aurel32
        r->s32[i] = cvtsdsw(t, &sat);
2651 8142cddd aurel32
    }
2652 8142cddd aurel32
2653 8142cddd aurel32
    if (sat) {
2654 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2655 8142cddd aurel32
    }
2656 8142cddd aurel32
}
2657 8142cddd aurel32
2658 8142cddd aurel32
void helper_vsum4ubs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2659 8142cddd aurel32
{
2660 8142cddd aurel32
    int i, j;
2661 8142cddd aurel32
    int sat = 0;
2662 8142cddd aurel32
2663 8142cddd aurel32
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2664 8142cddd aurel32
        uint64_t t = (uint64_t)b->u32[i];
2665 8142cddd aurel32
        for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
2666 8142cddd aurel32
            t += a->u8[4*i+j];
2667 8142cddd aurel32
        }
2668 8142cddd aurel32
        r->u32[i] = cvtuduw(t, &sat);
2669 8142cddd aurel32
    }
2670 8142cddd aurel32
2671 8142cddd aurel32
    if (sat) {
2672 8142cddd aurel32
        env->vscr |= (1 << VSCR_SAT);
2673 8142cddd aurel32
    }
2674 8142cddd aurel32
}
2675 8142cddd aurel32
2676 79f85c3a aurel32
#if defined(WORDS_BIGENDIAN)
2677 79f85c3a aurel32
#define UPKHI 1
2678 79f85c3a aurel32
#define UPKLO 0
2679 79f85c3a aurel32
#else
2680 79f85c3a aurel32
#define UPKHI 0
2681 79f85c3a aurel32
#define UPKLO 1
2682 79f85c3a aurel32
#endif
2683 79f85c3a aurel32
#define VUPKPX(suffix, hi)                                      \
2684 79f85c3a aurel32
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)       \
2685 79f85c3a aurel32
    {                                                           \
2686 79f85c3a aurel32
        int i;                                                  \
2687 79f85c3a aurel32
        ppc_avr_t result;                                       \
2688 79f85c3a aurel32
        for (i = 0; i < ARRAY_SIZE(r->u32); i++) {              \
2689 79f85c3a aurel32
            uint16_t e = b->u16[hi ? i : i+4];                  \
2690 79f85c3a aurel32
            uint8_t a = (e >> 15) ? 0xff : 0;                   \
2691 79f85c3a aurel32
            uint8_t r = (e >> 10) & 0x1f;                       \
2692 79f85c3a aurel32
            uint8_t g = (e >> 5) & 0x1f;                        \
2693 79f85c3a aurel32
            uint8_t b = e & 0x1f;                               \
2694 79f85c3a aurel32
            result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
2695 79f85c3a aurel32
        }                                                               \
2696 79f85c3a aurel32
        *r = result;                                                    \
2697 79f85c3a aurel32
    }
2698 79f85c3a aurel32
VUPKPX(lpx, UPKLO)
2699 79f85c3a aurel32
VUPKPX(hpx, UPKHI)
2700 79f85c3a aurel32
#undef VUPKPX
2701 79f85c3a aurel32
2702 6cf1c6e5 aurel32
#define VUPK(suffix, unpacked, packee, hi)                              \
2703 6cf1c6e5 aurel32
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
2704 6cf1c6e5 aurel32
    {                                                                   \
2705 6cf1c6e5 aurel32
        int i;                                                          \
2706 6cf1c6e5 aurel32
        ppc_avr_t result;                                               \
2707 6cf1c6e5 aurel32
        if (hi) {                                                       \
2708 6cf1c6e5 aurel32
            for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
2709 6cf1c6e5 aurel32
                result.unpacked[i] = b->packee[i];                      \
2710 6cf1c6e5 aurel32
            }                                                           \
2711 6cf1c6e5 aurel32
        } else {                                                        \
2712 6cf1c6e5 aurel32
            for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); i++) { \
2713 6cf1c6e5 aurel32
                result.unpacked[i-ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
2714 6cf1c6e5 aurel32
            }                                                           \
2715 6cf1c6e5 aurel32
        }                                                               \
2716 6cf1c6e5 aurel32
        *r = result;                                                    \
2717 6cf1c6e5 aurel32
    }
2718 6cf1c6e5 aurel32
VUPK(hsb, s16, s8, UPKHI)
2719 6cf1c6e5 aurel32
VUPK(hsh, s32, s16, UPKHI)
2720 6cf1c6e5 aurel32
VUPK(lsb, s16, s8, UPKLO)
2721 6cf1c6e5 aurel32
VUPK(lsh, s32, s16, UPKLO)
2722 6cf1c6e5 aurel32
#undef VUPK
2723 79f85c3a aurel32
#undef UPKHI
2724 79f85c3a aurel32
#undef UPKLO
2725 79f85c3a aurel32
2726 d6a46fe8 aurel32
#undef VECTOR_FOR_INORDER_I
2727 d6a46fe8 aurel32
#undef HI_IDX
2728 d6a46fe8 aurel32
#undef LO_IDX
2729 d6a46fe8 aurel32
2730 d6a46fe8 aurel32
/*****************************************************************************/
2731 0487d6a8 j_mayer
/* SPE extension helpers */
2732 0487d6a8 j_mayer
/* Use a table to make this quicker */
2733 0487d6a8 j_mayer
static uint8_t hbrev[16] = {
2734 0487d6a8 j_mayer
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
2735 0487d6a8 j_mayer
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
2736 0487d6a8 j_mayer
};
2737 0487d6a8 j_mayer
2738 b068d6a7 j_mayer
static always_inline uint8_t byte_reverse (uint8_t val)
2739 0487d6a8 j_mayer
{
2740 0487d6a8 j_mayer
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
2741 0487d6a8 j_mayer
}
2742 0487d6a8 j_mayer
2743 b068d6a7 j_mayer
static always_inline uint32_t word_reverse (uint32_t val)
2744 0487d6a8 j_mayer
{
2745 0487d6a8 j_mayer
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
2746 0487d6a8 j_mayer
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
2747 0487d6a8 j_mayer
}
2748 0487d6a8 j_mayer
2749 3cd7d1dd j_mayer
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
2750 57951c27 aurel32
target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
2751 0487d6a8 j_mayer
{
2752 0487d6a8 j_mayer
    uint32_t a, b, d, mask;
2753 0487d6a8 j_mayer
2754 3cd7d1dd j_mayer
    mask = UINT32_MAX >> (32 - MASKBITS);
2755 57951c27 aurel32
    a = arg1 & mask;
2756 57951c27 aurel32
    b = arg2 & mask;
2757 3cd7d1dd j_mayer
    d = word_reverse(1 + word_reverse(a | ~b));
2758 57951c27 aurel32
    return (arg1 & ~mask) | (d & b);
2759 0487d6a8 j_mayer
}
2760 0487d6a8 j_mayer
2761 57951c27 aurel32
uint32_t helper_cntlsw32 (uint32_t val)
2762 0487d6a8 j_mayer
{
2763 0487d6a8 j_mayer
    if (val & 0x80000000)
2764 603fccce j_mayer
        return clz32(~val);
2765 0487d6a8 j_mayer
    else
2766 603fccce j_mayer
        return clz32(val);
2767 0487d6a8 j_mayer
}
2768 0487d6a8 j_mayer
2769 57951c27 aurel32
uint32_t helper_cntlzw32 (uint32_t val)
2770 0487d6a8 j_mayer
{
2771 603fccce j_mayer
    return clz32(val);
2772 0487d6a8 j_mayer
}
2773 0487d6a8 j_mayer
2774 1c97856d aurel32
/* Single-precision floating-point conversions */
2775 1c97856d aurel32
static always_inline uint32_t efscfsi (uint32_t val)
2776 0487d6a8 j_mayer
{
2777 0ca9d380 aurel32
    CPU_FloatU u;
2778 0487d6a8 j_mayer
2779 0487d6a8 j_mayer
    u.f = int32_to_float32(val, &env->spe_status);
2780 0487d6a8 j_mayer
2781 0ca9d380 aurel32
    return u.l;
2782 0487d6a8 j_mayer
}
2783 0487d6a8 j_mayer
2784 1c97856d aurel32
static always_inline uint32_t efscfui (uint32_t val)
2785 0487d6a8 j_mayer
{
2786 0ca9d380 aurel32
    CPU_FloatU u;
2787 0487d6a8 j_mayer
2788 0487d6a8 j_mayer
    u.f = uint32_to_float32(val, &env->spe_status);
2789 0487d6a8 j_mayer
2790 0ca9d380 aurel32
    return u.l;
2791 0487d6a8 j_mayer
}
2792 0487d6a8 j_mayer
2793 1c97856d aurel32
static always_inline int32_t efsctsi (uint32_t val)
2794 0487d6a8 j_mayer
{
2795 0ca9d380 aurel32
    CPU_FloatU u;
2796 0487d6a8 j_mayer
2797 0ca9d380 aurel32
    u.l = val;
2798 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2799 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2800 0487d6a8 j_mayer
        return 0;
2801 0487d6a8 j_mayer
2802 0487d6a8 j_mayer
    return float32_to_int32(u.f, &env->spe_status);
2803 0487d6a8 j_mayer
}
2804 0487d6a8 j_mayer
2805 1c97856d aurel32
static always_inline uint32_t efsctui (uint32_t val)
2806 0487d6a8 j_mayer
{
2807 0ca9d380 aurel32
    CPU_FloatU u;
2808 0487d6a8 j_mayer
2809 0ca9d380 aurel32
    u.l = val;
2810 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2811 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2812 0487d6a8 j_mayer
        return 0;
2813 0487d6a8 j_mayer
2814 0487d6a8 j_mayer
    return float32_to_uint32(u.f, &env->spe_status);
2815 0487d6a8 j_mayer
}
2816 0487d6a8 j_mayer
2817 1c97856d aurel32
static always_inline uint32_t efsctsiz (uint32_t val)
2818 0487d6a8 j_mayer
{
2819 0ca9d380 aurel32
    CPU_FloatU u;
2820 0487d6a8 j_mayer
2821 0ca9d380 aurel32
    u.l = val;
2822 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2823 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2824 0487d6a8 j_mayer
        return 0;
2825 0487d6a8 j_mayer
2826 0487d6a8 j_mayer
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2827 0487d6a8 j_mayer
}
2828 0487d6a8 j_mayer
2829 1c97856d aurel32
static always_inline uint32_t efsctuiz (uint32_t val)
2830 0487d6a8 j_mayer
{
2831 0ca9d380 aurel32
    CPU_FloatU u;
2832 0487d6a8 j_mayer
2833 0ca9d380 aurel32
    u.l = val;
2834 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2835 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2836 0487d6a8 j_mayer
        return 0;
2837 0487d6a8 j_mayer
2838 0487d6a8 j_mayer
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2839 0487d6a8 j_mayer
}
2840 0487d6a8 j_mayer
2841 1c97856d aurel32
static always_inline uint32_t efscfsf (uint32_t val)
2842 0487d6a8 j_mayer
{
2843 0ca9d380 aurel32
    CPU_FloatU u;
2844 0487d6a8 j_mayer
    float32 tmp;
2845 0487d6a8 j_mayer
2846 0487d6a8 j_mayer
    u.f = int32_to_float32(val, &env->spe_status);
2847 0487d6a8 j_mayer
    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
2848 0487d6a8 j_mayer
    u.f = float32_div(u.f, tmp, &env->spe_status);
2849 0487d6a8 j_mayer
2850 0ca9d380 aurel32
    return u.l;
2851 0487d6a8 j_mayer
}
2852 0487d6a8 j_mayer
2853 1c97856d aurel32
static always_inline uint32_t efscfuf (uint32_t val)
2854 0487d6a8 j_mayer
{
2855 0ca9d380 aurel32
    CPU_FloatU u;
2856 0487d6a8 j_mayer
    float32 tmp;
2857 0487d6a8 j_mayer
2858 0487d6a8 j_mayer
    u.f = uint32_to_float32(val, &env->spe_status);
2859 0487d6a8 j_mayer
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2860 0487d6a8 j_mayer
    u.f = float32_div(u.f, tmp, &env->spe_status);
2861 0487d6a8 j_mayer
2862 0ca9d380 aurel32
    return u.l;
2863 0487d6a8 j_mayer
}
2864 0487d6a8 j_mayer
2865 1c97856d aurel32
static always_inline uint32_t efsctsf (uint32_t val)
2866 0487d6a8 j_mayer
{
2867 0ca9d380 aurel32
    CPU_FloatU u;
2868 0487d6a8 j_mayer
    float32 tmp;
2869 0487d6a8 j_mayer
2870 0ca9d380 aurel32
    u.l = val;
2871 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2872 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2873 0487d6a8 j_mayer
        return 0;
2874 0487d6a8 j_mayer
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2875 0487d6a8 j_mayer
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2876 0487d6a8 j_mayer
2877 0487d6a8 j_mayer
    return float32_to_int32(u.f, &env->spe_status);
2878 0487d6a8 j_mayer
}
2879 0487d6a8 j_mayer
2880 1c97856d aurel32
static always_inline uint32_t efsctuf (uint32_t val)
2881 0487d6a8 j_mayer
{
2882 0ca9d380 aurel32
    CPU_FloatU u;
2883 0487d6a8 j_mayer
    float32 tmp;
2884 0487d6a8 j_mayer
2885 0ca9d380 aurel32
    u.l = val;
2886 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2887 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2888 0487d6a8 j_mayer
        return 0;
2889 0487d6a8 j_mayer
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2890 0487d6a8 j_mayer
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2891 0487d6a8 j_mayer
2892 0487d6a8 j_mayer
    return float32_to_uint32(u.f, &env->spe_status);
2893 0487d6a8 j_mayer
}
2894 0487d6a8 j_mayer
2895 1c97856d aurel32
#define HELPER_SPE_SINGLE_CONV(name)                                          \
2896 1c97856d aurel32
uint32_t helper_e##name (uint32_t val)                                        \
2897 1c97856d aurel32
{                                                                             \
2898 1c97856d aurel32
    return e##name(val);                                                      \
2899 1c97856d aurel32
}
2900 1c97856d aurel32
/* efscfsi */
2901 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsi);
2902 1c97856d aurel32
/* efscfui */
2903 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfui);
2904 1c97856d aurel32
/* efscfuf */
2905 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfuf);
2906 1c97856d aurel32
/* efscfsf */
2907 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsf);
2908 1c97856d aurel32
/* efsctsi */
2909 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsi);
2910 1c97856d aurel32
/* efsctui */
2911 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctui);
2912 1c97856d aurel32
/* efsctsiz */
2913 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsiz);
2914 1c97856d aurel32
/* efsctuiz */
2915 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuiz);
2916 1c97856d aurel32
/* efsctsf */
2917 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsf);
2918 1c97856d aurel32
/* efsctuf */
2919 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuf);
2920 1c97856d aurel32
2921 1c97856d aurel32
#define HELPER_SPE_VECTOR_CONV(name)                                          \
2922 1c97856d aurel32
uint64_t helper_ev##name (uint64_t val)                                       \
2923 1c97856d aurel32
{                                                                             \
2924 1c97856d aurel32
    return ((uint64_t)e##name(val >> 32) << 32) |                             \
2925 1c97856d aurel32
            (uint64_t)e##name(val);                                           \
2926 0487d6a8 j_mayer
}
2927 1c97856d aurel32
/* evfscfsi */
2928 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsi);
2929 1c97856d aurel32
/* evfscfui */
2930 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfui);
2931 1c97856d aurel32
/* evfscfuf */
2932 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfuf);
2933 1c97856d aurel32
/* evfscfsf */
2934 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsf);
2935 1c97856d aurel32
/* evfsctsi */
2936 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsi);
2937 1c97856d aurel32
/* evfsctui */
2938 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctui);
2939 1c97856d aurel32
/* evfsctsiz */
2940 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsiz);
2941 1c97856d aurel32
/* evfsctuiz */
2942 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuiz);
2943 1c97856d aurel32
/* evfsctsf */
2944 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsf);
2945 1c97856d aurel32
/* evfsctuf */
2946 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuf);
2947 0487d6a8 j_mayer
2948 1c97856d aurel32
/* Single-precision floating-point arithmetic */
2949 1c97856d aurel32
static always_inline uint32_t efsadd (uint32_t op1, uint32_t op2)
2950 0487d6a8 j_mayer
{
2951 1c97856d aurel32
    CPU_FloatU u1, u2;
2952 1c97856d aurel32
    u1.l = op1;
2953 1c97856d aurel32
    u2.l = op2;
2954 1c97856d aurel32
    u1.f = float32_add(u1.f, u2.f, &env->spe_status);
2955 1c97856d aurel32
    return u1.l;
2956 0487d6a8 j_mayer
}
2957 0487d6a8 j_mayer
2958 1c97856d aurel32
static always_inline uint32_t efssub (uint32_t op1, uint32_t op2)
2959 0487d6a8 j_mayer
{
2960 1c97856d aurel32
    CPU_FloatU u1, u2;
2961 1c97856d aurel32
    u1.l = op1;
2962 1c97856d aurel32
    u2.l = op2;
2963 1c97856d aurel32
    u1.f = float32_sub(u1.f, u2.f, &env->spe_status);
2964 1c97856d aurel32
    return u1.l;
2965 0487d6a8 j_mayer
}
2966 0487d6a8 j_mayer
2967 1c97856d aurel32
static always_inline uint32_t efsmul (uint32_t op1, uint32_t op2)
2968 0487d6a8 j_mayer
{
2969 1c97856d aurel32
    CPU_FloatU u1, u2;
2970 1c97856d aurel32
    u1.l = op1;
2971 1c97856d aurel32
    u2.l = op2;
2972 1c97856d aurel32
    u1.f = float32_mul(u1.f, u2.f, &env->spe_status);
2973 1c97856d aurel32
    return u1.l;
2974 0487d6a8 j_mayer
}
2975 0487d6a8 j_mayer
2976 1c97856d aurel32
static always_inline uint32_t efsdiv (uint32_t op1, uint32_t op2)
2977 0487d6a8 j_mayer
{
2978 1c97856d aurel32
    CPU_FloatU u1, u2;
2979 1c97856d aurel32
    u1.l = op1;
2980 1c97856d aurel32
    u2.l = op2;
2981 1c97856d aurel32
    u1.f = float32_div(u1.f, u2.f, &env->spe_status);
2982 1c97856d aurel32
    return u1.l;
2983 0487d6a8 j_mayer
}
2984 0487d6a8 j_mayer
2985 1c97856d aurel32
#define HELPER_SPE_SINGLE_ARITH(name)                                         \
2986 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
2987 1c97856d aurel32
{                                                                             \
2988 1c97856d aurel32
    return e##name(op1, op2);                                                 \
2989 1c97856d aurel32
}
2990 1c97856d aurel32
/* efsadd */
2991 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsadd);
2992 1c97856d aurel32
/* efssub */
2993 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fssub);
2994 1c97856d aurel32
/* efsmul */
2995 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsmul);
2996 1c97856d aurel32
/* efsdiv */
2997 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsdiv);
2998 1c97856d aurel32
2999 1c97856d aurel32
#define HELPER_SPE_VECTOR_ARITH(name)                                         \
3000 1c97856d aurel32
uint64_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3001 1c97856d aurel32
{                                                                             \
3002 1c97856d aurel32
    return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |                  \
3003 1c97856d aurel32
            (uint64_t)e##name(op1, op2);                                      \
3004 1c97856d aurel32
}
3005 1c97856d aurel32
/* evfsadd */
3006 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsadd);
3007 1c97856d aurel32
/* evfssub */
3008 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fssub);
3009 1c97856d aurel32
/* evfsmul */
3010 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsmul);
3011 1c97856d aurel32
/* evfsdiv */
3012 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsdiv);
3013 1c97856d aurel32
3014 1c97856d aurel32
/* Single-precision floating-point comparisons */
3015 1c97856d aurel32
static always_inline uint32_t efststlt (uint32_t op1, uint32_t op2)
3016 0487d6a8 j_mayer
{
3017 1c97856d aurel32
    CPU_FloatU u1, u2;
3018 1c97856d aurel32
    u1.l = op1;
3019 1c97856d aurel32
    u2.l = op2;
3020 1c97856d aurel32
    return float32_lt(u1.f, u2.f, &env->spe_status) ? 4 : 0;
3021 0487d6a8 j_mayer
}
3022 0487d6a8 j_mayer
3023 1c97856d aurel32
static always_inline uint32_t efststgt (uint32_t op1, uint32_t op2)
3024 0487d6a8 j_mayer
{
3025 1c97856d aurel32
    CPU_FloatU u1, u2;
3026 1c97856d aurel32
    u1.l = op1;
3027 1c97856d aurel32
    u2.l = op2;
3028 1c97856d aurel32
    return float32_le(u1.f, u2.f, &env->spe_status) ? 0 : 4;
3029 0487d6a8 j_mayer
}
3030 0487d6a8 j_mayer
3031 1c97856d aurel32
static always_inline uint32_t efststeq (uint32_t op1, uint32_t op2)
3032 0487d6a8 j_mayer
{
3033 1c97856d aurel32
    CPU_FloatU u1, u2;
3034 1c97856d aurel32
    u1.l = op1;
3035 1c97856d aurel32
    u2.l = op2;
3036 1c97856d aurel32
    return float32_eq(u1.f, u2.f, &env->spe_status) ? 4 : 0;
3037 0487d6a8 j_mayer
}
3038 0487d6a8 j_mayer
3039 1c97856d aurel32
static always_inline uint32_t efscmplt (uint32_t op1, uint32_t op2)
3040 0487d6a8 j_mayer
{
3041 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3042 1c97856d aurel32
    return efststlt(op1, op2);
3043 0487d6a8 j_mayer
}
3044 0487d6a8 j_mayer
3045 1c97856d aurel32
static always_inline uint32_t efscmpgt (uint32_t op1, uint32_t op2)
3046 0487d6a8 j_mayer
{
3047 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3048 1c97856d aurel32
    return efststgt(op1, op2);
3049 0487d6a8 j_mayer
}
3050 0487d6a8 j_mayer
3051 1c97856d aurel32
static always_inline uint32_t efscmpeq (uint32_t op1, uint32_t op2)
3052 0487d6a8 j_mayer
{
3053 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3054 1c97856d aurel32
    return efststeq(op1, op2);
3055 0487d6a8 j_mayer
}
3056 0487d6a8 j_mayer
3057 1c97856d aurel32
#define HELPER_SINGLE_SPE_CMP(name)                                           \
3058 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
3059 1c97856d aurel32
{                                                                             \
3060 1c97856d aurel32
    return e##name(op1, op2) << 2;                                            \
3061 1c97856d aurel32
}
3062 1c97856d aurel32
/* efststlt */
3063 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststlt);
3064 1c97856d aurel32
/* efststgt */
3065 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststgt);
3066 1c97856d aurel32
/* efststeq */
3067 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststeq);
3068 1c97856d aurel32
/* efscmplt */
3069 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmplt);
3070 1c97856d aurel32
/* efscmpgt */
3071 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpgt);
3072 1c97856d aurel32
/* efscmpeq */
3073 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpeq);
3074 1c97856d aurel32
3075 1c97856d aurel32
static always_inline uint32_t evcmp_merge (int t0, int t1)
3076 0487d6a8 j_mayer
{
3077 1c97856d aurel32
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
3078 0487d6a8 j_mayer
}
3079 0487d6a8 j_mayer
3080 1c97856d aurel32
#define HELPER_VECTOR_SPE_CMP(name)                                           \
3081 1c97856d aurel32
uint32_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3082 1c97856d aurel32
{                                                                             \
3083 1c97856d aurel32
    return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2));     \
3084 0487d6a8 j_mayer
}
3085 1c97856d aurel32
/* evfststlt */
3086 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststlt);
3087 1c97856d aurel32
/* evfststgt */
3088 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststgt);
3089 1c97856d aurel32
/* evfststeq */
3090 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststeq);
3091 1c97856d aurel32
/* evfscmplt */
3092 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmplt);
3093 1c97856d aurel32
/* evfscmpgt */
3094 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpgt);
3095 1c97856d aurel32
/* evfscmpeq */
3096 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpeq);
3097 0487d6a8 j_mayer
3098 1c97856d aurel32
/* Double-precision floating-point conversion */
3099 1c97856d aurel32
uint64_t helper_efdcfsi (uint32_t val)
3100 0487d6a8 j_mayer
{
3101 1c97856d aurel32
    CPU_DoubleU u;
3102 1c97856d aurel32
3103 1c97856d aurel32
    u.d = int32_to_float64(val, &env->spe_status);
3104 1c97856d aurel32
3105 1c97856d aurel32
    return u.ll;
3106 0487d6a8 j_mayer
}
3107 0487d6a8 j_mayer
3108 1c97856d aurel32
uint64_t helper_efdcfsid (uint64_t val)
3109 0487d6a8 j_mayer
{
3110 0ca9d380 aurel32
    CPU_DoubleU u;
3111 0487d6a8 j_mayer
3112 0ca9d380 aurel32
    u.d = int64_to_float64(val, &env->spe_status);
3113 0487d6a8 j_mayer
3114 0ca9d380 aurel32
    return u.ll;
3115 0487d6a8 j_mayer
}
3116 0487d6a8 j_mayer
3117 1c97856d aurel32
uint64_t helper_efdcfui (uint32_t val)
3118 1c97856d aurel32
{
3119 1c97856d aurel32
    CPU_DoubleU u;
3120 1c97856d aurel32
3121 1c97856d aurel32
    u.d = uint32_to_float64(val, &env->spe_status);
3122 1c97856d aurel32
3123 1c97856d aurel32
    return u.ll;
3124 1c97856d aurel32
}
3125 1c97856d aurel32
3126 1c97856d aurel32
uint64_t helper_efdcfuid (uint64_t val)
3127 0487d6a8 j_mayer
{
3128 0ca9d380 aurel32
    CPU_DoubleU u;
3129 0487d6a8 j_mayer
3130 0ca9d380 aurel32
    u.d = uint64_to_float64(val, &env->spe_status);
3131 0487d6a8 j_mayer
3132 0ca9d380 aurel32
    return u.ll;
3133 0487d6a8 j_mayer
}
3134 0487d6a8 j_mayer
3135 1c97856d aurel32
uint32_t helper_efdctsi (uint64_t val)
3136 0487d6a8 j_mayer
{
3137 0ca9d380 aurel32
    CPU_DoubleU u;
3138 0487d6a8 j_mayer
3139 0ca9d380 aurel32
    u.ll = val;
3140 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3141 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3142 0487d6a8 j_mayer
        return 0;
3143 0487d6a8 j_mayer
3144 1c97856d aurel32
    return float64_to_int32(u.d, &env->spe_status);
3145 0487d6a8 j_mayer
}
3146 0487d6a8 j_mayer
3147 1c97856d aurel32
uint32_t helper_efdctui (uint64_t val)
3148 0487d6a8 j_mayer
{
3149 0ca9d380 aurel32
    CPU_DoubleU u;
3150 0487d6a8 j_mayer
3151 0ca9d380 aurel32
    u.ll = val;
3152 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3153 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3154 0487d6a8 j_mayer
        return 0;
3155 0487d6a8 j_mayer
3156 1c97856d aurel32
    return float64_to_uint32(u.d, &env->spe_status);
3157 0487d6a8 j_mayer
}
3158 0487d6a8 j_mayer
3159 1c97856d aurel32
uint32_t helper_efdctsiz (uint64_t val)
3160 0487d6a8 j_mayer
{
3161 0ca9d380 aurel32
    CPU_DoubleU u;
3162 0487d6a8 j_mayer
3163 0ca9d380 aurel32
    u.ll = val;
3164 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3165 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3166 0487d6a8 j_mayer
        return 0;
3167 0487d6a8 j_mayer
3168 1c97856d aurel32
    return float64_to_int32_round_to_zero(u.d, &env->spe_status);
3169 0487d6a8 j_mayer
}
3170 0487d6a8 j_mayer
3171 1c97856d aurel32
uint64_t helper_efdctsidz (uint64_t val)
3172 0487d6a8 j_mayer
{
3173 0ca9d380 aurel32
    CPU_DoubleU u;
3174 0487d6a8 j_mayer
3175 0ca9d380 aurel32
    u.ll = val;
3176 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3177 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3178 0487d6a8 j_mayer
        return 0;
3179 0487d6a8 j_mayer
3180 1c97856d aurel32
    return float64_to_int64_round_to_zero(u.d, &env->spe_status);
3181 0487d6a8 j_mayer
}
3182 0487d6a8 j_mayer
3183 1c97856d aurel32
uint32_t helper_efdctuiz (uint64_t val)
3184 0487d6a8 j_mayer
{
3185 1c97856d aurel32
    CPU_DoubleU u;
3186 0487d6a8 j_mayer
3187 1c97856d aurel32
    u.ll = val;
3188 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
3189 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3190 1c97856d aurel32
        return 0;
3191 0487d6a8 j_mayer
3192 1c97856d aurel32
    return float64_to_uint32_round_to_zero(u.d, &env->spe_status);
3193 0487d6a8 j_mayer
}
3194 0487d6a8 j_mayer
3195 1c97856d aurel32
uint64_t helper_efdctuidz (uint64_t val)
3196 0487d6a8 j_mayer
{
3197 1c97856d aurel32
    CPU_DoubleU u;
3198 0487d6a8 j_mayer
3199 1c97856d aurel32
    u.ll = val;
3200 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
3201 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3202 1c97856d aurel32
        return 0;
3203 0487d6a8 j_mayer
3204 1c97856d aurel32
    return float64_to_uint64_round_to_zero(u.d, &env->spe_status);
3205 0487d6a8 j_mayer
}
3206 0487d6a8 j_mayer
3207 1c97856d aurel32
uint64_t helper_efdcfsf (uint32_t val)
3208 0487d6a8 j_mayer
{
3209 0ca9d380 aurel32
    CPU_DoubleU u;
3210 0487d6a8 j_mayer
    float64 tmp;
3211 0487d6a8 j_mayer
3212 0ca9d380 aurel32
    u.d = int32_to_float64(val, &env->spe_status);
3213 0487d6a8 j_mayer
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
3214 0ca9d380 aurel32
    u.d = float64_div(u.d, tmp, &env->spe_status);
3215 0487d6a8 j_mayer
3216 0ca9d380 aurel32
    return u.ll;
3217 0487d6a8 j_mayer
}
3218 0487d6a8 j_mayer
3219 1c97856d aurel32
uint64_t helper_efdcfuf (uint32_t val)
3220 0487d6a8 j_mayer
{
3221 0ca9d380 aurel32
    CPU_DoubleU u;
3222 0487d6a8 j_mayer
    float64 tmp;
3223 0487d6a8 j_mayer
3224 0ca9d380 aurel32
    u.d = uint32_to_float64(val, &env->spe_status);
3225 0487d6a8 j_mayer
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
3226 0ca9d380 aurel32
    u.d = float64_div(u.d, tmp, &env->spe_status);
3227 0487d6a8 j_mayer
3228 0ca9d380 aurel32
    return u.ll;
3229 0487d6a8 j_mayer
}
3230 0487d6a8 j_mayer
3231 1c97856d aurel32
uint32_t helper_efdctsf (uint64_t val)
3232 0487d6a8 j_mayer
{
3233 0ca9d380 aurel32
    CPU_DoubleU u;
3234 0487d6a8 j_mayer
    float64 tmp;
3235 0487d6a8 j_mayer
3236 0ca9d380 aurel32
    u.ll = val;
3237 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3238 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3239 0487d6a8 j_mayer
        return 0;
3240 0487d6a8 j_mayer
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
3241 0ca9d380 aurel32
    u.d = float64_mul(u.d, tmp, &env->spe_status);
3242 0487d6a8 j_mayer
3243 0ca9d380 aurel32
    return float64_to_int32(u.d, &env->spe_status);
3244 0487d6a8 j_mayer
}
3245 0487d6a8 j_mayer
3246 1c97856d aurel32
uint32_t helper_efdctuf (uint64_t val)
3247 0487d6a8 j_mayer
{
3248 0ca9d380 aurel32
    CPU_DoubleU u;
3249 0487d6a8 j_mayer
    float64 tmp;
3250 0487d6a8 j_mayer
3251 0ca9d380 aurel32
    u.ll = val;
3252 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
3253 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
3254 0487d6a8 j_mayer
        return 0;
3255 0487d6a8 j_mayer
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
3256 0ca9d380 aurel32
    u.d = float64_mul(u.d, tmp, &env->spe_status);
3257 0487d6a8 j_mayer
3258 0ca9d380 aurel32
    return float64_to_uint32(u.d, &env->spe_status);
3259 0487d6a8 j_mayer
}
3260 0487d6a8 j_mayer
3261 1c97856d aurel32
uint32_t helper_efscfd (uint64_t val)
3262 0487d6a8 j_mayer
{
3263 0ca9d380 aurel32
    CPU_DoubleU u1;
3264 0ca9d380 aurel32
    CPU_FloatU u2;
3265 0487d6a8 j_mayer
3266 0ca9d380 aurel32
    u1.ll = val;
3267 0ca9d380 aurel32
    u2.f = float64_to_float32(u1.d, &env->spe_status);
3268 0487d6a8 j_mayer
3269 0ca9d380 aurel32
    return u2.l;
3270 0487d6a8 j_mayer
}
3271 0487d6a8 j_mayer
3272 1c97856d aurel32
uint64_t helper_efdcfs (uint32_t val)
3273 0487d6a8 j_mayer
{
3274 0ca9d380 aurel32
    CPU_DoubleU u2;
3275 0ca9d380 aurel32
    CPU_FloatU u1;
3276 0487d6a8 j_mayer
3277 0ca9d380 aurel32
    u1.l = val;
3278 0ca9d380 aurel32
    u2.d = float32_to_float64(u1.f, &env->spe_status);
3279 0487d6a8 j_mayer
3280 0ca9d380 aurel32
    return u2.ll;
3281 0487d6a8 j_mayer
}
3282 0487d6a8 j_mayer
3283 1c97856d aurel32
/* Double precision fixed-point arithmetic */
3284 1c97856d aurel32
uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
3285 0487d6a8 j_mayer
{
3286 1c97856d aurel32
    CPU_DoubleU u1, u2;
3287 1c97856d aurel32
    u1.ll = op1;
3288 1c97856d aurel32
    u2.ll = op2;
3289 1c97856d aurel32
    u1.d = float64_add(u1.d, u2.d, &env->spe_status);
3290 1c97856d aurel32
    return u1.ll;
3291 0487d6a8 j_mayer
}
3292 0487d6a8 j_mayer
3293 1c97856d aurel32
uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
3294 0487d6a8 j_mayer
{
3295 1c97856d aurel32
    CPU_DoubleU u1, u2;
3296 1c97856d aurel32
    u1.ll = op1;
3297 1c97856d aurel32
    u2.ll = op2;
3298 1c97856d aurel32
    u1.d = float64_sub(u1.d, u2.d, &env->spe_status);
3299 1c97856d aurel32
    return u1.ll;
3300 0487d6a8 j_mayer
}
3301 0487d6a8 j_mayer
3302 1c97856d aurel32
uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
3303 0487d6a8 j_mayer
{
3304 1c97856d aurel32
    CPU_DoubleU u1, u2;
3305 1c97856d aurel32
    u1.ll = op1;
3306 1c97856d aurel32
    u2.ll = op2;
3307 1c97856d aurel32
    u1.d = float64_mul(u1.d, u2.d, &env->spe_status);
3308 1c97856d aurel32
    return u1.ll;
3309 0487d6a8 j_mayer
}
3310 0487d6a8 j_mayer
3311 1c97856d aurel32
uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
3312 0487d6a8 j_mayer
{
3313 1c97856d aurel32
    CPU_DoubleU u1, u2;
3314 1c97856d aurel32
    u1.ll = op1;
3315 1c97856d aurel32
    u2.ll = op2;
3316 1c97856d aurel32
    u1.d = float64_div(u1.d, u2.d, &env->spe_status);
3317 1c97856d aurel32
    return u1.ll;
3318 0487d6a8 j_mayer
}
3319 0487d6a8 j_mayer
3320 1c97856d aurel32
/* Double precision floating point helpers */
3321 1c97856d aurel32
uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
3322 0487d6a8 j_mayer
{
3323 1c97856d aurel32
    CPU_DoubleU u1, u2;
3324 1c97856d aurel32
    u1.ll = op1;
3325 1c97856d aurel32
    u2.ll = op2;
3326 1c97856d aurel32
    return float64_lt(u1.d, u2.d, &env->spe_status) ? 4 : 0;
3327 0487d6a8 j_mayer
}
3328 0487d6a8 j_mayer
3329 1c97856d aurel32
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
3330 0487d6a8 j_mayer
{
3331 1c97856d aurel32
    CPU_DoubleU u1, u2;
3332 1c97856d aurel32
    u1.ll = op1;
3333 1c97856d aurel32
    u2.ll = op2;
3334 1c97856d aurel32
    return float64_le(u1.d, u2.d, &env->spe_status) ? 0 : 4;
3335 0487d6a8 j_mayer
}
3336 0487d6a8 j_mayer
3337 1c97856d aurel32
uint32_t helper_efdtsteq (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
    return float64_eq(u1.d, u2.d, &env->spe_status) ? 4 : 0;
3343 0487d6a8 j_mayer
}
3344 0487d6a8 j_mayer
3345 1c97856d aurel32
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
3346 0487d6a8 j_mayer
{
3347 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3348 1c97856d aurel32
    return helper_efdtstlt(op1, op2);
3349 0487d6a8 j_mayer
}
3350 0487d6a8 j_mayer
3351 1c97856d aurel32
uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
3352 1c97856d aurel32
{
3353 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3354 1c97856d aurel32
    return helper_efdtstgt(op1, op2);
3355 1c97856d aurel32
}
3356 0487d6a8 j_mayer
3357 1c97856d aurel32
uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
3358 1c97856d aurel32
{
3359 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3360 1c97856d aurel32
    return helper_efdtsteq(op1, op2);
3361 1c97856d aurel32
}
3362 0487d6a8 j_mayer
3363 fdabc366 bellard
/*****************************************************************************/
3364 fdabc366 bellard
/* Softmmu support */
3365 fdabc366 bellard
#if !defined (CONFIG_USER_ONLY)
3366 fdabc366 bellard
3367 fdabc366 bellard
#define MMUSUFFIX _mmu
3368 fdabc366 bellard
3369 fdabc366 bellard
#define SHIFT 0
3370 fdabc366 bellard
#include "softmmu_template.h"
3371 fdabc366 bellard
3372 fdabc366 bellard
#define SHIFT 1
3373 fdabc366 bellard
#include "softmmu_template.h"
3374 fdabc366 bellard
3375 fdabc366 bellard
#define SHIFT 2
3376 fdabc366 bellard
#include "softmmu_template.h"
3377 fdabc366 bellard
3378 fdabc366 bellard
#define SHIFT 3
3379 fdabc366 bellard
#include "softmmu_template.h"
3380 fdabc366 bellard
3381 fdabc366 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
3382 fdabc366 bellard
   NULL, it means that the function was called in C code (i.e. not
3383 fdabc366 bellard
   from generated code or from helper.c) */
3384 fdabc366 bellard
/* XXX: fix it to restore all registers */
3385 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3386 fdabc366 bellard
{
3387 fdabc366 bellard
    TranslationBlock *tb;
3388 fdabc366 bellard
    CPUState *saved_env;
3389 44f8625d bellard
    unsigned long pc;
3390 fdabc366 bellard
    int ret;
3391 fdabc366 bellard
3392 fdabc366 bellard
    /* XXX: hack to restore env in all cases, even if not called from
3393 fdabc366 bellard
       generated code */
3394 fdabc366 bellard
    saved_env = env;
3395 fdabc366 bellard
    env = cpu_single_env;
3396 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3397 76a66253 j_mayer
    if (unlikely(ret != 0)) {
3398 fdabc366 bellard
        if (likely(retaddr)) {
3399 fdabc366 bellard
            /* now we have a real cpu fault */
3400 44f8625d bellard
            pc = (unsigned long)retaddr;
3401 fdabc366 bellard
            tb = tb_find_pc(pc);
3402 fdabc366 bellard
            if (likely(tb)) {
3403 fdabc366 bellard
                /* the PC is inside the translated code. It means that we have
3404 fdabc366 bellard
                   a virtual CPU fault */
3405 fdabc366 bellard
                cpu_restore_state(tb, env, pc, NULL);
3406 76a66253 j_mayer
            }
3407 fdabc366 bellard
        }
3408 e06fcd75 aurel32
        helper_raise_exception_err(env->exception_index, env->error_code);
3409 fdabc366 bellard
    }
3410 fdabc366 bellard
    env = saved_env;
3411 9a64fbe4 bellard
}
3412 9a64fbe4 bellard
3413 74d37793 aurel32
/* Segment registers load and store */
3414 74d37793 aurel32
target_ulong helper_load_sr (target_ulong sr_num)
3415 74d37793 aurel32
{
3416 74d37793 aurel32
    return env->sr[sr_num];
3417 74d37793 aurel32
}
3418 74d37793 aurel32
3419 74d37793 aurel32
void helper_store_sr (target_ulong sr_num, target_ulong val)
3420 74d37793 aurel32
{
3421 45d827d2 aurel32
    ppc_store_sr(env, sr_num, val);
3422 74d37793 aurel32
}
3423 74d37793 aurel32
3424 74d37793 aurel32
/* SLB management */
3425 74d37793 aurel32
#if defined(TARGET_PPC64)
3426 74d37793 aurel32
target_ulong helper_load_slb (target_ulong slb_nr)
3427 74d37793 aurel32
{
3428 74d37793 aurel32
    return ppc_load_slb(env, slb_nr);
3429 74d37793 aurel32
}
3430 74d37793 aurel32
3431 74d37793 aurel32
void helper_store_slb (target_ulong slb_nr, target_ulong rs)
3432 74d37793 aurel32
{
3433 74d37793 aurel32
    ppc_store_slb(env, slb_nr, rs);
3434 74d37793 aurel32
}
3435 74d37793 aurel32
3436 74d37793 aurel32
void helper_slbia (void)
3437 74d37793 aurel32
{
3438 74d37793 aurel32
    ppc_slb_invalidate_all(env);
3439 74d37793 aurel32
}
3440 74d37793 aurel32
3441 74d37793 aurel32
void helper_slbie (target_ulong addr)
3442 74d37793 aurel32
{
3443 74d37793 aurel32
    ppc_slb_invalidate_one(env, addr);
3444 74d37793 aurel32
}
3445 74d37793 aurel32
3446 74d37793 aurel32
#endif /* defined(TARGET_PPC64) */
3447 74d37793 aurel32
3448 74d37793 aurel32
/* TLB management */
3449 74d37793 aurel32
void helper_tlbia (void)
3450 74d37793 aurel32
{
3451 74d37793 aurel32
    ppc_tlb_invalidate_all(env);
3452 74d37793 aurel32
}
3453 74d37793 aurel32
3454 74d37793 aurel32
void helper_tlbie (target_ulong addr)
3455 74d37793 aurel32
{
3456 74d37793 aurel32
    ppc_tlb_invalidate_one(env, addr);
3457 74d37793 aurel32
}
3458 74d37793 aurel32
3459 76a66253 j_mayer
/* Software driven TLBs management */
3460 76a66253 j_mayer
/* PowerPC 602/603 software TLB load instructions helpers */
3461 74d37793 aurel32
static void do_6xx_tlb (target_ulong new_EPN, int is_code)
3462 76a66253 j_mayer
{
3463 76a66253 j_mayer
    target_ulong RPN, CMP, EPN;
3464 76a66253 j_mayer
    int way;
3465 d9bce9d9 j_mayer
3466 76a66253 j_mayer
    RPN = env->spr[SPR_RPA];
3467 76a66253 j_mayer
    if (is_code) {
3468 76a66253 j_mayer
        CMP = env->spr[SPR_ICMP];
3469 76a66253 j_mayer
        EPN = env->spr[SPR_IMISS];
3470 76a66253 j_mayer
    } else {
3471 76a66253 j_mayer
        CMP = env->spr[SPR_DCMP];
3472 76a66253 j_mayer
        EPN = env->spr[SPR_DMISS];
3473 76a66253 j_mayer
    }
3474 76a66253 j_mayer
    way = (env->spr[SPR_SRR1] >> 17) & 1;
3475 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3476 76a66253 j_mayer
    if (loglevel != 0) {
3477 0e69805a aurel32
        fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3478 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
3479 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
3480 76a66253 j_mayer
    }
3481 76a66253 j_mayer
#endif
3482 76a66253 j_mayer
    /* Store this TLB */
3483 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3484 d9bce9d9 j_mayer
                     way, is_code, CMP, RPN);
3485 76a66253 j_mayer
}
3486 76a66253 j_mayer
3487 74d37793 aurel32
void helper_6xx_tlbd (target_ulong EPN)
3488 0f3955e2 aurel32
{
3489 74d37793 aurel32
    do_6xx_tlb(EPN, 0);
3490 0f3955e2 aurel32
}
3491 0f3955e2 aurel32
3492 74d37793 aurel32
void helper_6xx_tlbi (target_ulong EPN)
3493 0f3955e2 aurel32
{
3494 74d37793 aurel32
    do_6xx_tlb(EPN, 1);
3495 0f3955e2 aurel32
}
3496 0f3955e2 aurel32
3497 0f3955e2 aurel32
/* PowerPC 74xx software TLB load instructions helpers */
3498 74d37793 aurel32
static void do_74xx_tlb (target_ulong new_EPN, int is_code)
3499 7dbe11ac j_mayer
{
3500 7dbe11ac j_mayer
    target_ulong RPN, CMP, EPN;
3501 7dbe11ac j_mayer
    int way;
3502 7dbe11ac j_mayer
3503 7dbe11ac j_mayer
    RPN = env->spr[SPR_PTELO];
3504 7dbe11ac j_mayer
    CMP = env->spr[SPR_PTEHI];
3505 7dbe11ac j_mayer
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
3506 7dbe11ac j_mayer
    way = env->spr[SPR_TLBMISS] & 0x3;
3507 7dbe11ac j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3508 7dbe11ac j_mayer
    if (loglevel != 0) {
3509 0e69805a aurel32
        fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3510 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
3511 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
3512 7dbe11ac j_mayer
    }
3513 7dbe11ac j_mayer
#endif
3514 7dbe11ac j_mayer
    /* Store this TLB */
3515 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3516 7dbe11ac j_mayer
                     way, is_code, CMP, RPN);
3517 7dbe11ac j_mayer
}
3518 7dbe11ac j_mayer
3519 74d37793 aurel32
void helper_74xx_tlbd (target_ulong EPN)
3520 0f3955e2 aurel32
{
3521 74d37793 aurel32
    do_74xx_tlb(EPN, 0);
3522 0f3955e2 aurel32
}
3523 0f3955e2 aurel32
3524 74d37793 aurel32
void helper_74xx_tlbi (target_ulong EPN)
3525 0f3955e2 aurel32
{
3526 74d37793 aurel32
    do_74xx_tlb(EPN, 1);
3527 0f3955e2 aurel32
}
3528 0f3955e2 aurel32
3529 a11b8151 j_mayer
static always_inline target_ulong booke_tlb_to_page_size (int size)
3530 a8dea12f j_mayer
{
3531 a8dea12f j_mayer
    return 1024 << (2 * size);
3532 a8dea12f j_mayer
}
3533 a8dea12f j_mayer
3534 a11b8151 j_mayer
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
3535 a8dea12f j_mayer
{
3536 a8dea12f j_mayer
    int size;
3537 a8dea12f j_mayer
3538 a8dea12f j_mayer
    switch (page_size) {
3539 a8dea12f j_mayer
    case 0x00000400UL:
3540 a8dea12f j_mayer
        size = 0x0;
3541 a8dea12f j_mayer
        break;
3542 a8dea12f j_mayer
    case 0x00001000UL:
3543 a8dea12f j_mayer
        size = 0x1;
3544 a8dea12f j_mayer
        break;
3545 a8dea12f j_mayer
    case 0x00004000UL:
3546 a8dea12f j_mayer
        size = 0x2;
3547 a8dea12f j_mayer
        break;
3548 a8dea12f j_mayer
    case 0x00010000UL:
3549 a8dea12f j_mayer
        size = 0x3;
3550 a8dea12f j_mayer
        break;
3551 a8dea12f j_mayer
    case 0x00040000UL:
3552 a8dea12f j_mayer
        size = 0x4;
3553 a8dea12f j_mayer
        break;
3554 a8dea12f j_mayer
    case 0x00100000UL:
3555 a8dea12f j_mayer
        size = 0x5;
3556 a8dea12f j_mayer
        break;
3557 a8dea12f j_mayer
    case 0x00400000UL:
3558 a8dea12f j_mayer
        size = 0x6;
3559 a8dea12f j_mayer
        break;
3560 a8dea12f j_mayer
    case 0x01000000UL:
3561 a8dea12f j_mayer
        size = 0x7;
3562 a8dea12f j_mayer
        break;
3563 a8dea12f j_mayer
    case 0x04000000UL:
3564 a8dea12f j_mayer
        size = 0x8;
3565 a8dea12f j_mayer
        break;
3566 a8dea12f j_mayer
    case 0x10000000UL:
3567 a8dea12f j_mayer
        size = 0x9;
3568 a8dea12f j_mayer
        break;
3569 a8dea12f j_mayer
    case 0x40000000UL:
3570 a8dea12f j_mayer
        size = 0xA;
3571 a8dea12f j_mayer
        break;
3572 a8dea12f j_mayer
#if defined (TARGET_PPC64)
3573 a8dea12f j_mayer
    case 0x000100000000ULL:
3574 a8dea12f j_mayer
        size = 0xB;
3575 a8dea12f j_mayer
        break;
3576 a8dea12f j_mayer
    case 0x000400000000ULL:
3577 a8dea12f j_mayer
        size = 0xC;
3578 a8dea12f j_mayer
        break;
3579 a8dea12f j_mayer
    case 0x001000000000ULL:
3580 a8dea12f j_mayer
        size = 0xD;
3581 a8dea12f j_mayer
        break;
3582 a8dea12f j_mayer
    case 0x004000000000ULL:
3583 a8dea12f j_mayer
        size = 0xE;
3584 a8dea12f j_mayer
        break;
3585 a8dea12f j_mayer
    case 0x010000000000ULL:
3586 a8dea12f j_mayer
        size = 0xF;
3587 a8dea12f j_mayer
        break;
3588 a8dea12f j_mayer
#endif
3589 a8dea12f j_mayer
    default:
3590 a8dea12f j_mayer
        size = -1;
3591 a8dea12f j_mayer
        break;
3592 a8dea12f j_mayer
    }
3593 a8dea12f j_mayer
3594 a8dea12f j_mayer
    return size;
3595 a8dea12f j_mayer
}
3596 a8dea12f j_mayer
3597 76a66253 j_mayer
/* Helpers for 4xx TLB management */
3598 74d37793 aurel32
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
3599 76a66253 j_mayer
{
3600 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3601 74d37793 aurel32
    target_ulong ret;
3602 a8dea12f j_mayer
    int size;
3603 76a66253 j_mayer
3604 74d37793 aurel32
    entry &= 0x3F;
3605 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3606 74d37793 aurel32
    ret = tlb->EPN;
3607 a8dea12f j_mayer
    if (tlb->prot & PAGE_VALID)
3608 74d37793 aurel32
        ret |= 0x400;
3609 a8dea12f j_mayer
    size = booke_page_size_to_tlb(tlb->size);
3610 a8dea12f j_mayer
    if (size < 0 || size > 0x7)
3611 a8dea12f j_mayer
        size = 1;
3612 74d37793 aurel32
    ret |= size << 7;
3613 a8dea12f j_mayer
    env->spr[SPR_40x_PID] = tlb->PID;
3614 74d37793 aurel32
    return ret;
3615 76a66253 j_mayer
}
3616 76a66253 j_mayer
3617 74d37793 aurel32
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
3618 76a66253 j_mayer
{
3619 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3620 74d37793 aurel32
    target_ulong ret;
3621 76a66253 j_mayer
3622 74d37793 aurel32
    entry &= 0x3F;
3623 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3624 74d37793 aurel32
    ret = tlb->RPN;
3625 a8dea12f j_mayer
    if (tlb->prot & PAGE_EXEC)
3626 74d37793 aurel32
        ret |= 0x200;
3627 a8dea12f j_mayer
    if (tlb->prot & PAGE_WRITE)
3628 74d37793 aurel32
        ret |= 0x100;
3629 74d37793 aurel32
    return ret;
3630 76a66253 j_mayer
}
3631 76a66253 j_mayer
3632 74d37793 aurel32
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
3633 76a66253 j_mayer
{
3634 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3635 76a66253 j_mayer
    target_ulong page, end;
3636 76a66253 j_mayer
3637 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3638 6b80055d j_mayer
    if (loglevel != 0) {
3639 0e69805a aurel32
        fprintf(logfile, "%s entry %d val " ADDRX "\n", __func__, (int)entry, val);
3640 c55e9aef j_mayer
    }
3641 c55e9aef j_mayer
#endif
3642 74d37793 aurel32
    entry &= 0x3F;
3643 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3644 76a66253 j_mayer
    /* Invalidate previous TLB (if it's valid) */
3645 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
3646 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
3647 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3648 6b80055d j_mayer
        if (loglevel != 0) {
3649 c55e9aef j_mayer
            fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
3650 74d37793 aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3651 c55e9aef j_mayer
        }
3652 c55e9aef j_mayer
#endif
3653 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3654 76a66253 j_mayer
            tlb_flush_page(env, page);
3655 76a66253 j_mayer
    }
3656 74d37793 aurel32
    tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
3657 c294fc58 j_mayer
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
3658 c294fc58 j_mayer
     * If this ever occurs, one should use the ppcemb target instead
3659 c294fc58 j_mayer
     * of the ppc or ppc64 one
3660 c294fc58 j_mayer
     */
3661 74d37793 aurel32
    if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
3662 71c8b8fd j_mayer
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
3663 71c8b8fd j_mayer
                  "are not supported (%d)\n",
3664 74d37793 aurel32
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
3665 c294fc58 j_mayer
    }
3666 74d37793 aurel32
    tlb->EPN = val & ~(tlb->size - 1);
3667 74d37793 aurel32
    if (val & 0x40)
3668 76a66253 j_mayer
        tlb->prot |= PAGE_VALID;
3669 76a66253 j_mayer
    else
3670 76a66253 j_mayer
        tlb->prot &= ~PAGE_VALID;
3671 74d37793 aurel32
    if (val & 0x20) {
3672 c294fc58 j_mayer
        /* XXX: TO BE FIXED */
3673 c294fc58 j_mayer
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
3674 c294fc58 j_mayer
    }
3675 c55e9aef j_mayer
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
3676 74d37793 aurel32
    tlb->attr = val & 0xFF;
3677 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3678 c294fc58 j_mayer
    if (loglevel != 0) {
3679 c294fc58 j_mayer
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3680 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3681 0e69805a aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3682 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
3683 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3684 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3685 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3686 c55e9aef j_mayer
    }
3687 c55e9aef j_mayer
#endif
3688 76a66253 j_mayer
    /* Invalidate new TLB (if valid) */
3689 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
3690 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
3691 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3692 6b80055d j_mayer
        if (loglevel != 0) {
3693 c55e9aef j_mayer
            fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
3694 0e69805a aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3695 c55e9aef j_mayer
        }
3696 c55e9aef j_mayer
#endif
3697 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3698 76a66253 j_mayer
            tlb_flush_page(env, page);
3699 76a66253 j_mayer
    }
3700 76a66253 j_mayer
}
3701 76a66253 j_mayer
3702 74d37793 aurel32
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
3703 76a66253 j_mayer
{
3704 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3705 76a66253 j_mayer
3706 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3707 6b80055d j_mayer
    if (loglevel != 0) {
3708 0e69805a aurel32
        fprintf(logfile, "%s entry %i val " ADDRX "\n", __func__, (int)entry, val);
3709 c55e9aef j_mayer
    }
3710 c55e9aef j_mayer
#endif
3711 74d37793 aurel32
    entry &= 0x3F;
3712 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3713 74d37793 aurel32
    tlb->RPN = val & 0xFFFFFC00;
3714 76a66253 j_mayer
    tlb->prot = PAGE_READ;
3715 74d37793 aurel32
    if (val & 0x200)
3716 76a66253 j_mayer
        tlb->prot |= PAGE_EXEC;
3717 74d37793 aurel32
    if (val & 0x100)
3718 76a66253 j_mayer
        tlb->prot |= PAGE_WRITE;
3719 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3720 6b80055d j_mayer
    if (loglevel != 0) {
3721 6b80055d j_mayer
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3722 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3723 74d37793 aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3724 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
3725 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3726 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3727 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3728 c55e9aef j_mayer
    }
3729 c55e9aef j_mayer
#endif
3730 76a66253 j_mayer
}
3731 5eb7995e j_mayer
3732 74d37793 aurel32
target_ulong helper_4xx_tlbsx (target_ulong address)
3733 74d37793 aurel32
{
3734 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
3735 74d37793 aurel32
}
3736 74d37793 aurel32
3737 a4bb6c3e j_mayer
/* PowerPC 440 TLB management */
3738 74d37793 aurel32
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
3739 5eb7995e j_mayer
{
3740 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
3741 a4bb6c3e j_mayer
    target_ulong EPN, RPN, size;
3742 5eb7995e j_mayer
    int do_flush_tlbs;
3743 5eb7995e j_mayer
3744 5eb7995e j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3745 5eb7995e j_mayer
    if (loglevel != 0) {
3746 0e69805a aurel32
        fprintf(logfile, "%s word %d entry %d value " ADDRX "\n",
3747 0e69805a aurel32
                __func__, word, (int)entry, value);
3748 5eb7995e j_mayer
    }
3749 5eb7995e j_mayer
#endif
3750 5eb7995e j_mayer
    do_flush_tlbs = 0;
3751 74d37793 aurel32
    entry &= 0x3F;
3752 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3753 a4bb6c3e j_mayer
    switch (word) {
3754 a4bb6c3e j_mayer
    default:
3755 a4bb6c3e j_mayer
        /* Just here to please gcc */
3756 a4bb6c3e j_mayer
    case 0:
3757 74d37793 aurel32
        EPN = value & 0xFFFFFC00;
3758 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
3759 5eb7995e j_mayer
            do_flush_tlbs = 1;
3760 a4bb6c3e j_mayer
        tlb->EPN = EPN;
3761 74d37793 aurel32
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
3762 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
3763 a4bb6c3e j_mayer
            do_flush_tlbs = 1;
3764 a4bb6c3e j_mayer
        tlb->size = size;
3765 a4bb6c3e j_mayer
        tlb->attr &= ~0x1;
3766 74d37793 aurel32
        tlb->attr |= (value >> 8) & 1;
3767 74d37793 aurel32
        if (value & 0x200) {
3768 a4bb6c3e j_mayer
            tlb->prot |= PAGE_VALID;
3769 a4bb6c3e j_mayer
        } else {
3770 a4bb6c3e j_mayer
            if (tlb->prot & PAGE_VALID) {
3771 a4bb6c3e j_mayer
                tlb->prot &= ~PAGE_VALID;
3772 a4bb6c3e j_mayer
                do_flush_tlbs = 1;
3773 a4bb6c3e j_mayer
            }
3774 5eb7995e j_mayer
        }
3775 a4bb6c3e j_mayer
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
3776 a4bb6c3e j_mayer
        if (do_flush_tlbs)
3777 a4bb6c3e j_mayer
            tlb_flush(env, 1);
3778 a4bb6c3e j_mayer
        break;
3779 a4bb6c3e j_mayer
    case 1:
3780 74d37793 aurel32
        RPN = value & 0xFFFFFC0F;
3781 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
3782 a4bb6c3e j_mayer
            tlb_flush(env, 1);
3783 a4bb6c3e j_mayer
        tlb->RPN = RPN;
3784 a4bb6c3e j_mayer
        break;
3785 a4bb6c3e j_mayer
    case 2:
3786 74d37793 aurel32
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
3787 a4bb6c3e j_mayer
        tlb->prot = tlb->prot & PAGE_VALID;
3788 74d37793 aurel32
        if (value & 0x1)
3789 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ << 4;
3790 74d37793 aurel32
        if (value & 0x2)
3791 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE << 4;
3792 74d37793 aurel32
        if (value & 0x4)
3793 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC << 4;
3794 74d37793 aurel32
        if (value & 0x8)
3795 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ;
3796 74d37793 aurel32
        if (value & 0x10)
3797 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE;
3798 74d37793 aurel32
        if (value & 0x20)
3799 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC;
3800 a4bb6c3e j_mayer
        break;
3801 5eb7995e j_mayer
    }
3802 5eb7995e j_mayer
}
3803 5eb7995e j_mayer
3804 74d37793 aurel32
target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
3805 5eb7995e j_mayer
{
3806 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
3807 74d37793 aurel32
    target_ulong ret;
3808 5eb7995e j_mayer
    int size;
3809 5eb7995e j_mayer
3810 74d37793 aurel32
    entry &= 0x3F;
3811 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3812 a4bb6c3e j_mayer
    switch (word) {
3813 a4bb6c3e j_mayer
    default:
3814 a4bb6c3e j_mayer
        /* Just here to please gcc */
3815 a4bb6c3e j_mayer
    case 0:
3816 74d37793 aurel32
        ret = tlb->EPN;
3817 a4bb6c3e j_mayer
        size = booke_page_size_to_tlb(tlb->size);
3818 a4bb6c3e j_mayer
        if (size < 0 || size > 0xF)
3819 a4bb6c3e j_mayer
            size = 1;
3820 74d37793 aurel32
        ret |= size << 4;
3821 a4bb6c3e j_mayer
        if (tlb->attr & 0x1)
3822 74d37793 aurel32
            ret |= 0x100;
3823 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_VALID)
3824 74d37793 aurel32
            ret |= 0x200;
3825 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
3826 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] |= tlb->PID;
3827 a4bb6c3e j_mayer
        break;
3828 a4bb6c3e j_mayer
    case 1:
3829 74d37793 aurel32
        ret = tlb->RPN;
3830 a4bb6c3e j_mayer
        break;
3831 a4bb6c3e j_mayer
    case 2:
3832 74d37793 aurel32
        ret = tlb->attr & ~0x1;
3833 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_READ << 4))
3834 74d37793 aurel32
            ret |= 0x1;
3835 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_WRITE << 4))
3836 74d37793 aurel32
            ret |= 0x2;
3837 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_EXEC << 4))
3838 74d37793 aurel32
            ret |= 0x4;
3839 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_READ)
3840 74d37793 aurel32
            ret |= 0x8;
3841 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_WRITE)
3842 74d37793 aurel32
            ret |= 0x10;
3843 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_EXEC)
3844 74d37793 aurel32
            ret |= 0x20;
3845 a4bb6c3e j_mayer
        break;
3846 a4bb6c3e j_mayer
    }
3847 74d37793 aurel32
    return ret;
3848 5eb7995e j_mayer
}
3849 74d37793 aurel32
3850 74d37793 aurel32
target_ulong helper_440_tlbsx (target_ulong address)
3851 74d37793 aurel32
{
3852 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
3853 74d37793 aurel32
}
3854 74d37793 aurel32
3855 76a66253 j_mayer
#endif /* !CONFIG_USER_ONLY */