Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 7b239bec

History | View | Annotate | Download (91 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 7872c51c aurel32
#define VARITH_DO(name, op, element)        \
1976 7872c51c aurel32
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)          \
1977 7872c51c aurel32
{                                                                       \
1978 7872c51c aurel32
    int i;                                                              \
1979 7872c51c aurel32
    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                      \
1980 7872c51c aurel32
        r->element[i] = a->element[i] op b->element[i];                 \
1981 7872c51c aurel32
    }                                                                   \
1982 7872c51c aurel32
}
1983 7872c51c aurel32
#define VARITH(suffix, element)                  \
1984 7872c51c aurel32
  VARITH_DO(add##suffix, +, element)             \
1985 7872c51c aurel32
  VARITH_DO(sub##suffix, -, element)
1986 7872c51c aurel32
VARITH(ubm, u8)
1987 7872c51c aurel32
VARITH(uhm, u16)
1988 7872c51c aurel32
VARITH(uwm, u32)
1989 7872c51c aurel32
#undef VARITH_DO
1990 7872c51c aurel32
#undef VARITH
1991 7872c51c aurel32
1992 fab3cbe9 aurel32
#define VAVG_DO(name, element, etype)                                   \
1993 fab3cbe9 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
1994 fab3cbe9 aurel32
    {                                                                   \
1995 fab3cbe9 aurel32
        int i;                                                          \
1996 fab3cbe9 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1997 fab3cbe9 aurel32
            etype x = (etype)a->element[i] + (etype)b->element[i] + 1;  \
1998 fab3cbe9 aurel32
            r->element[i] = x >> 1;                                     \
1999 fab3cbe9 aurel32
        }                                                               \
2000 fab3cbe9 aurel32
    }
2001 fab3cbe9 aurel32
2002 fab3cbe9 aurel32
#define VAVG(type, signed_element, signed_type, unsigned_element, unsigned_type) \
2003 fab3cbe9 aurel32
    VAVG_DO(avgs##type, signed_element, signed_type)                    \
2004 fab3cbe9 aurel32
    VAVG_DO(avgu##type, unsigned_element, unsigned_type)
2005 fab3cbe9 aurel32
VAVG(b, s8, int16_t, u8, uint16_t)
2006 fab3cbe9 aurel32
VAVG(h, s16, int32_t, u16, uint32_t)
2007 fab3cbe9 aurel32
VAVG(w, s32, int64_t, u32, uint64_t)
2008 fab3cbe9 aurel32
#undef VAVG_DO
2009 fab3cbe9 aurel32
#undef VAVG
2010 fab3cbe9 aurel32
2011 e4039339 aurel32
#define VMINMAX_DO(name, compare, element)                              \
2012 e4039339 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2013 e4039339 aurel32
    {                                                                   \
2014 e4039339 aurel32
        int i;                                                          \
2015 e4039339 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2016 e4039339 aurel32
            if (a->element[i] compare b->element[i]) {                  \
2017 e4039339 aurel32
                r->element[i] = b->element[i];                          \
2018 e4039339 aurel32
            } else {                                                    \
2019 e4039339 aurel32
                r->element[i] = a->element[i];                          \
2020 e4039339 aurel32
            }                                                           \
2021 e4039339 aurel32
        }                                                               \
2022 e4039339 aurel32
    }
2023 e4039339 aurel32
#define VMINMAX(suffix, element)                \
2024 e4039339 aurel32
  VMINMAX_DO(min##suffix, >, element)           \
2025 e4039339 aurel32
  VMINMAX_DO(max##suffix, <, element)
2026 e4039339 aurel32
VMINMAX(sb, s8)
2027 e4039339 aurel32
VMINMAX(sh, s16)
2028 e4039339 aurel32
VMINMAX(sw, s32)
2029 e4039339 aurel32
VMINMAX(ub, u8)
2030 e4039339 aurel32
VMINMAX(uh, u16)
2031 e4039339 aurel32
VMINMAX(uw, u32)
2032 e4039339 aurel32
#undef VMINMAX_DO
2033 e4039339 aurel32
#undef VMINMAX
2034 e4039339 aurel32
2035 3b430048 aurel32
#define VMRG_DO(name, element, highp)                                   \
2036 3b430048 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2037 3b430048 aurel32
    {                                                                   \
2038 3b430048 aurel32
        ppc_avr_t result;                                               \
2039 3b430048 aurel32
        int i;                                                          \
2040 3b430048 aurel32
        size_t n_elems = ARRAY_SIZE(r->element);                        \
2041 3b430048 aurel32
        for (i = 0; i < n_elems/2; i++) {                               \
2042 3b430048 aurel32
            if (highp) {                                                \
2043 3b430048 aurel32
                result.element[i*2+HI_IDX] = a->element[i];             \
2044 3b430048 aurel32
                result.element[i*2+LO_IDX] = b->element[i];             \
2045 3b430048 aurel32
            } else {                                                    \
2046 3b430048 aurel32
                result.element[n_elems - i*2 - (1+HI_IDX)] = b->element[n_elems - i - 1]; \
2047 3b430048 aurel32
                result.element[n_elems - i*2 - (1+LO_IDX)] = a->element[n_elems - i - 1]; \
2048 3b430048 aurel32
            }                                                           \
2049 3b430048 aurel32
        }                                                               \
2050 3b430048 aurel32
        *r = result;                                                    \
2051 3b430048 aurel32
    }
2052 3b430048 aurel32
#if defined(WORDS_BIGENDIAN)
2053 3b430048 aurel32
#define MRGHI 0
2054 3b430048 aurel32
#define MRGL0 1
2055 3b430048 aurel32
#else
2056 3b430048 aurel32
#define MRGHI 1
2057 3b430048 aurel32
#define MRGLO 0
2058 3b430048 aurel32
#endif
2059 3b430048 aurel32
#define VMRG(suffix, element)                   \
2060 3b430048 aurel32
  VMRG_DO(mrgl##suffix, element, MRGHI)         \
2061 3b430048 aurel32
  VMRG_DO(mrgh##suffix, element, MRGLO)
2062 3b430048 aurel32
VMRG(b, u8)
2063 3b430048 aurel32
VMRG(h, u16)
2064 3b430048 aurel32
VMRG(w, u32)
2065 3b430048 aurel32
#undef VMRG_DO
2066 3b430048 aurel32
#undef VMRG
2067 3b430048 aurel32
#undef MRGHI
2068 3b430048 aurel32
#undef MRGLO
2069 3b430048 aurel32
2070 2c277908 aurel32
#define VMUL_DO(name, mul_element, prod_element, evenp)                 \
2071 2c277908 aurel32
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2072 2c277908 aurel32
    {                                                                   \
2073 2c277908 aurel32
        int i;                                                          \
2074 2c277908 aurel32
        VECTOR_FOR_INORDER_I(i, prod_element) {                         \
2075 2c277908 aurel32
            if (evenp) {                                                \
2076 2c277908 aurel32
                r->prod_element[i] = a->mul_element[i*2+HI_IDX] * b->mul_element[i*2+HI_IDX]; \
2077 2c277908 aurel32
            } else {                                                    \
2078 2c277908 aurel32
                r->prod_element[i] = a->mul_element[i*2+LO_IDX] * b->mul_element[i*2+LO_IDX]; \
2079 2c277908 aurel32
            }                                                           \
2080 2c277908 aurel32
        }                                                               \
2081 2c277908 aurel32
    }
2082 2c277908 aurel32
#define VMUL(suffix, mul_element, prod_element) \
2083 2c277908 aurel32
  VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
2084 2c277908 aurel32
  VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
2085 2c277908 aurel32
VMUL(sb, s8, s16)
2086 2c277908 aurel32
VMUL(sh, s16, s32)
2087 2c277908 aurel32
VMUL(ub, u8, u16)
2088 2c277908 aurel32
VMUL(uh, u16, u32)
2089 2c277908 aurel32
#undef VMUL_DO
2090 2c277908 aurel32
#undef VMUL
2091 2c277908 aurel32
2092 d79f0809 aurel32
#define VSL(suffix, element)                                            \
2093 d79f0809 aurel32
    void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2094 d79f0809 aurel32
    {                                                                   \
2095 d79f0809 aurel32
        int i;                                                          \
2096 d79f0809 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2097 d79f0809 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2098 d79f0809 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2099 d79f0809 aurel32
            r->element[i] = a->element[i] << shift;                     \
2100 d79f0809 aurel32
        }                                                               \
2101 d79f0809 aurel32
    }
2102 d79f0809 aurel32
VSL(b, u8)
2103 d79f0809 aurel32
VSL(h, u16)
2104 d79f0809 aurel32
VSL(w, u32)
2105 d79f0809 aurel32
#undef VSL
2106 d79f0809 aurel32
2107 7b239bec aurel32
void helper_vslo (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2108 7b239bec aurel32
{
2109 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2110 7b239bec aurel32
2111 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2112 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2113 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2114 7b239bec aurel32
#else
2115 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2116 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2117 7b239bec aurel32
#endif
2118 7b239bec aurel32
}
2119 7b239bec aurel32
2120 07ef34c3 aurel32
#define VSR(suffix, element)                                            \
2121 07ef34c3 aurel32
    void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2122 07ef34c3 aurel32
    {                                                                   \
2123 07ef34c3 aurel32
        int i;                                                          \
2124 07ef34c3 aurel32
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2125 07ef34c3 aurel32
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2126 07ef34c3 aurel32
            unsigned int shift = b->element[i] & mask;                  \
2127 07ef34c3 aurel32
            r->element[i] = a->element[i] >> shift;                     \
2128 07ef34c3 aurel32
        }                                                               \
2129 07ef34c3 aurel32
    }
2130 07ef34c3 aurel32
VSR(ab, s8)
2131 07ef34c3 aurel32
VSR(ah, s16)
2132 07ef34c3 aurel32
VSR(aw, s32)
2133 07ef34c3 aurel32
VSR(b, u8)
2134 07ef34c3 aurel32
VSR(h, u16)
2135 07ef34c3 aurel32
VSR(w, u32)
2136 07ef34c3 aurel32
#undef VSR
2137 07ef34c3 aurel32
2138 7b239bec aurel32
void helper_vsro (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2139 7b239bec aurel32
{
2140 7b239bec aurel32
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2141 7b239bec aurel32
2142 7b239bec aurel32
#if defined (WORDS_BIGENDIAN)
2143 7b239bec aurel32
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2144 7b239bec aurel32
  memset (&r->u8[0], 0, sh);
2145 7b239bec aurel32
#else
2146 7b239bec aurel32
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2147 7b239bec aurel32
  memset (&r->u8[16-sh], 0, sh);
2148 7b239bec aurel32
#endif
2149 7b239bec aurel32
}
2150 7b239bec aurel32
2151 d6a46fe8 aurel32
#undef VECTOR_FOR_INORDER_I
2152 d6a46fe8 aurel32
#undef HI_IDX
2153 d6a46fe8 aurel32
#undef LO_IDX
2154 d6a46fe8 aurel32
2155 d6a46fe8 aurel32
/*****************************************************************************/
2156 0487d6a8 j_mayer
/* SPE extension helpers */
2157 0487d6a8 j_mayer
/* Use a table to make this quicker */
2158 0487d6a8 j_mayer
static uint8_t hbrev[16] = {
2159 0487d6a8 j_mayer
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
2160 0487d6a8 j_mayer
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
2161 0487d6a8 j_mayer
};
2162 0487d6a8 j_mayer
2163 b068d6a7 j_mayer
static always_inline uint8_t byte_reverse (uint8_t val)
2164 0487d6a8 j_mayer
{
2165 0487d6a8 j_mayer
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
2166 0487d6a8 j_mayer
}
2167 0487d6a8 j_mayer
2168 b068d6a7 j_mayer
static always_inline uint32_t word_reverse (uint32_t val)
2169 0487d6a8 j_mayer
{
2170 0487d6a8 j_mayer
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
2171 0487d6a8 j_mayer
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
2172 0487d6a8 j_mayer
}
2173 0487d6a8 j_mayer
2174 3cd7d1dd j_mayer
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
2175 57951c27 aurel32
target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
2176 0487d6a8 j_mayer
{
2177 0487d6a8 j_mayer
    uint32_t a, b, d, mask;
2178 0487d6a8 j_mayer
2179 3cd7d1dd j_mayer
    mask = UINT32_MAX >> (32 - MASKBITS);
2180 57951c27 aurel32
    a = arg1 & mask;
2181 57951c27 aurel32
    b = arg2 & mask;
2182 3cd7d1dd j_mayer
    d = word_reverse(1 + word_reverse(a | ~b));
2183 57951c27 aurel32
    return (arg1 & ~mask) | (d & b);
2184 0487d6a8 j_mayer
}
2185 0487d6a8 j_mayer
2186 57951c27 aurel32
uint32_t helper_cntlsw32 (uint32_t val)
2187 0487d6a8 j_mayer
{
2188 0487d6a8 j_mayer
    if (val & 0x80000000)
2189 603fccce j_mayer
        return clz32(~val);
2190 0487d6a8 j_mayer
    else
2191 603fccce j_mayer
        return clz32(val);
2192 0487d6a8 j_mayer
}
2193 0487d6a8 j_mayer
2194 57951c27 aurel32
uint32_t helper_cntlzw32 (uint32_t val)
2195 0487d6a8 j_mayer
{
2196 603fccce j_mayer
    return clz32(val);
2197 0487d6a8 j_mayer
}
2198 0487d6a8 j_mayer
2199 1c97856d aurel32
/* Single-precision floating-point conversions */
2200 1c97856d aurel32
static always_inline uint32_t efscfsi (uint32_t val)
2201 0487d6a8 j_mayer
{
2202 0ca9d380 aurel32
    CPU_FloatU u;
2203 0487d6a8 j_mayer
2204 0487d6a8 j_mayer
    u.f = int32_to_float32(val, &env->spe_status);
2205 0487d6a8 j_mayer
2206 0ca9d380 aurel32
    return u.l;
2207 0487d6a8 j_mayer
}
2208 0487d6a8 j_mayer
2209 1c97856d aurel32
static always_inline uint32_t efscfui (uint32_t val)
2210 0487d6a8 j_mayer
{
2211 0ca9d380 aurel32
    CPU_FloatU u;
2212 0487d6a8 j_mayer
2213 0487d6a8 j_mayer
    u.f = uint32_to_float32(val, &env->spe_status);
2214 0487d6a8 j_mayer
2215 0ca9d380 aurel32
    return u.l;
2216 0487d6a8 j_mayer
}
2217 0487d6a8 j_mayer
2218 1c97856d aurel32
static always_inline int32_t efsctsi (uint32_t val)
2219 0487d6a8 j_mayer
{
2220 0ca9d380 aurel32
    CPU_FloatU u;
2221 0487d6a8 j_mayer
2222 0ca9d380 aurel32
    u.l = val;
2223 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2224 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2225 0487d6a8 j_mayer
        return 0;
2226 0487d6a8 j_mayer
2227 0487d6a8 j_mayer
    return float32_to_int32(u.f, &env->spe_status);
2228 0487d6a8 j_mayer
}
2229 0487d6a8 j_mayer
2230 1c97856d aurel32
static always_inline uint32_t efsctui (uint32_t val)
2231 0487d6a8 j_mayer
{
2232 0ca9d380 aurel32
    CPU_FloatU u;
2233 0487d6a8 j_mayer
2234 0ca9d380 aurel32
    u.l = val;
2235 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2236 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2237 0487d6a8 j_mayer
        return 0;
2238 0487d6a8 j_mayer
2239 0487d6a8 j_mayer
    return float32_to_uint32(u.f, &env->spe_status);
2240 0487d6a8 j_mayer
}
2241 0487d6a8 j_mayer
2242 1c97856d aurel32
static always_inline uint32_t efsctsiz (uint32_t val)
2243 0487d6a8 j_mayer
{
2244 0ca9d380 aurel32
    CPU_FloatU u;
2245 0487d6a8 j_mayer
2246 0ca9d380 aurel32
    u.l = val;
2247 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2248 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2249 0487d6a8 j_mayer
        return 0;
2250 0487d6a8 j_mayer
2251 0487d6a8 j_mayer
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2252 0487d6a8 j_mayer
}
2253 0487d6a8 j_mayer
2254 1c97856d aurel32
static always_inline uint32_t efsctuiz (uint32_t val)
2255 0487d6a8 j_mayer
{
2256 0ca9d380 aurel32
    CPU_FloatU u;
2257 0487d6a8 j_mayer
2258 0ca9d380 aurel32
    u.l = val;
2259 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2260 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2261 0487d6a8 j_mayer
        return 0;
2262 0487d6a8 j_mayer
2263 0487d6a8 j_mayer
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2264 0487d6a8 j_mayer
}
2265 0487d6a8 j_mayer
2266 1c97856d aurel32
static always_inline uint32_t efscfsf (uint32_t val)
2267 0487d6a8 j_mayer
{
2268 0ca9d380 aurel32
    CPU_FloatU u;
2269 0487d6a8 j_mayer
    float32 tmp;
2270 0487d6a8 j_mayer
2271 0487d6a8 j_mayer
    u.f = int32_to_float32(val, &env->spe_status);
2272 0487d6a8 j_mayer
    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
2273 0487d6a8 j_mayer
    u.f = float32_div(u.f, tmp, &env->spe_status);
2274 0487d6a8 j_mayer
2275 0ca9d380 aurel32
    return u.l;
2276 0487d6a8 j_mayer
}
2277 0487d6a8 j_mayer
2278 1c97856d aurel32
static always_inline uint32_t efscfuf (uint32_t val)
2279 0487d6a8 j_mayer
{
2280 0ca9d380 aurel32
    CPU_FloatU u;
2281 0487d6a8 j_mayer
    float32 tmp;
2282 0487d6a8 j_mayer
2283 0487d6a8 j_mayer
    u.f = uint32_to_float32(val, &env->spe_status);
2284 0487d6a8 j_mayer
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2285 0487d6a8 j_mayer
    u.f = float32_div(u.f, tmp, &env->spe_status);
2286 0487d6a8 j_mayer
2287 0ca9d380 aurel32
    return u.l;
2288 0487d6a8 j_mayer
}
2289 0487d6a8 j_mayer
2290 1c97856d aurel32
static always_inline uint32_t efsctsf (uint32_t val)
2291 0487d6a8 j_mayer
{
2292 0ca9d380 aurel32
    CPU_FloatU u;
2293 0487d6a8 j_mayer
    float32 tmp;
2294 0487d6a8 j_mayer
2295 0ca9d380 aurel32
    u.l = val;
2296 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2297 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2298 0487d6a8 j_mayer
        return 0;
2299 0487d6a8 j_mayer
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2300 0487d6a8 j_mayer
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2301 0487d6a8 j_mayer
2302 0487d6a8 j_mayer
    return float32_to_int32(u.f, &env->spe_status);
2303 0487d6a8 j_mayer
}
2304 0487d6a8 j_mayer
2305 1c97856d aurel32
static always_inline uint32_t efsctuf (uint32_t val)
2306 0487d6a8 j_mayer
{
2307 0ca9d380 aurel32
    CPU_FloatU u;
2308 0487d6a8 j_mayer
    float32 tmp;
2309 0487d6a8 j_mayer
2310 0ca9d380 aurel32
    u.l = val;
2311 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2312 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2313 0487d6a8 j_mayer
        return 0;
2314 0487d6a8 j_mayer
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2315 0487d6a8 j_mayer
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2316 0487d6a8 j_mayer
2317 0487d6a8 j_mayer
    return float32_to_uint32(u.f, &env->spe_status);
2318 0487d6a8 j_mayer
}
2319 0487d6a8 j_mayer
2320 1c97856d aurel32
#define HELPER_SPE_SINGLE_CONV(name)                                          \
2321 1c97856d aurel32
uint32_t helper_e##name (uint32_t val)                                        \
2322 1c97856d aurel32
{                                                                             \
2323 1c97856d aurel32
    return e##name(val);                                                      \
2324 1c97856d aurel32
}
2325 1c97856d aurel32
/* efscfsi */
2326 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsi);
2327 1c97856d aurel32
/* efscfui */
2328 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfui);
2329 1c97856d aurel32
/* efscfuf */
2330 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfuf);
2331 1c97856d aurel32
/* efscfsf */
2332 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsf);
2333 1c97856d aurel32
/* efsctsi */
2334 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsi);
2335 1c97856d aurel32
/* efsctui */
2336 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctui);
2337 1c97856d aurel32
/* efsctsiz */
2338 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsiz);
2339 1c97856d aurel32
/* efsctuiz */
2340 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuiz);
2341 1c97856d aurel32
/* efsctsf */
2342 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsf);
2343 1c97856d aurel32
/* efsctuf */
2344 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuf);
2345 1c97856d aurel32
2346 1c97856d aurel32
#define HELPER_SPE_VECTOR_CONV(name)                                          \
2347 1c97856d aurel32
uint64_t helper_ev##name (uint64_t val)                                       \
2348 1c97856d aurel32
{                                                                             \
2349 1c97856d aurel32
    return ((uint64_t)e##name(val >> 32) << 32) |                             \
2350 1c97856d aurel32
            (uint64_t)e##name(val);                                           \
2351 0487d6a8 j_mayer
}
2352 1c97856d aurel32
/* evfscfsi */
2353 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsi);
2354 1c97856d aurel32
/* evfscfui */
2355 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfui);
2356 1c97856d aurel32
/* evfscfuf */
2357 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfuf);
2358 1c97856d aurel32
/* evfscfsf */
2359 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsf);
2360 1c97856d aurel32
/* evfsctsi */
2361 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsi);
2362 1c97856d aurel32
/* evfsctui */
2363 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctui);
2364 1c97856d aurel32
/* evfsctsiz */
2365 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsiz);
2366 1c97856d aurel32
/* evfsctuiz */
2367 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuiz);
2368 1c97856d aurel32
/* evfsctsf */
2369 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsf);
2370 1c97856d aurel32
/* evfsctuf */
2371 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuf);
2372 0487d6a8 j_mayer
2373 1c97856d aurel32
/* Single-precision floating-point arithmetic */
2374 1c97856d aurel32
static always_inline uint32_t efsadd (uint32_t op1, uint32_t op2)
2375 0487d6a8 j_mayer
{
2376 1c97856d aurel32
    CPU_FloatU u1, u2;
2377 1c97856d aurel32
    u1.l = op1;
2378 1c97856d aurel32
    u2.l = op2;
2379 1c97856d aurel32
    u1.f = float32_add(u1.f, u2.f, &env->spe_status);
2380 1c97856d aurel32
    return u1.l;
2381 0487d6a8 j_mayer
}
2382 0487d6a8 j_mayer
2383 1c97856d aurel32
static always_inline uint32_t efssub (uint32_t op1, uint32_t op2)
2384 0487d6a8 j_mayer
{
2385 1c97856d aurel32
    CPU_FloatU u1, u2;
2386 1c97856d aurel32
    u1.l = op1;
2387 1c97856d aurel32
    u2.l = op2;
2388 1c97856d aurel32
    u1.f = float32_sub(u1.f, u2.f, &env->spe_status);
2389 1c97856d aurel32
    return u1.l;
2390 0487d6a8 j_mayer
}
2391 0487d6a8 j_mayer
2392 1c97856d aurel32
static always_inline uint32_t efsmul (uint32_t op1, uint32_t op2)
2393 0487d6a8 j_mayer
{
2394 1c97856d aurel32
    CPU_FloatU u1, u2;
2395 1c97856d aurel32
    u1.l = op1;
2396 1c97856d aurel32
    u2.l = op2;
2397 1c97856d aurel32
    u1.f = float32_mul(u1.f, u2.f, &env->spe_status);
2398 1c97856d aurel32
    return u1.l;
2399 0487d6a8 j_mayer
}
2400 0487d6a8 j_mayer
2401 1c97856d aurel32
static always_inline uint32_t efsdiv (uint32_t op1, uint32_t op2)
2402 0487d6a8 j_mayer
{
2403 1c97856d aurel32
    CPU_FloatU u1, u2;
2404 1c97856d aurel32
    u1.l = op1;
2405 1c97856d aurel32
    u2.l = op2;
2406 1c97856d aurel32
    u1.f = float32_div(u1.f, u2.f, &env->spe_status);
2407 1c97856d aurel32
    return u1.l;
2408 0487d6a8 j_mayer
}
2409 0487d6a8 j_mayer
2410 1c97856d aurel32
#define HELPER_SPE_SINGLE_ARITH(name)                                         \
2411 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
2412 1c97856d aurel32
{                                                                             \
2413 1c97856d aurel32
    return e##name(op1, op2);                                                 \
2414 1c97856d aurel32
}
2415 1c97856d aurel32
/* efsadd */
2416 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsadd);
2417 1c97856d aurel32
/* efssub */
2418 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fssub);
2419 1c97856d aurel32
/* efsmul */
2420 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsmul);
2421 1c97856d aurel32
/* efsdiv */
2422 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsdiv);
2423 1c97856d aurel32
2424 1c97856d aurel32
#define HELPER_SPE_VECTOR_ARITH(name)                                         \
2425 1c97856d aurel32
uint64_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
2426 1c97856d aurel32
{                                                                             \
2427 1c97856d aurel32
    return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |                  \
2428 1c97856d aurel32
            (uint64_t)e##name(op1, op2);                                      \
2429 1c97856d aurel32
}
2430 1c97856d aurel32
/* evfsadd */
2431 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsadd);
2432 1c97856d aurel32
/* evfssub */
2433 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fssub);
2434 1c97856d aurel32
/* evfsmul */
2435 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsmul);
2436 1c97856d aurel32
/* evfsdiv */
2437 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsdiv);
2438 1c97856d aurel32
2439 1c97856d aurel32
/* Single-precision floating-point comparisons */
2440 1c97856d aurel32
static always_inline uint32_t efststlt (uint32_t op1, uint32_t op2)
2441 0487d6a8 j_mayer
{
2442 1c97856d aurel32
    CPU_FloatU u1, u2;
2443 1c97856d aurel32
    u1.l = op1;
2444 1c97856d aurel32
    u2.l = op2;
2445 1c97856d aurel32
    return float32_lt(u1.f, u2.f, &env->spe_status) ? 4 : 0;
2446 0487d6a8 j_mayer
}
2447 0487d6a8 j_mayer
2448 1c97856d aurel32
static always_inline uint32_t efststgt (uint32_t op1, uint32_t op2)
2449 0487d6a8 j_mayer
{
2450 1c97856d aurel32
    CPU_FloatU u1, u2;
2451 1c97856d aurel32
    u1.l = op1;
2452 1c97856d aurel32
    u2.l = op2;
2453 1c97856d aurel32
    return float32_le(u1.f, u2.f, &env->spe_status) ? 0 : 4;
2454 0487d6a8 j_mayer
}
2455 0487d6a8 j_mayer
2456 1c97856d aurel32
static always_inline uint32_t efststeq (uint32_t op1, uint32_t op2)
2457 0487d6a8 j_mayer
{
2458 1c97856d aurel32
    CPU_FloatU u1, u2;
2459 1c97856d aurel32
    u1.l = op1;
2460 1c97856d aurel32
    u2.l = op2;
2461 1c97856d aurel32
    return float32_eq(u1.f, u2.f, &env->spe_status) ? 4 : 0;
2462 0487d6a8 j_mayer
}
2463 0487d6a8 j_mayer
2464 1c97856d aurel32
static always_inline uint32_t efscmplt (uint32_t op1, uint32_t op2)
2465 0487d6a8 j_mayer
{
2466 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2467 1c97856d aurel32
    return efststlt(op1, op2);
2468 0487d6a8 j_mayer
}
2469 0487d6a8 j_mayer
2470 1c97856d aurel32
static always_inline uint32_t efscmpgt (uint32_t op1, uint32_t op2)
2471 0487d6a8 j_mayer
{
2472 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2473 1c97856d aurel32
    return efststgt(op1, op2);
2474 0487d6a8 j_mayer
}
2475 0487d6a8 j_mayer
2476 1c97856d aurel32
static always_inline uint32_t efscmpeq (uint32_t op1, uint32_t op2)
2477 0487d6a8 j_mayer
{
2478 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2479 1c97856d aurel32
    return efststeq(op1, op2);
2480 0487d6a8 j_mayer
}
2481 0487d6a8 j_mayer
2482 1c97856d aurel32
#define HELPER_SINGLE_SPE_CMP(name)                                           \
2483 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
2484 1c97856d aurel32
{                                                                             \
2485 1c97856d aurel32
    return e##name(op1, op2) << 2;                                            \
2486 1c97856d aurel32
}
2487 1c97856d aurel32
/* efststlt */
2488 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststlt);
2489 1c97856d aurel32
/* efststgt */
2490 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststgt);
2491 1c97856d aurel32
/* efststeq */
2492 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststeq);
2493 1c97856d aurel32
/* efscmplt */
2494 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmplt);
2495 1c97856d aurel32
/* efscmpgt */
2496 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpgt);
2497 1c97856d aurel32
/* efscmpeq */
2498 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpeq);
2499 1c97856d aurel32
2500 1c97856d aurel32
static always_inline uint32_t evcmp_merge (int t0, int t1)
2501 0487d6a8 j_mayer
{
2502 1c97856d aurel32
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
2503 0487d6a8 j_mayer
}
2504 0487d6a8 j_mayer
2505 1c97856d aurel32
#define HELPER_VECTOR_SPE_CMP(name)                                           \
2506 1c97856d aurel32
uint32_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
2507 1c97856d aurel32
{                                                                             \
2508 1c97856d aurel32
    return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2));     \
2509 0487d6a8 j_mayer
}
2510 1c97856d aurel32
/* evfststlt */
2511 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststlt);
2512 1c97856d aurel32
/* evfststgt */
2513 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststgt);
2514 1c97856d aurel32
/* evfststeq */
2515 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststeq);
2516 1c97856d aurel32
/* evfscmplt */
2517 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmplt);
2518 1c97856d aurel32
/* evfscmpgt */
2519 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpgt);
2520 1c97856d aurel32
/* evfscmpeq */
2521 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpeq);
2522 0487d6a8 j_mayer
2523 1c97856d aurel32
/* Double-precision floating-point conversion */
2524 1c97856d aurel32
uint64_t helper_efdcfsi (uint32_t val)
2525 0487d6a8 j_mayer
{
2526 1c97856d aurel32
    CPU_DoubleU u;
2527 1c97856d aurel32
2528 1c97856d aurel32
    u.d = int32_to_float64(val, &env->spe_status);
2529 1c97856d aurel32
2530 1c97856d aurel32
    return u.ll;
2531 0487d6a8 j_mayer
}
2532 0487d6a8 j_mayer
2533 1c97856d aurel32
uint64_t helper_efdcfsid (uint64_t val)
2534 0487d6a8 j_mayer
{
2535 0ca9d380 aurel32
    CPU_DoubleU u;
2536 0487d6a8 j_mayer
2537 0ca9d380 aurel32
    u.d = int64_to_float64(val, &env->spe_status);
2538 0487d6a8 j_mayer
2539 0ca9d380 aurel32
    return u.ll;
2540 0487d6a8 j_mayer
}
2541 0487d6a8 j_mayer
2542 1c97856d aurel32
uint64_t helper_efdcfui (uint32_t val)
2543 1c97856d aurel32
{
2544 1c97856d aurel32
    CPU_DoubleU u;
2545 1c97856d aurel32
2546 1c97856d aurel32
    u.d = uint32_to_float64(val, &env->spe_status);
2547 1c97856d aurel32
2548 1c97856d aurel32
    return u.ll;
2549 1c97856d aurel32
}
2550 1c97856d aurel32
2551 1c97856d aurel32
uint64_t helper_efdcfuid (uint64_t val)
2552 0487d6a8 j_mayer
{
2553 0ca9d380 aurel32
    CPU_DoubleU u;
2554 0487d6a8 j_mayer
2555 0ca9d380 aurel32
    u.d = uint64_to_float64(val, &env->spe_status);
2556 0487d6a8 j_mayer
2557 0ca9d380 aurel32
    return u.ll;
2558 0487d6a8 j_mayer
}
2559 0487d6a8 j_mayer
2560 1c97856d aurel32
uint32_t helper_efdctsi (uint64_t val)
2561 0487d6a8 j_mayer
{
2562 0ca9d380 aurel32
    CPU_DoubleU u;
2563 0487d6a8 j_mayer
2564 0ca9d380 aurel32
    u.ll = val;
2565 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2566 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2567 0487d6a8 j_mayer
        return 0;
2568 0487d6a8 j_mayer
2569 1c97856d aurel32
    return float64_to_int32(u.d, &env->spe_status);
2570 0487d6a8 j_mayer
}
2571 0487d6a8 j_mayer
2572 1c97856d aurel32
uint32_t helper_efdctui (uint64_t val)
2573 0487d6a8 j_mayer
{
2574 0ca9d380 aurel32
    CPU_DoubleU u;
2575 0487d6a8 j_mayer
2576 0ca9d380 aurel32
    u.ll = val;
2577 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2578 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2579 0487d6a8 j_mayer
        return 0;
2580 0487d6a8 j_mayer
2581 1c97856d aurel32
    return float64_to_uint32(u.d, &env->spe_status);
2582 0487d6a8 j_mayer
}
2583 0487d6a8 j_mayer
2584 1c97856d aurel32
uint32_t helper_efdctsiz (uint64_t val)
2585 0487d6a8 j_mayer
{
2586 0ca9d380 aurel32
    CPU_DoubleU u;
2587 0487d6a8 j_mayer
2588 0ca9d380 aurel32
    u.ll = val;
2589 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2590 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2591 0487d6a8 j_mayer
        return 0;
2592 0487d6a8 j_mayer
2593 1c97856d aurel32
    return float64_to_int32_round_to_zero(u.d, &env->spe_status);
2594 0487d6a8 j_mayer
}
2595 0487d6a8 j_mayer
2596 1c97856d aurel32
uint64_t helper_efdctsidz (uint64_t val)
2597 0487d6a8 j_mayer
{
2598 0ca9d380 aurel32
    CPU_DoubleU u;
2599 0487d6a8 j_mayer
2600 0ca9d380 aurel32
    u.ll = val;
2601 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2602 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2603 0487d6a8 j_mayer
        return 0;
2604 0487d6a8 j_mayer
2605 1c97856d aurel32
    return float64_to_int64_round_to_zero(u.d, &env->spe_status);
2606 0487d6a8 j_mayer
}
2607 0487d6a8 j_mayer
2608 1c97856d aurel32
uint32_t helper_efdctuiz (uint64_t val)
2609 0487d6a8 j_mayer
{
2610 1c97856d aurel32
    CPU_DoubleU u;
2611 0487d6a8 j_mayer
2612 1c97856d aurel32
    u.ll = val;
2613 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
2614 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2615 1c97856d aurel32
        return 0;
2616 0487d6a8 j_mayer
2617 1c97856d aurel32
    return float64_to_uint32_round_to_zero(u.d, &env->spe_status);
2618 0487d6a8 j_mayer
}
2619 0487d6a8 j_mayer
2620 1c97856d aurel32
uint64_t helper_efdctuidz (uint64_t val)
2621 0487d6a8 j_mayer
{
2622 1c97856d aurel32
    CPU_DoubleU u;
2623 0487d6a8 j_mayer
2624 1c97856d aurel32
    u.ll = val;
2625 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
2626 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2627 1c97856d aurel32
        return 0;
2628 0487d6a8 j_mayer
2629 1c97856d aurel32
    return float64_to_uint64_round_to_zero(u.d, &env->spe_status);
2630 0487d6a8 j_mayer
}
2631 0487d6a8 j_mayer
2632 1c97856d aurel32
uint64_t helper_efdcfsf (uint32_t val)
2633 0487d6a8 j_mayer
{
2634 0ca9d380 aurel32
    CPU_DoubleU u;
2635 0487d6a8 j_mayer
    float64 tmp;
2636 0487d6a8 j_mayer
2637 0ca9d380 aurel32
    u.d = int32_to_float64(val, &env->spe_status);
2638 0487d6a8 j_mayer
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2639 0ca9d380 aurel32
    u.d = float64_div(u.d, tmp, &env->spe_status);
2640 0487d6a8 j_mayer
2641 0ca9d380 aurel32
    return u.ll;
2642 0487d6a8 j_mayer
}
2643 0487d6a8 j_mayer
2644 1c97856d aurel32
uint64_t helper_efdcfuf (uint32_t val)
2645 0487d6a8 j_mayer
{
2646 0ca9d380 aurel32
    CPU_DoubleU u;
2647 0487d6a8 j_mayer
    float64 tmp;
2648 0487d6a8 j_mayer
2649 0ca9d380 aurel32
    u.d = uint32_to_float64(val, &env->spe_status);
2650 0487d6a8 j_mayer
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2651 0ca9d380 aurel32
    u.d = float64_div(u.d, tmp, &env->spe_status);
2652 0487d6a8 j_mayer
2653 0ca9d380 aurel32
    return u.ll;
2654 0487d6a8 j_mayer
}
2655 0487d6a8 j_mayer
2656 1c97856d aurel32
uint32_t helper_efdctsf (uint64_t val)
2657 0487d6a8 j_mayer
{
2658 0ca9d380 aurel32
    CPU_DoubleU u;
2659 0487d6a8 j_mayer
    float64 tmp;
2660 0487d6a8 j_mayer
2661 0ca9d380 aurel32
    u.ll = val;
2662 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2663 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2664 0487d6a8 j_mayer
        return 0;
2665 0487d6a8 j_mayer
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2666 0ca9d380 aurel32
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2667 0487d6a8 j_mayer
2668 0ca9d380 aurel32
    return float64_to_int32(u.d, &env->spe_status);
2669 0487d6a8 j_mayer
}
2670 0487d6a8 j_mayer
2671 1c97856d aurel32
uint32_t helper_efdctuf (uint64_t val)
2672 0487d6a8 j_mayer
{
2673 0ca9d380 aurel32
    CPU_DoubleU u;
2674 0487d6a8 j_mayer
    float64 tmp;
2675 0487d6a8 j_mayer
2676 0ca9d380 aurel32
    u.ll = val;
2677 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2678 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2679 0487d6a8 j_mayer
        return 0;
2680 0487d6a8 j_mayer
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2681 0ca9d380 aurel32
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2682 0487d6a8 j_mayer
2683 0ca9d380 aurel32
    return float64_to_uint32(u.d, &env->spe_status);
2684 0487d6a8 j_mayer
}
2685 0487d6a8 j_mayer
2686 1c97856d aurel32
uint32_t helper_efscfd (uint64_t val)
2687 0487d6a8 j_mayer
{
2688 0ca9d380 aurel32
    CPU_DoubleU u1;
2689 0ca9d380 aurel32
    CPU_FloatU u2;
2690 0487d6a8 j_mayer
2691 0ca9d380 aurel32
    u1.ll = val;
2692 0ca9d380 aurel32
    u2.f = float64_to_float32(u1.d, &env->spe_status);
2693 0487d6a8 j_mayer
2694 0ca9d380 aurel32
    return u2.l;
2695 0487d6a8 j_mayer
}
2696 0487d6a8 j_mayer
2697 1c97856d aurel32
uint64_t helper_efdcfs (uint32_t val)
2698 0487d6a8 j_mayer
{
2699 0ca9d380 aurel32
    CPU_DoubleU u2;
2700 0ca9d380 aurel32
    CPU_FloatU u1;
2701 0487d6a8 j_mayer
2702 0ca9d380 aurel32
    u1.l = val;
2703 0ca9d380 aurel32
    u2.d = float32_to_float64(u1.f, &env->spe_status);
2704 0487d6a8 j_mayer
2705 0ca9d380 aurel32
    return u2.ll;
2706 0487d6a8 j_mayer
}
2707 0487d6a8 j_mayer
2708 1c97856d aurel32
/* Double precision fixed-point arithmetic */
2709 1c97856d aurel32
uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
2710 0487d6a8 j_mayer
{
2711 1c97856d aurel32
    CPU_DoubleU u1, u2;
2712 1c97856d aurel32
    u1.ll = op1;
2713 1c97856d aurel32
    u2.ll = op2;
2714 1c97856d aurel32
    u1.d = float64_add(u1.d, u2.d, &env->spe_status);
2715 1c97856d aurel32
    return u1.ll;
2716 0487d6a8 j_mayer
}
2717 0487d6a8 j_mayer
2718 1c97856d aurel32
uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
2719 0487d6a8 j_mayer
{
2720 1c97856d aurel32
    CPU_DoubleU u1, u2;
2721 1c97856d aurel32
    u1.ll = op1;
2722 1c97856d aurel32
    u2.ll = op2;
2723 1c97856d aurel32
    u1.d = float64_sub(u1.d, u2.d, &env->spe_status);
2724 1c97856d aurel32
    return u1.ll;
2725 0487d6a8 j_mayer
}
2726 0487d6a8 j_mayer
2727 1c97856d aurel32
uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
2728 0487d6a8 j_mayer
{
2729 1c97856d aurel32
    CPU_DoubleU u1, u2;
2730 1c97856d aurel32
    u1.ll = op1;
2731 1c97856d aurel32
    u2.ll = op2;
2732 1c97856d aurel32
    u1.d = float64_mul(u1.d, u2.d, &env->spe_status);
2733 1c97856d aurel32
    return u1.ll;
2734 0487d6a8 j_mayer
}
2735 0487d6a8 j_mayer
2736 1c97856d aurel32
uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
2737 0487d6a8 j_mayer
{
2738 1c97856d aurel32
    CPU_DoubleU u1, u2;
2739 1c97856d aurel32
    u1.ll = op1;
2740 1c97856d aurel32
    u2.ll = op2;
2741 1c97856d aurel32
    u1.d = float64_div(u1.d, u2.d, &env->spe_status);
2742 1c97856d aurel32
    return u1.ll;
2743 0487d6a8 j_mayer
}
2744 0487d6a8 j_mayer
2745 1c97856d aurel32
/* Double precision floating point helpers */
2746 1c97856d aurel32
uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
2747 0487d6a8 j_mayer
{
2748 1c97856d aurel32
    CPU_DoubleU u1, u2;
2749 1c97856d aurel32
    u1.ll = op1;
2750 1c97856d aurel32
    u2.ll = op2;
2751 1c97856d aurel32
    return float64_lt(u1.d, u2.d, &env->spe_status) ? 4 : 0;
2752 0487d6a8 j_mayer
}
2753 0487d6a8 j_mayer
2754 1c97856d aurel32
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
2755 0487d6a8 j_mayer
{
2756 1c97856d aurel32
    CPU_DoubleU u1, u2;
2757 1c97856d aurel32
    u1.ll = op1;
2758 1c97856d aurel32
    u2.ll = op2;
2759 1c97856d aurel32
    return float64_le(u1.d, u2.d, &env->spe_status) ? 0 : 4;
2760 0487d6a8 j_mayer
}
2761 0487d6a8 j_mayer
2762 1c97856d aurel32
uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
2763 0487d6a8 j_mayer
{
2764 1c97856d aurel32
    CPU_DoubleU u1, u2;
2765 1c97856d aurel32
    u1.ll = op1;
2766 1c97856d aurel32
    u2.ll = op2;
2767 1c97856d aurel32
    return float64_eq(u1.d, u2.d, &env->spe_status) ? 4 : 0;
2768 0487d6a8 j_mayer
}
2769 0487d6a8 j_mayer
2770 1c97856d aurel32
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
2771 0487d6a8 j_mayer
{
2772 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2773 1c97856d aurel32
    return helper_efdtstlt(op1, op2);
2774 0487d6a8 j_mayer
}
2775 0487d6a8 j_mayer
2776 1c97856d aurel32
uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
2777 1c97856d aurel32
{
2778 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2779 1c97856d aurel32
    return helper_efdtstgt(op1, op2);
2780 1c97856d aurel32
}
2781 0487d6a8 j_mayer
2782 1c97856d aurel32
uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
2783 1c97856d aurel32
{
2784 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2785 1c97856d aurel32
    return helper_efdtsteq(op1, op2);
2786 1c97856d aurel32
}
2787 0487d6a8 j_mayer
2788 fdabc366 bellard
/*****************************************************************************/
2789 fdabc366 bellard
/* Softmmu support */
2790 fdabc366 bellard
#if !defined (CONFIG_USER_ONLY)
2791 fdabc366 bellard
2792 fdabc366 bellard
#define MMUSUFFIX _mmu
2793 fdabc366 bellard
2794 fdabc366 bellard
#define SHIFT 0
2795 fdabc366 bellard
#include "softmmu_template.h"
2796 fdabc366 bellard
2797 fdabc366 bellard
#define SHIFT 1
2798 fdabc366 bellard
#include "softmmu_template.h"
2799 fdabc366 bellard
2800 fdabc366 bellard
#define SHIFT 2
2801 fdabc366 bellard
#include "softmmu_template.h"
2802 fdabc366 bellard
2803 fdabc366 bellard
#define SHIFT 3
2804 fdabc366 bellard
#include "softmmu_template.h"
2805 fdabc366 bellard
2806 fdabc366 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
2807 fdabc366 bellard
   NULL, it means that the function was called in C code (i.e. not
2808 fdabc366 bellard
   from generated code or from helper.c) */
2809 fdabc366 bellard
/* XXX: fix it to restore all registers */
2810 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2811 fdabc366 bellard
{
2812 fdabc366 bellard
    TranslationBlock *tb;
2813 fdabc366 bellard
    CPUState *saved_env;
2814 44f8625d bellard
    unsigned long pc;
2815 fdabc366 bellard
    int ret;
2816 fdabc366 bellard
2817 fdabc366 bellard
    /* XXX: hack to restore env in all cases, even if not called from
2818 fdabc366 bellard
       generated code */
2819 fdabc366 bellard
    saved_env = env;
2820 fdabc366 bellard
    env = cpu_single_env;
2821 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2822 76a66253 j_mayer
    if (unlikely(ret != 0)) {
2823 fdabc366 bellard
        if (likely(retaddr)) {
2824 fdabc366 bellard
            /* now we have a real cpu fault */
2825 44f8625d bellard
            pc = (unsigned long)retaddr;
2826 fdabc366 bellard
            tb = tb_find_pc(pc);
2827 fdabc366 bellard
            if (likely(tb)) {
2828 fdabc366 bellard
                /* the PC is inside the translated code. It means that we have
2829 fdabc366 bellard
                   a virtual CPU fault */
2830 fdabc366 bellard
                cpu_restore_state(tb, env, pc, NULL);
2831 76a66253 j_mayer
            }
2832 fdabc366 bellard
        }
2833 e06fcd75 aurel32
        helper_raise_exception_err(env->exception_index, env->error_code);
2834 fdabc366 bellard
    }
2835 fdabc366 bellard
    env = saved_env;
2836 9a64fbe4 bellard
}
2837 9a64fbe4 bellard
2838 74d37793 aurel32
/* Segment registers load and store */
2839 74d37793 aurel32
target_ulong helper_load_sr (target_ulong sr_num)
2840 74d37793 aurel32
{
2841 74d37793 aurel32
    return env->sr[sr_num];
2842 74d37793 aurel32
}
2843 74d37793 aurel32
2844 74d37793 aurel32
void helper_store_sr (target_ulong sr_num, target_ulong val)
2845 74d37793 aurel32
{
2846 45d827d2 aurel32
    ppc_store_sr(env, sr_num, val);
2847 74d37793 aurel32
}
2848 74d37793 aurel32
2849 74d37793 aurel32
/* SLB management */
2850 74d37793 aurel32
#if defined(TARGET_PPC64)
2851 74d37793 aurel32
target_ulong helper_load_slb (target_ulong slb_nr)
2852 74d37793 aurel32
{
2853 74d37793 aurel32
    return ppc_load_slb(env, slb_nr);
2854 74d37793 aurel32
}
2855 74d37793 aurel32
2856 74d37793 aurel32
void helper_store_slb (target_ulong slb_nr, target_ulong rs)
2857 74d37793 aurel32
{
2858 74d37793 aurel32
    ppc_store_slb(env, slb_nr, rs);
2859 74d37793 aurel32
}
2860 74d37793 aurel32
2861 74d37793 aurel32
void helper_slbia (void)
2862 74d37793 aurel32
{
2863 74d37793 aurel32
    ppc_slb_invalidate_all(env);
2864 74d37793 aurel32
}
2865 74d37793 aurel32
2866 74d37793 aurel32
void helper_slbie (target_ulong addr)
2867 74d37793 aurel32
{
2868 74d37793 aurel32
    ppc_slb_invalidate_one(env, addr);
2869 74d37793 aurel32
}
2870 74d37793 aurel32
2871 74d37793 aurel32
#endif /* defined(TARGET_PPC64) */
2872 74d37793 aurel32
2873 74d37793 aurel32
/* TLB management */
2874 74d37793 aurel32
void helper_tlbia (void)
2875 74d37793 aurel32
{
2876 74d37793 aurel32
    ppc_tlb_invalidate_all(env);
2877 74d37793 aurel32
}
2878 74d37793 aurel32
2879 74d37793 aurel32
void helper_tlbie (target_ulong addr)
2880 74d37793 aurel32
{
2881 74d37793 aurel32
    ppc_tlb_invalidate_one(env, addr);
2882 74d37793 aurel32
}
2883 74d37793 aurel32
2884 76a66253 j_mayer
/* Software driven TLBs management */
2885 76a66253 j_mayer
/* PowerPC 602/603 software TLB load instructions helpers */
2886 74d37793 aurel32
static void do_6xx_tlb (target_ulong new_EPN, int is_code)
2887 76a66253 j_mayer
{
2888 76a66253 j_mayer
    target_ulong RPN, CMP, EPN;
2889 76a66253 j_mayer
    int way;
2890 d9bce9d9 j_mayer
2891 76a66253 j_mayer
    RPN = env->spr[SPR_RPA];
2892 76a66253 j_mayer
    if (is_code) {
2893 76a66253 j_mayer
        CMP = env->spr[SPR_ICMP];
2894 76a66253 j_mayer
        EPN = env->spr[SPR_IMISS];
2895 76a66253 j_mayer
    } else {
2896 76a66253 j_mayer
        CMP = env->spr[SPR_DCMP];
2897 76a66253 j_mayer
        EPN = env->spr[SPR_DMISS];
2898 76a66253 j_mayer
    }
2899 76a66253 j_mayer
    way = (env->spr[SPR_SRR1] >> 17) & 1;
2900 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2901 76a66253 j_mayer
    if (loglevel != 0) {
2902 0e69805a aurel32
        fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
2903 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
2904 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
2905 76a66253 j_mayer
    }
2906 76a66253 j_mayer
#endif
2907 76a66253 j_mayer
    /* Store this TLB */
2908 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2909 d9bce9d9 j_mayer
                     way, is_code, CMP, RPN);
2910 76a66253 j_mayer
}
2911 76a66253 j_mayer
2912 74d37793 aurel32
void helper_6xx_tlbd (target_ulong EPN)
2913 0f3955e2 aurel32
{
2914 74d37793 aurel32
    do_6xx_tlb(EPN, 0);
2915 0f3955e2 aurel32
}
2916 0f3955e2 aurel32
2917 74d37793 aurel32
void helper_6xx_tlbi (target_ulong EPN)
2918 0f3955e2 aurel32
{
2919 74d37793 aurel32
    do_6xx_tlb(EPN, 1);
2920 0f3955e2 aurel32
}
2921 0f3955e2 aurel32
2922 0f3955e2 aurel32
/* PowerPC 74xx software TLB load instructions helpers */
2923 74d37793 aurel32
static void do_74xx_tlb (target_ulong new_EPN, int is_code)
2924 7dbe11ac j_mayer
{
2925 7dbe11ac j_mayer
    target_ulong RPN, CMP, EPN;
2926 7dbe11ac j_mayer
    int way;
2927 7dbe11ac j_mayer
2928 7dbe11ac j_mayer
    RPN = env->spr[SPR_PTELO];
2929 7dbe11ac j_mayer
    CMP = env->spr[SPR_PTEHI];
2930 7dbe11ac j_mayer
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2931 7dbe11ac j_mayer
    way = env->spr[SPR_TLBMISS] & 0x3;
2932 7dbe11ac j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2933 7dbe11ac j_mayer
    if (loglevel != 0) {
2934 0e69805a aurel32
        fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
2935 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
2936 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
2937 7dbe11ac j_mayer
    }
2938 7dbe11ac j_mayer
#endif
2939 7dbe11ac j_mayer
    /* Store this TLB */
2940 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2941 7dbe11ac j_mayer
                     way, is_code, CMP, RPN);
2942 7dbe11ac j_mayer
}
2943 7dbe11ac j_mayer
2944 74d37793 aurel32
void helper_74xx_tlbd (target_ulong EPN)
2945 0f3955e2 aurel32
{
2946 74d37793 aurel32
    do_74xx_tlb(EPN, 0);
2947 0f3955e2 aurel32
}
2948 0f3955e2 aurel32
2949 74d37793 aurel32
void helper_74xx_tlbi (target_ulong EPN)
2950 0f3955e2 aurel32
{
2951 74d37793 aurel32
    do_74xx_tlb(EPN, 1);
2952 0f3955e2 aurel32
}
2953 0f3955e2 aurel32
2954 a11b8151 j_mayer
static always_inline target_ulong booke_tlb_to_page_size (int size)
2955 a8dea12f j_mayer
{
2956 a8dea12f j_mayer
    return 1024 << (2 * size);
2957 a8dea12f j_mayer
}
2958 a8dea12f j_mayer
2959 a11b8151 j_mayer
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
2960 a8dea12f j_mayer
{
2961 a8dea12f j_mayer
    int size;
2962 a8dea12f j_mayer
2963 a8dea12f j_mayer
    switch (page_size) {
2964 a8dea12f j_mayer
    case 0x00000400UL:
2965 a8dea12f j_mayer
        size = 0x0;
2966 a8dea12f j_mayer
        break;
2967 a8dea12f j_mayer
    case 0x00001000UL:
2968 a8dea12f j_mayer
        size = 0x1;
2969 a8dea12f j_mayer
        break;
2970 a8dea12f j_mayer
    case 0x00004000UL:
2971 a8dea12f j_mayer
        size = 0x2;
2972 a8dea12f j_mayer
        break;
2973 a8dea12f j_mayer
    case 0x00010000UL:
2974 a8dea12f j_mayer
        size = 0x3;
2975 a8dea12f j_mayer
        break;
2976 a8dea12f j_mayer
    case 0x00040000UL:
2977 a8dea12f j_mayer
        size = 0x4;
2978 a8dea12f j_mayer
        break;
2979 a8dea12f j_mayer
    case 0x00100000UL:
2980 a8dea12f j_mayer
        size = 0x5;
2981 a8dea12f j_mayer
        break;
2982 a8dea12f j_mayer
    case 0x00400000UL:
2983 a8dea12f j_mayer
        size = 0x6;
2984 a8dea12f j_mayer
        break;
2985 a8dea12f j_mayer
    case 0x01000000UL:
2986 a8dea12f j_mayer
        size = 0x7;
2987 a8dea12f j_mayer
        break;
2988 a8dea12f j_mayer
    case 0x04000000UL:
2989 a8dea12f j_mayer
        size = 0x8;
2990 a8dea12f j_mayer
        break;
2991 a8dea12f j_mayer
    case 0x10000000UL:
2992 a8dea12f j_mayer
        size = 0x9;
2993 a8dea12f j_mayer
        break;
2994 a8dea12f j_mayer
    case 0x40000000UL:
2995 a8dea12f j_mayer
        size = 0xA;
2996 a8dea12f j_mayer
        break;
2997 a8dea12f j_mayer
#if defined (TARGET_PPC64)
2998 a8dea12f j_mayer
    case 0x000100000000ULL:
2999 a8dea12f j_mayer
        size = 0xB;
3000 a8dea12f j_mayer
        break;
3001 a8dea12f j_mayer
    case 0x000400000000ULL:
3002 a8dea12f j_mayer
        size = 0xC;
3003 a8dea12f j_mayer
        break;
3004 a8dea12f j_mayer
    case 0x001000000000ULL:
3005 a8dea12f j_mayer
        size = 0xD;
3006 a8dea12f j_mayer
        break;
3007 a8dea12f j_mayer
    case 0x004000000000ULL:
3008 a8dea12f j_mayer
        size = 0xE;
3009 a8dea12f j_mayer
        break;
3010 a8dea12f j_mayer
    case 0x010000000000ULL:
3011 a8dea12f j_mayer
        size = 0xF;
3012 a8dea12f j_mayer
        break;
3013 a8dea12f j_mayer
#endif
3014 a8dea12f j_mayer
    default:
3015 a8dea12f j_mayer
        size = -1;
3016 a8dea12f j_mayer
        break;
3017 a8dea12f j_mayer
    }
3018 a8dea12f j_mayer
3019 a8dea12f j_mayer
    return size;
3020 a8dea12f j_mayer
}
3021 a8dea12f j_mayer
3022 76a66253 j_mayer
/* Helpers for 4xx TLB management */
3023 74d37793 aurel32
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
3024 76a66253 j_mayer
{
3025 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3026 74d37793 aurel32
    target_ulong ret;
3027 a8dea12f j_mayer
    int size;
3028 76a66253 j_mayer
3029 74d37793 aurel32
    entry &= 0x3F;
3030 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3031 74d37793 aurel32
    ret = tlb->EPN;
3032 a8dea12f j_mayer
    if (tlb->prot & PAGE_VALID)
3033 74d37793 aurel32
        ret |= 0x400;
3034 a8dea12f j_mayer
    size = booke_page_size_to_tlb(tlb->size);
3035 a8dea12f j_mayer
    if (size < 0 || size > 0x7)
3036 a8dea12f j_mayer
        size = 1;
3037 74d37793 aurel32
    ret |= size << 7;
3038 a8dea12f j_mayer
    env->spr[SPR_40x_PID] = tlb->PID;
3039 74d37793 aurel32
    return ret;
3040 76a66253 j_mayer
}
3041 76a66253 j_mayer
3042 74d37793 aurel32
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
3043 76a66253 j_mayer
{
3044 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3045 74d37793 aurel32
    target_ulong ret;
3046 76a66253 j_mayer
3047 74d37793 aurel32
    entry &= 0x3F;
3048 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3049 74d37793 aurel32
    ret = tlb->RPN;
3050 a8dea12f j_mayer
    if (tlb->prot & PAGE_EXEC)
3051 74d37793 aurel32
        ret |= 0x200;
3052 a8dea12f j_mayer
    if (tlb->prot & PAGE_WRITE)
3053 74d37793 aurel32
        ret |= 0x100;
3054 74d37793 aurel32
    return ret;
3055 76a66253 j_mayer
}
3056 76a66253 j_mayer
3057 74d37793 aurel32
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
3058 76a66253 j_mayer
{
3059 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3060 76a66253 j_mayer
    target_ulong page, end;
3061 76a66253 j_mayer
3062 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3063 6b80055d j_mayer
    if (loglevel != 0) {
3064 0e69805a aurel32
        fprintf(logfile, "%s entry %d val " ADDRX "\n", __func__, (int)entry, val);
3065 c55e9aef j_mayer
    }
3066 c55e9aef j_mayer
#endif
3067 74d37793 aurel32
    entry &= 0x3F;
3068 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3069 76a66253 j_mayer
    /* Invalidate previous TLB (if it's valid) */
3070 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
3071 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
3072 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3073 6b80055d j_mayer
        if (loglevel != 0) {
3074 c55e9aef j_mayer
            fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
3075 74d37793 aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3076 c55e9aef j_mayer
        }
3077 c55e9aef j_mayer
#endif
3078 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3079 76a66253 j_mayer
            tlb_flush_page(env, page);
3080 76a66253 j_mayer
    }
3081 74d37793 aurel32
    tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
3082 c294fc58 j_mayer
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
3083 c294fc58 j_mayer
     * If this ever occurs, one should use the ppcemb target instead
3084 c294fc58 j_mayer
     * of the ppc or ppc64 one
3085 c294fc58 j_mayer
     */
3086 74d37793 aurel32
    if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
3087 71c8b8fd j_mayer
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
3088 71c8b8fd j_mayer
                  "are not supported (%d)\n",
3089 74d37793 aurel32
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
3090 c294fc58 j_mayer
    }
3091 74d37793 aurel32
    tlb->EPN = val & ~(tlb->size - 1);
3092 74d37793 aurel32
    if (val & 0x40)
3093 76a66253 j_mayer
        tlb->prot |= PAGE_VALID;
3094 76a66253 j_mayer
    else
3095 76a66253 j_mayer
        tlb->prot &= ~PAGE_VALID;
3096 74d37793 aurel32
    if (val & 0x20) {
3097 c294fc58 j_mayer
        /* XXX: TO BE FIXED */
3098 c294fc58 j_mayer
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
3099 c294fc58 j_mayer
    }
3100 c55e9aef j_mayer
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
3101 74d37793 aurel32
    tlb->attr = val & 0xFF;
3102 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3103 c294fc58 j_mayer
    if (loglevel != 0) {
3104 c294fc58 j_mayer
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3105 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3106 0e69805a aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3107 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
3108 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3109 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3110 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3111 c55e9aef j_mayer
    }
3112 c55e9aef j_mayer
#endif
3113 76a66253 j_mayer
    /* Invalidate new TLB (if valid) */
3114 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
3115 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
3116 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3117 6b80055d j_mayer
        if (loglevel != 0) {
3118 c55e9aef j_mayer
            fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
3119 0e69805a aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3120 c55e9aef j_mayer
        }
3121 c55e9aef j_mayer
#endif
3122 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3123 76a66253 j_mayer
            tlb_flush_page(env, page);
3124 76a66253 j_mayer
    }
3125 76a66253 j_mayer
}
3126 76a66253 j_mayer
3127 74d37793 aurel32
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
3128 76a66253 j_mayer
{
3129 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
3130 76a66253 j_mayer
3131 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3132 6b80055d j_mayer
    if (loglevel != 0) {
3133 0e69805a aurel32
        fprintf(logfile, "%s entry %i val " ADDRX "\n", __func__, (int)entry, val);
3134 c55e9aef j_mayer
    }
3135 c55e9aef j_mayer
#endif
3136 74d37793 aurel32
    entry &= 0x3F;
3137 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3138 74d37793 aurel32
    tlb->RPN = val & 0xFFFFFC00;
3139 76a66253 j_mayer
    tlb->prot = PAGE_READ;
3140 74d37793 aurel32
    if (val & 0x200)
3141 76a66253 j_mayer
        tlb->prot |= PAGE_EXEC;
3142 74d37793 aurel32
    if (val & 0x100)
3143 76a66253 j_mayer
        tlb->prot |= PAGE_WRITE;
3144 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3145 6b80055d j_mayer
    if (loglevel != 0) {
3146 6b80055d j_mayer
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3147 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3148 74d37793 aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3149 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
3150 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3151 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3152 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3153 c55e9aef j_mayer
    }
3154 c55e9aef j_mayer
#endif
3155 76a66253 j_mayer
}
3156 5eb7995e j_mayer
3157 74d37793 aurel32
target_ulong helper_4xx_tlbsx (target_ulong address)
3158 74d37793 aurel32
{
3159 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
3160 74d37793 aurel32
}
3161 74d37793 aurel32
3162 a4bb6c3e j_mayer
/* PowerPC 440 TLB management */
3163 74d37793 aurel32
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
3164 5eb7995e j_mayer
{
3165 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
3166 a4bb6c3e j_mayer
    target_ulong EPN, RPN, size;
3167 5eb7995e j_mayer
    int do_flush_tlbs;
3168 5eb7995e j_mayer
3169 5eb7995e j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3170 5eb7995e j_mayer
    if (loglevel != 0) {
3171 0e69805a aurel32
        fprintf(logfile, "%s word %d entry %d value " ADDRX "\n",
3172 0e69805a aurel32
                __func__, word, (int)entry, value);
3173 5eb7995e j_mayer
    }
3174 5eb7995e j_mayer
#endif
3175 5eb7995e j_mayer
    do_flush_tlbs = 0;
3176 74d37793 aurel32
    entry &= 0x3F;
3177 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3178 a4bb6c3e j_mayer
    switch (word) {
3179 a4bb6c3e j_mayer
    default:
3180 a4bb6c3e j_mayer
        /* Just here to please gcc */
3181 a4bb6c3e j_mayer
    case 0:
3182 74d37793 aurel32
        EPN = value & 0xFFFFFC00;
3183 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
3184 5eb7995e j_mayer
            do_flush_tlbs = 1;
3185 a4bb6c3e j_mayer
        tlb->EPN = EPN;
3186 74d37793 aurel32
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
3187 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
3188 a4bb6c3e j_mayer
            do_flush_tlbs = 1;
3189 a4bb6c3e j_mayer
        tlb->size = size;
3190 a4bb6c3e j_mayer
        tlb->attr &= ~0x1;
3191 74d37793 aurel32
        tlb->attr |= (value >> 8) & 1;
3192 74d37793 aurel32
        if (value & 0x200) {
3193 a4bb6c3e j_mayer
            tlb->prot |= PAGE_VALID;
3194 a4bb6c3e j_mayer
        } else {
3195 a4bb6c3e j_mayer
            if (tlb->prot & PAGE_VALID) {
3196 a4bb6c3e j_mayer
                tlb->prot &= ~PAGE_VALID;
3197 a4bb6c3e j_mayer
                do_flush_tlbs = 1;
3198 a4bb6c3e j_mayer
            }
3199 5eb7995e j_mayer
        }
3200 a4bb6c3e j_mayer
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
3201 a4bb6c3e j_mayer
        if (do_flush_tlbs)
3202 a4bb6c3e j_mayer
            tlb_flush(env, 1);
3203 a4bb6c3e j_mayer
        break;
3204 a4bb6c3e j_mayer
    case 1:
3205 74d37793 aurel32
        RPN = value & 0xFFFFFC0F;
3206 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
3207 a4bb6c3e j_mayer
            tlb_flush(env, 1);
3208 a4bb6c3e j_mayer
        tlb->RPN = RPN;
3209 a4bb6c3e j_mayer
        break;
3210 a4bb6c3e j_mayer
    case 2:
3211 74d37793 aurel32
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
3212 a4bb6c3e j_mayer
        tlb->prot = tlb->prot & PAGE_VALID;
3213 74d37793 aurel32
        if (value & 0x1)
3214 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ << 4;
3215 74d37793 aurel32
        if (value & 0x2)
3216 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE << 4;
3217 74d37793 aurel32
        if (value & 0x4)
3218 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC << 4;
3219 74d37793 aurel32
        if (value & 0x8)
3220 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ;
3221 74d37793 aurel32
        if (value & 0x10)
3222 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE;
3223 74d37793 aurel32
        if (value & 0x20)
3224 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC;
3225 a4bb6c3e j_mayer
        break;
3226 5eb7995e j_mayer
    }
3227 5eb7995e j_mayer
}
3228 5eb7995e j_mayer
3229 74d37793 aurel32
target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
3230 5eb7995e j_mayer
{
3231 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
3232 74d37793 aurel32
    target_ulong ret;
3233 5eb7995e j_mayer
    int size;
3234 5eb7995e j_mayer
3235 74d37793 aurel32
    entry &= 0x3F;
3236 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3237 a4bb6c3e j_mayer
    switch (word) {
3238 a4bb6c3e j_mayer
    default:
3239 a4bb6c3e j_mayer
        /* Just here to please gcc */
3240 a4bb6c3e j_mayer
    case 0:
3241 74d37793 aurel32
        ret = tlb->EPN;
3242 a4bb6c3e j_mayer
        size = booke_page_size_to_tlb(tlb->size);
3243 a4bb6c3e j_mayer
        if (size < 0 || size > 0xF)
3244 a4bb6c3e j_mayer
            size = 1;
3245 74d37793 aurel32
        ret |= size << 4;
3246 a4bb6c3e j_mayer
        if (tlb->attr & 0x1)
3247 74d37793 aurel32
            ret |= 0x100;
3248 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_VALID)
3249 74d37793 aurel32
            ret |= 0x200;
3250 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
3251 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] |= tlb->PID;
3252 a4bb6c3e j_mayer
        break;
3253 a4bb6c3e j_mayer
    case 1:
3254 74d37793 aurel32
        ret = tlb->RPN;
3255 a4bb6c3e j_mayer
        break;
3256 a4bb6c3e j_mayer
    case 2:
3257 74d37793 aurel32
        ret = tlb->attr & ~0x1;
3258 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_READ << 4))
3259 74d37793 aurel32
            ret |= 0x1;
3260 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_WRITE << 4))
3261 74d37793 aurel32
            ret |= 0x2;
3262 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_EXEC << 4))
3263 74d37793 aurel32
            ret |= 0x4;
3264 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_READ)
3265 74d37793 aurel32
            ret |= 0x8;
3266 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_WRITE)
3267 74d37793 aurel32
            ret |= 0x10;
3268 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_EXEC)
3269 74d37793 aurel32
            ret |= 0x20;
3270 a4bb6c3e j_mayer
        break;
3271 a4bb6c3e j_mayer
    }
3272 74d37793 aurel32
    return ret;
3273 5eb7995e j_mayer
}
3274 74d37793 aurel32
3275 74d37793 aurel32
target_ulong helper_440_tlbsx (target_ulong address)
3276 74d37793 aurel32
{
3277 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
3278 74d37793 aurel32
}
3279 74d37793 aurel32
3280 76a66253 j_mayer
#endif /* !CONFIG_USER_ONLY */