Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 01feec08

History | View | Annotate | Download (85 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 9a64fbe4 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 9a64fbe4 bellard
 */
20 9a64fbe4 bellard
#include "exec.h"
21 603fccce j_mayer
#include "host-utils.h"
22 a7812ae4 pbrook
#include "helper.h"
23 9a64fbe4 bellard
24 0411a972 j_mayer
#include "helper_regs.h"
25 0487d6a8 j_mayer
26 fdabc366 bellard
//#define DEBUG_OP
27 fdabc366 bellard
//#define DEBUG_EXCEPTIONS
28 76a66253 j_mayer
//#define DEBUG_SOFTWARE_TLB
29 fdabc366 bellard
30 9a64fbe4 bellard
/*****************************************************************************/
31 9a64fbe4 bellard
/* Exceptions processing helpers */
32 9a64fbe4 bellard
33 64adab3f aurel32
void helper_raise_exception_err (uint32_t exception, uint32_t error_code)
34 9a64fbe4 bellard
{
35 e06fcd75 aurel32
#if 0
36 e06fcd75 aurel32
    printf("Raise exception %3x code : %d\n", exception, error_code);
37 e06fcd75 aurel32
#endif
38 e06fcd75 aurel32
    env->exception_index = exception;
39 e06fcd75 aurel32
    env->error_code = error_code;
40 e06fcd75 aurel32
    cpu_loop_exit();
41 76a66253 j_mayer
}
42 9fddaa0c bellard
43 e06fcd75 aurel32
void helper_raise_exception (uint32_t exception)
44 9fddaa0c bellard
{
45 e06fcd75 aurel32
    helper_raise_exception_err(exception, 0);
46 9a64fbe4 bellard
}
47 9a64fbe4 bellard
48 9a64fbe4 bellard
/*****************************************************************************/
49 76a66253 j_mayer
/* Registers load and stores */
50 a7812ae4 pbrook
target_ulong helper_load_cr (void)
51 76a66253 j_mayer
{
52 e1571908 aurel32
    return (env->crf[0] << 28) |
53 e1571908 aurel32
           (env->crf[1] << 24) |
54 e1571908 aurel32
           (env->crf[2] << 20) |
55 e1571908 aurel32
           (env->crf[3] << 16) |
56 e1571908 aurel32
           (env->crf[4] << 12) |
57 e1571908 aurel32
           (env->crf[5] << 8) |
58 e1571908 aurel32
           (env->crf[6] << 4) |
59 e1571908 aurel32
           (env->crf[7] << 0);
60 76a66253 j_mayer
}
61 76a66253 j_mayer
62 e1571908 aurel32
void helper_store_cr (target_ulong val, uint32_t mask)
63 76a66253 j_mayer
{
64 76a66253 j_mayer
    int i, sh;
65 76a66253 j_mayer
66 36081602 j_mayer
    for (i = 0, sh = 7; i < 8; i++, sh--) {
67 76a66253 j_mayer
        if (mask & (1 << sh))
68 e1571908 aurel32
            env->crf[i] = (val >> (sh * 4)) & 0xFUL;
69 76a66253 j_mayer
    }
70 76a66253 j_mayer
}
71 76a66253 j_mayer
72 45d827d2 aurel32
/*****************************************************************************/
73 45d827d2 aurel32
/* SPR accesses */
74 45d827d2 aurel32
void helper_load_dump_spr (uint32_t sprn)
75 a496775f j_mayer
{
76 6b80055d j_mayer
    if (loglevel != 0) {
77 a496775f j_mayer
        fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
78 a496775f j_mayer
                sprn, sprn, env->spr[sprn]);
79 a496775f j_mayer
    }
80 a496775f j_mayer
}
81 a496775f j_mayer
82 45d827d2 aurel32
void helper_store_dump_spr (uint32_t sprn)
83 a496775f j_mayer
{
84 6b80055d j_mayer
    if (loglevel != 0) {
85 45d827d2 aurel32
        fprintf(logfile, "Write SPR %d %03x <= " ADDRX "\n",
86 45d827d2 aurel32
                sprn, sprn, env->spr[sprn]);
87 45d827d2 aurel32
    }
88 45d827d2 aurel32
}
89 45d827d2 aurel32
90 45d827d2 aurel32
target_ulong helper_load_tbl (void)
91 45d827d2 aurel32
{
92 45d827d2 aurel32
    return cpu_ppc_load_tbl(env);
93 45d827d2 aurel32
}
94 45d827d2 aurel32
95 45d827d2 aurel32
target_ulong helper_load_tbu (void)
96 45d827d2 aurel32
{
97 45d827d2 aurel32
    return cpu_ppc_load_tbu(env);
98 45d827d2 aurel32
}
99 45d827d2 aurel32
100 45d827d2 aurel32
target_ulong helper_load_atbl (void)
101 45d827d2 aurel32
{
102 45d827d2 aurel32
    return cpu_ppc_load_atbl(env);
103 45d827d2 aurel32
}
104 45d827d2 aurel32
105 45d827d2 aurel32
target_ulong helper_load_atbu (void)
106 45d827d2 aurel32
{
107 45d827d2 aurel32
    return cpu_ppc_load_atbu(env);
108 45d827d2 aurel32
}
109 45d827d2 aurel32
110 45d827d2 aurel32
target_ulong helper_load_601_rtcl (void)
111 45d827d2 aurel32
{
112 45d827d2 aurel32
    return cpu_ppc601_load_rtcl(env);
113 45d827d2 aurel32
}
114 45d827d2 aurel32
115 45d827d2 aurel32
target_ulong helper_load_601_rtcu (void)
116 45d827d2 aurel32
{
117 45d827d2 aurel32
    return cpu_ppc601_load_rtcu(env);
118 45d827d2 aurel32
}
119 45d827d2 aurel32
120 45d827d2 aurel32
#if !defined(CONFIG_USER_ONLY)
121 45d827d2 aurel32
#if defined (TARGET_PPC64)
122 45d827d2 aurel32
void helper_store_asr (target_ulong val)
123 45d827d2 aurel32
{
124 45d827d2 aurel32
    ppc_store_asr(env, val);
125 45d827d2 aurel32
}
126 45d827d2 aurel32
#endif
127 45d827d2 aurel32
128 45d827d2 aurel32
void helper_store_sdr1 (target_ulong val)
129 45d827d2 aurel32
{
130 45d827d2 aurel32
    ppc_store_sdr1(env, val);
131 45d827d2 aurel32
}
132 45d827d2 aurel32
133 45d827d2 aurel32
void helper_store_tbl (target_ulong val)
134 45d827d2 aurel32
{
135 45d827d2 aurel32
    cpu_ppc_store_tbl(env, val);
136 45d827d2 aurel32
}
137 45d827d2 aurel32
138 45d827d2 aurel32
void helper_store_tbu (target_ulong val)
139 45d827d2 aurel32
{
140 45d827d2 aurel32
    cpu_ppc_store_tbu(env, val);
141 45d827d2 aurel32
}
142 45d827d2 aurel32
143 45d827d2 aurel32
void helper_store_atbl (target_ulong val)
144 45d827d2 aurel32
{
145 45d827d2 aurel32
    cpu_ppc_store_atbl(env, val);
146 45d827d2 aurel32
}
147 45d827d2 aurel32
148 45d827d2 aurel32
void helper_store_atbu (target_ulong val)
149 45d827d2 aurel32
{
150 45d827d2 aurel32
    cpu_ppc_store_atbu(env, val);
151 45d827d2 aurel32
}
152 45d827d2 aurel32
153 45d827d2 aurel32
void helper_store_601_rtcl (target_ulong val)
154 45d827d2 aurel32
{
155 45d827d2 aurel32
    cpu_ppc601_store_rtcl(env, val);
156 45d827d2 aurel32
}
157 45d827d2 aurel32
158 45d827d2 aurel32
void helper_store_601_rtcu (target_ulong val)
159 45d827d2 aurel32
{
160 45d827d2 aurel32
    cpu_ppc601_store_rtcu(env, val);
161 45d827d2 aurel32
}
162 45d827d2 aurel32
163 45d827d2 aurel32
target_ulong helper_load_decr (void)
164 45d827d2 aurel32
{
165 45d827d2 aurel32
    return cpu_ppc_load_decr(env);
166 45d827d2 aurel32
}
167 45d827d2 aurel32
168 45d827d2 aurel32
void helper_store_decr (target_ulong val)
169 45d827d2 aurel32
{
170 45d827d2 aurel32
    cpu_ppc_store_decr(env, val);
171 45d827d2 aurel32
}
172 45d827d2 aurel32
173 45d827d2 aurel32
void helper_store_hid0_601 (target_ulong val)
174 45d827d2 aurel32
{
175 45d827d2 aurel32
    target_ulong hid0;
176 45d827d2 aurel32
177 45d827d2 aurel32
    hid0 = env->spr[SPR_HID0];
178 45d827d2 aurel32
    if ((val ^ hid0) & 0x00000008) {
179 45d827d2 aurel32
        /* Change current endianness */
180 45d827d2 aurel32
        env->hflags &= ~(1 << MSR_LE);
181 45d827d2 aurel32
        env->hflags_nmsr &= ~(1 << MSR_LE);
182 45d827d2 aurel32
        env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
183 45d827d2 aurel32
        env->hflags |= env->hflags_nmsr;
184 45d827d2 aurel32
        if (loglevel != 0) {
185 45d827d2 aurel32
            fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
186 45d827d2 aurel32
                    __func__, val & 0x8 ? 'l' : 'b', env->hflags);
187 45d827d2 aurel32
        }
188 a496775f j_mayer
    }
189 45d827d2 aurel32
    env->spr[SPR_HID0] = (uint32_t)val;
190 a496775f j_mayer
}
191 a496775f j_mayer
192 45d827d2 aurel32
void helper_store_403_pbr (uint32_t num, target_ulong value)
193 45d827d2 aurel32
{
194 45d827d2 aurel32
    if (likely(env->pb[num] != value)) {
195 45d827d2 aurel32
        env->pb[num] = value;
196 45d827d2 aurel32
        /* Should be optimized */
197 45d827d2 aurel32
        tlb_flush(env, 1);
198 45d827d2 aurel32
    }
199 45d827d2 aurel32
}
200 45d827d2 aurel32
201 45d827d2 aurel32
target_ulong helper_load_40x_pit (void)
202 45d827d2 aurel32
{
203 45d827d2 aurel32
    return load_40x_pit(env);
204 45d827d2 aurel32
}
205 45d827d2 aurel32
206 45d827d2 aurel32
void helper_store_40x_pit (target_ulong val)
207 45d827d2 aurel32
{
208 45d827d2 aurel32
    store_40x_pit(env, val);
209 45d827d2 aurel32
}
210 45d827d2 aurel32
211 45d827d2 aurel32
void helper_store_40x_dbcr0 (target_ulong val)
212 45d827d2 aurel32
{
213 45d827d2 aurel32
    store_40x_dbcr0(env, val);
214 45d827d2 aurel32
}
215 45d827d2 aurel32
216 45d827d2 aurel32
void helper_store_40x_sler (target_ulong val)
217 45d827d2 aurel32
{
218 45d827d2 aurel32
    store_40x_sler(env, val);
219 45d827d2 aurel32
}
220 45d827d2 aurel32
221 45d827d2 aurel32
void helper_store_booke_tcr (target_ulong val)
222 45d827d2 aurel32
{
223 45d827d2 aurel32
    store_booke_tcr(env, val);
224 45d827d2 aurel32
}
225 45d827d2 aurel32
226 45d827d2 aurel32
void helper_store_booke_tsr (target_ulong val)
227 45d827d2 aurel32
{
228 45d827d2 aurel32
    store_booke_tsr(env, val);
229 45d827d2 aurel32
}
230 45d827d2 aurel32
231 45d827d2 aurel32
void helper_store_ibatu (uint32_t nr, target_ulong val)
232 45d827d2 aurel32
{
233 45d827d2 aurel32
    ppc_store_ibatu(env, nr, val);
234 45d827d2 aurel32
}
235 45d827d2 aurel32
236 45d827d2 aurel32
void helper_store_ibatl (uint32_t nr, target_ulong val)
237 45d827d2 aurel32
{
238 45d827d2 aurel32
    ppc_store_ibatl(env, nr, val);
239 45d827d2 aurel32
}
240 45d827d2 aurel32
241 45d827d2 aurel32
void helper_store_dbatu (uint32_t nr, target_ulong val)
242 45d827d2 aurel32
{
243 45d827d2 aurel32
    ppc_store_dbatu(env, nr, val);
244 45d827d2 aurel32
}
245 45d827d2 aurel32
246 45d827d2 aurel32
void helper_store_dbatl (uint32_t nr, target_ulong val)
247 45d827d2 aurel32
{
248 45d827d2 aurel32
    ppc_store_dbatl(env, nr, val);
249 45d827d2 aurel32
}
250 45d827d2 aurel32
251 45d827d2 aurel32
void helper_store_601_batl (uint32_t nr, target_ulong val)
252 45d827d2 aurel32
{
253 45d827d2 aurel32
    ppc_store_ibatl_601(env, nr, val);
254 45d827d2 aurel32
}
255 45d827d2 aurel32
256 45d827d2 aurel32
void helper_store_601_batu (uint32_t nr, target_ulong val)
257 45d827d2 aurel32
{
258 45d827d2 aurel32
    ppc_store_ibatu_601(env, nr, val);
259 45d827d2 aurel32
}
260 45d827d2 aurel32
#endif
261 45d827d2 aurel32
262 76a66253 j_mayer
/*****************************************************************************/
263 ff4a62cd aurel32
/* Memory load and stores */
264 ff4a62cd aurel32
265 76db3ba4 aurel32
static always_inline target_ulong addr_add(target_ulong addr, target_long arg)
266 ff4a62cd aurel32
{
267 ff4a62cd aurel32
#if defined(TARGET_PPC64)
268 76db3ba4 aurel32
        if (!msr_sf)
269 76db3ba4 aurel32
            return (uint32_t)(addr + arg);
270 ff4a62cd aurel32
        else
271 ff4a62cd aurel32
#endif
272 76db3ba4 aurel32
            return addr + arg;
273 ff4a62cd aurel32
}
274 ff4a62cd aurel32
275 ff4a62cd aurel32
void helper_lmw (target_ulong addr, uint32_t reg)
276 ff4a62cd aurel32
{
277 76db3ba4 aurel32
    for (; reg < 32; reg++) {
278 ff4a62cd aurel32
        if (msr_le)
279 76db3ba4 aurel32
            env->gpr[reg] = bswap32(ldl(addr));
280 ff4a62cd aurel32
        else
281 76db3ba4 aurel32
            env->gpr[reg] = ldl(addr);
282 76db3ba4 aurel32
        addr = addr_add(addr, 4);
283 ff4a62cd aurel32
    }
284 ff4a62cd aurel32
}
285 ff4a62cd aurel32
286 ff4a62cd aurel32
void helper_stmw (target_ulong addr, uint32_t reg)
287 ff4a62cd aurel32
{
288 76db3ba4 aurel32
    for (; reg < 32; reg++) {
289 ff4a62cd aurel32
        if (msr_le)
290 76db3ba4 aurel32
            stl(addr, bswap32((uint32_t)env->gpr[reg]));
291 ff4a62cd aurel32
        else
292 76db3ba4 aurel32
            stl(addr, (uint32_t)env->gpr[reg]);
293 76db3ba4 aurel32
        addr = addr_add(addr, 4);
294 ff4a62cd aurel32
    }
295 ff4a62cd aurel32
}
296 ff4a62cd aurel32
297 dfbc799d aurel32
void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg)
298 dfbc799d aurel32
{
299 dfbc799d aurel32
    int sh;
300 76db3ba4 aurel32
    for (; nb > 3; nb -= 4) {
301 76db3ba4 aurel32
        env->gpr[reg] = ldl(addr);
302 dfbc799d aurel32
        reg = (reg + 1) % 32;
303 76db3ba4 aurel32
        addr = addr_add(addr, 4);
304 dfbc799d aurel32
    }
305 dfbc799d aurel32
    if (unlikely(nb > 0)) {
306 dfbc799d aurel32
        env->gpr[reg] = 0;
307 76db3ba4 aurel32
        for (sh = 24; nb > 0; nb--, sh -= 8) {
308 76db3ba4 aurel32
            env->gpr[reg] |= ldub(addr) << sh;
309 76db3ba4 aurel32
            addr = addr_add(addr, 1);
310 dfbc799d aurel32
        }
311 dfbc799d aurel32
    }
312 dfbc799d aurel32
}
313 dfbc799d aurel32
/* PPC32 specification says we must generate an exception if
314 dfbc799d aurel32
 * rA is in the range of registers to be loaded.
315 dfbc799d aurel32
 * In an other hand, IBM says this is valid, but rA won't be loaded.
316 dfbc799d aurel32
 * For now, I'll follow the spec...
317 dfbc799d aurel32
 */
318 dfbc799d aurel32
void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
319 dfbc799d aurel32
{
320 dfbc799d aurel32
    if (likely(xer_bc != 0)) {
321 dfbc799d aurel32
        if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) ||
322 dfbc799d aurel32
                     (reg < rb && (reg + xer_bc) > rb))) {
323 e06fcd75 aurel32
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
324 e06fcd75 aurel32
                                       POWERPC_EXCP_INVAL |
325 e06fcd75 aurel32
                                       POWERPC_EXCP_INVAL_LSWX);
326 dfbc799d aurel32
        } else {
327 dfbc799d aurel32
            helper_lsw(addr, xer_bc, reg);
328 dfbc799d aurel32
        }
329 dfbc799d aurel32
    }
330 dfbc799d aurel32
}
331 dfbc799d aurel32
332 dfbc799d aurel32
void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg)
333 dfbc799d aurel32
{
334 dfbc799d aurel32
    int sh;
335 76db3ba4 aurel32
    for (; nb > 3; nb -= 4) {
336 76db3ba4 aurel32
        stl(addr, env->gpr[reg]);
337 dfbc799d aurel32
        reg = (reg + 1) % 32;
338 76db3ba4 aurel32
        addr = addr_add(addr, 4);
339 dfbc799d aurel32
    }
340 dfbc799d aurel32
    if (unlikely(nb > 0)) {
341 76db3ba4 aurel32
        for (sh = 24; nb > 0; nb--, sh -= 8)
342 76db3ba4 aurel32
            stb(addr, (env->gpr[reg] >> sh) & 0xFF);
343 76db3ba4 aurel32
            addr = addr_add(addr, 1);
344 dfbc799d aurel32
    }
345 dfbc799d aurel32
}
346 dfbc799d aurel32
347 799a8c8d aurel32
static void do_dcbz(target_ulong addr, int dcache_line_size)
348 799a8c8d aurel32
{
349 76db3ba4 aurel32
    addr &= ~(dcache_line_size - 1);
350 799a8c8d aurel32
    int i;
351 799a8c8d aurel32
    for (i = 0 ; i < dcache_line_size ; i += 4) {
352 dcc532c8 aurel32
        stl(addr + i , 0);
353 799a8c8d aurel32
    }
354 76db3ba4 aurel32
    if (env->reserve == addr)
355 799a8c8d aurel32
        env->reserve = (target_ulong)-1ULL;
356 799a8c8d aurel32
}
357 799a8c8d aurel32
358 799a8c8d aurel32
void helper_dcbz(target_ulong addr)
359 799a8c8d aurel32
{
360 799a8c8d aurel32
    do_dcbz(addr, env->dcache_line_size);
361 799a8c8d aurel32
}
362 799a8c8d aurel32
363 799a8c8d aurel32
void helper_dcbz_970(target_ulong addr)
364 799a8c8d aurel32
{
365 799a8c8d aurel32
    if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1)
366 799a8c8d aurel32
        do_dcbz(addr, 32);
367 799a8c8d aurel32
    else
368 799a8c8d aurel32
        do_dcbz(addr, env->dcache_line_size);
369 799a8c8d aurel32
}
370 799a8c8d aurel32
371 37d269df aurel32
void helper_icbi(target_ulong addr)
372 37d269df aurel32
{
373 37d269df aurel32
    uint32_t tmp;
374 37d269df aurel32
375 76db3ba4 aurel32
    addr &= ~(env->dcache_line_size - 1);
376 37d269df aurel32
    /* Invalidate one cache line :
377 37d269df aurel32
     * PowerPC specification says this is to be treated like a load
378 37d269df aurel32
     * (not a fetch) by the MMU. To be sure it will be so,
379 37d269df aurel32
     * do the load "by hand".
380 37d269df aurel32
     */
381 dcc532c8 aurel32
    tmp = ldl(addr);
382 37d269df aurel32
    tb_invalidate_page_range(addr, addr + env->icache_line_size);
383 37d269df aurel32
}
384 37d269df aurel32
385 bdb4b689 aurel32
// XXX: to be tested
386 bdb4b689 aurel32
target_ulong helper_lscbx (target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
387 bdb4b689 aurel32
{
388 bdb4b689 aurel32
    int i, c, d;
389 bdb4b689 aurel32
    d = 24;
390 bdb4b689 aurel32
    for (i = 0; i < xer_bc; i++) {
391 76db3ba4 aurel32
        c = ldub(addr);
392 76db3ba4 aurel32
        addr = addr_add(addr, 1);
393 bdb4b689 aurel32
        /* ra (if not 0) and rb are never modified */
394 bdb4b689 aurel32
        if (likely(reg != rb && (ra == 0 || reg != ra))) {
395 bdb4b689 aurel32
            env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
396 bdb4b689 aurel32
        }
397 bdb4b689 aurel32
        if (unlikely(c == xer_cmp))
398 bdb4b689 aurel32
            break;
399 bdb4b689 aurel32
        if (likely(d != 0)) {
400 bdb4b689 aurel32
            d -= 8;
401 bdb4b689 aurel32
        } else {
402 bdb4b689 aurel32
            d = 24;
403 bdb4b689 aurel32
            reg++;
404 bdb4b689 aurel32
            reg = reg & 0x1F;
405 bdb4b689 aurel32
        }
406 bdb4b689 aurel32
    }
407 bdb4b689 aurel32
    return i;
408 bdb4b689 aurel32
}
409 bdb4b689 aurel32
410 ff4a62cd aurel32
/*****************************************************************************/
411 fdabc366 bellard
/* Fixed point operations helpers */
412 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
413 d9bce9d9 j_mayer
414 74637406 aurel32
/* multiply high word */
415 74637406 aurel32
uint64_t helper_mulhd (uint64_t arg1, uint64_t arg2)
416 fdabc366 bellard
{
417 74637406 aurel32
    uint64_t tl, th;
418 fdabc366 bellard
419 74637406 aurel32
    muls64(&tl, &th, arg1, arg2);
420 74637406 aurel32
    return th;
421 d9bce9d9 j_mayer
}
422 d9bce9d9 j_mayer
423 74637406 aurel32
/* multiply high word unsigned */
424 74637406 aurel32
uint64_t helper_mulhdu (uint64_t arg1, uint64_t arg2)
425 fdabc366 bellard
{
426 74637406 aurel32
    uint64_t tl, th;
427 fdabc366 bellard
428 74637406 aurel32
    mulu64(&tl, &th, arg1, arg2);
429 74637406 aurel32
    return th;
430 fdabc366 bellard
}
431 fdabc366 bellard
432 74637406 aurel32
uint64_t helper_mulldo (uint64_t arg1, uint64_t arg2)
433 fdabc366 bellard
{
434 d9bce9d9 j_mayer
    int64_t th;
435 d9bce9d9 j_mayer
    uint64_t tl;
436 d9bce9d9 j_mayer
437 74637406 aurel32
    muls64(&tl, (uint64_t *)&th, arg1, arg2);
438 88ad920b j_mayer
    /* If th != 0 && th != -1, then we had an overflow */
439 6f2d8978 j_mayer
    if (likely((uint64_t)(th + 1) <= 1)) {
440 3d7b417e aurel32
        env->xer &= ~(1 << XER_OV);
441 fdabc366 bellard
    } else {
442 3d7b417e aurel32
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
443 fdabc366 bellard
    }
444 74637406 aurel32
    return (int64_t)tl;
445 d9bce9d9 j_mayer
}
446 d9bce9d9 j_mayer
#endif
447 d9bce9d9 j_mayer
448 26d67362 aurel32
target_ulong helper_cntlzw (target_ulong t)
449 603fccce j_mayer
{
450 26d67362 aurel32
    return clz32(t);
451 603fccce j_mayer
}
452 603fccce j_mayer
453 603fccce j_mayer
#if defined(TARGET_PPC64)
454 26d67362 aurel32
target_ulong helper_cntlzd (target_ulong t)
455 603fccce j_mayer
{
456 26d67362 aurel32
    return clz64(t);
457 603fccce j_mayer
}
458 603fccce j_mayer
#endif
459 603fccce j_mayer
460 9a64fbe4 bellard
/* shift right arithmetic helper */
461 26d67362 aurel32
target_ulong helper_sraw (target_ulong value, target_ulong shift)
462 9a64fbe4 bellard
{
463 9a64fbe4 bellard
    int32_t ret;
464 9a64fbe4 bellard
465 26d67362 aurel32
    if (likely(!(shift & 0x20))) {
466 26d67362 aurel32
        if (likely((uint32_t)shift != 0)) {
467 26d67362 aurel32
            shift &= 0x1f;
468 26d67362 aurel32
            ret = (int32_t)value >> shift;
469 26d67362 aurel32
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
470 3d7b417e aurel32
                env->xer &= ~(1 << XER_CA);
471 fdabc366 bellard
            } else {
472 3d7b417e aurel32
                env->xer |= (1 << XER_CA);
473 fdabc366 bellard
            }
474 fdabc366 bellard
        } else {
475 26d67362 aurel32
            ret = (int32_t)value;
476 3d7b417e aurel32
            env->xer &= ~(1 << XER_CA);
477 fdabc366 bellard
        }
478 fdabc366 bellard
    } else {
479 26d67362 aurel32
        ret = (int32_t)value >> 31;
480 26d67362 aurel32
        if (ret) {
481 3d7b417e aurel32
            env->xer |= (1 << XER_CA);
482 26d67362 aurel32
        } else {
483 26d67362 aurel32
            env->xer &= ~(1 << XER_CA);
484 76a66253 j_mayer
        }
485 fdabc366 bellard
    }
486 26d67362 aurel32
    return (target_long)ret;
487 9a64fbe4 bellard
}
488 9a64fbe4 bellard
489 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
490 26d67362 aurel32
target_ulong helper_srad (target_ulong value, target_ulong shift)
491 d9bce9d9 j_mayer
{
492 d9bce9d9 j_mayer
    int64_t ret;
493 d9bce9d9 j_mayer
494 26d67362 aurel32
    if (likely(!(shift & 0x40))) {
495 26d67362 aurel32
        if (likely((uint64_t)shift != 0)) {
496 26d67362 aurel32
            shift &= 0x3f;
497 26d67362 aurel32
            ret = (int64_t)value >> shift;
498 26d67362 aurel32
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
499 3d7b417e aurel32
                env->xer &= ~(1 << XER_CA);
500 d9bce9d9 j_mayer
            } else {
501 3d7b417e aurel32
                env->xer |= (1 << XER_CA);
502 d9bce9d9 j_mayer
            }
503 d9bce9d9 j_mayer
        } else {
504 26d67362 aurel32
            ret = (int64_t)value;
505 3d7b417e aurel32
            env->xer &= ~(1 << XER_CA);
506 d9bce9d9 j_mayer
        }
507 d9bce9d9 j_mayer
    } else {
508 26d67362 aurel32
        ret = (int64_t)value >> 63;
509 26d67362 aurel32
        if (ret) {
510 3d7b417e aurel32
            env->xer |= (1 << XER_CA);
511 26d67362 aurel32
        } else {
512 26d67362 aurel32
            env->xer &= ~(1 << XER_CA);
513 d9bce9d9 j_mayer
        }
514 d9bce9d9 j_mayer
    }
515 26d67362 aurel32
    return ret;
516 d9bce9d9 j_mayer
}
517 d9bce9d9 j_mayer
#endif
518 d9bce9d9 j_mayer
519 26d67362 aurel32
target_ulong helper_popcntb (target_ulong val)
520 d9bce9d9 j_mayer
{
521 6176a26d aurel32
    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
522 6176a26d aurel32
    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
523 6176a26d aurel32
    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
524 6176a26d aurel32
    return val;
525 d9bce9d9 j_mayer
}
526 d9bce9d9 j_mayer
527 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
528 26d67362 aurel32
target_ulong helper_popcntb_64 (target_ulong val)
529 d9bce9d9 j_mayer
{
530 6176a26d aurel32
    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
531 6176a26d aurel32
    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
532 6176a26d aurel32
    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
533 6176a26d aurel32
    return val;
534 d9bce9d9 j_mayer
}
535 d9bce9d9 j_mayer
#endif
536 d9bce9d9 j_mayer
537 fdabc366 bellard
/*****************************************************************************/
538 9a64fbe4 bellard
/* Floating point operations helpers */
539 a0d7d5a7 aurel32
uint64_t helper_float32_to_float64(uint32_t arg)
540 a0d7d5a7 aurel32
{
541 a0d7d5a7 aurel32
    CPU_FloatU f;
542 a0d7d5a7 aurel32
    CPU_DoubleU d;
543 a0d7d5a7 aurel32
    f.l = arg;
544 a0d7d5a7 aurel32
    d.d = float32_to_float64(f.f, &env->fp_status);
545 a0d7d5a7 aurel32
    return d.ll;
546 a0d7d5a7 aurel32
}
547 a0d7d5a7 aurel32
548 a0d7d5a7 aurel32
uint32_t helper_float64_to_float32(uint64_t arg)
549 a0d7d5a7 aurel32
{
550 a0d7d5a7 aurel32
    CPU_FloatU f;
551 a0d7d5a7 aurel32
    CPU_DoubleU d;
552 a0d7d5a7 aurel32
    d.ll = arg;
553 a0d7d5a7 aurel32
    f.f = float64_to_float32(d.d, &env->fp_status);
554 a0d7d5a7 aurel32
    return f.l;
555 a0d7d5a7 aurel32
}
556 a0d7d5a7 aurel32
557 0ca9d380 aurel32
static always_inline int isden (float64 d)
558 7c58044c j_mayer
{
559 0ca9d380 aurel32
    CPU_DoubleU u;
560 7c58044c j_mayer
561 0ca9d380 aurel32
    u.d = d;
562 7c58044c j_mayer
563 0ca9d380 aurel32
    return ((u.ll >> 52) & 0x7FF) == 0;
564 7c58044c j_mayer
}
565 7c58044c j_mayer
566 80621676 aurel32
#ifdef CONFIG_SOFTFLOAT
567 80621676 aurel32
static always_inline int isnormal (float64 d)
568 80621676 aurel32
{
569 80621676 aurel32
    CPU_DoubleU u;
570 80621676 aurel32
571 80621676 aurel32
    u.d = d;
572 80621676 aurel32
573 80621676 aurel32
    uint32_t exp = (u.ll >> 52) & 0x7FF;
574 80621676 aurel32
    return ((0 < exp) && (exp < 0x7FF));
575 80621676 aurel32
}
576 80621676 aurel32
#endif
577 80621676 aurel32
578 af12906f aurel32
uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
579 7c58044c j_mayer
{
580 af12906f aurel32
    CPU_DoubleU farg;
581 7c58044c j_mayer
    int isneg;
582 af12906f aurel32
    int ret;
583 af12906f aurel32
    farg.ll = arg;
584 f23c346e aurel32
    isneg = float64_is_neg(farg.d);
585 af12906f aurel32
    if (unlikely(float64_is_nan(farg.d))) {
586 af12906f aurel32
        if (float64_is_signaling_nan(farg.d)) {
587 7c58044c j_mayer
            /* Signaling NaN: flags are undefined */
588 af12906f aurel32
            ret = 0x00;
589 7c58044c j_mayer
        } else {
590 7c58044c j_mayer
            /* Quiet NaN */
591 af12906f aurel32
            ret = 0x11;
592 7c58044c j_mayer
        }
593 f23c346e aurel32
    } else if (unlikely(float64_is_infinity(farg.d))) {
594 7c58044c j_mayer
        /* +/- infinity */
595 7c58044c j_mayer
        if (isneg)
596 af12906f aurel32
            ret = 0x09;
597 7c58044c j_mayer
        else
598 af12906f aurel32
            ret = 0x05;
599 7c58044c j_mayer
    } else {
600 f23c346e aurel32
        if (float64_is_zero(farg.d)) {
601 7c58044c j_mayer
            /* +/- zero */
602 7c58044c j_mayer
            if (isneg)
603 af12906f aurel32
                ret = 0x12;
604 7c58044c j_mayer
            else
605 af12906f aurel32
                ret = 0x02;
606 7c58044c j_mayer
        } else {
607 af12906f aurel32
            if (isden(farg.d)) {
608 7c58044c j_mayer
                /* Denormalized numbers */
609 af12906f aurel32
                ret = 0x10;
610 7c58044c j_mayer
            } else {
611 7c58044c j_mayer
                /* Normalized numbers */
612 af12906f aurel32
                ret = 0x00;
613 7c58044c j_mayer
            }
614 7c58044c j_mayer
            if (isneg) {
615 af12906f aurel32
                ret |= 0x08;
616 7c58044c j_mayer
            } else {
617 af12906f aurel32
                ret |= 0x04;
618 7c58044c j_mayer
            }
619 7c58044c j_mayer
        }
620 7c58044c j_mayer
    }
621 7c58044c j_mayer
    if (set_fprf) {
622 7c58044c j_mayer
        /* We update FPSCR_FPRF */
623 7c58044c j_mayer
        env->fpscr &= ~(0x1F << FPSCR_FPRF);
624 af12906f aurel32
        env->fpscr |= ret << FPSCR_FPRF;
625 7c58044c j_mayer
    }
626 7c58044c j_mayer
    /* We just need fpcc to update Rc1 */
627 af12906f aurel32
    return ret & 0xF;
628 7c58044c j_mayer
}
629 7c58044c j_mayer
630 7c58044c j_mayer
/* Floating-point invalid operations exception */
631 af12906f aurel32
static always_inline uint64_t fload_invalid_op_excp (int op)
632 7c58044c j_mayer
{
633 af12906f aurel32
    uint64_t ret = 0;
634 7c58044c j_mayer
    int ve;
635 7c58044c j_mayer
636 7c58044c j_mayer
    ve = fpscr_ve;
637 e0147e41 aurel32
    switch (op) {
638 e0147e41 aurel32
    case POWERPC_EXCP_FP_VXSNAN:
639 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXSNAN;
640 e0147e41 aurel32
        break;
641 e0147e41 aurel32
    case POWERPC_EXCP_FP_VXSOFT:
642 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXSOFT;
643 e0147e41 aurel32
        break;
644 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXISI:
645 7c58044c j_mayer
        /* Magnitude subtraction of infinities */
646 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXISI;
647 7c58044c j_mayer
        goto update_arith;
648 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXIDI:
649 7c58044c j_mayer
        /* Division of infinity by infinity */
650 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXIDI;
651 7c58044c j_mayer
        goto update_arith;
652 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXZDZ:
653 7c58044c j_mayer
        /* Division of zero by zero */
654 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXZDZ;
655 7c58044c j_mayer
        goto update_arith;
656 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXIMZ:
657 7c58044c j_mayer
        /* Multiplication of zero by infinity */
658 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXIMZ;
659 7c58044c j_mayer
        goto update_arith;
660 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXVC:
661 7c58044c j_mayer
        /* Ordered comparison of NaN */
662 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXVC;
663 7c58044c j_mayer
        env->fpscr &= ~(0xF << FPSCR_FPCC);
664 7c58044c j_mayer
        env->fpscr |= 0x11 << FPSCR_FPCC;
665 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
666 7c58044c j_mayer
        if (ve != 0) {
667 7c58044c j_mayer
            env->exception_index = POWERPC_EXCP_PROGRAM;
668 7c58044c j_mayer
            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
669 7c58044c j_mayer
            /* Update the floating-point enabled exception summary */
670 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FEX;
671 7c58044c j_mayer
            /* Exception is differed */
672 7c58044c j_mayer
            ve = 0;
673 7c58044c j_mayer
        }
674 7c58044c j_mayer
        break;
675 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXSQRT:
676 7c58044c j_mayer
        /* Square root of a negative number */
677 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXSQRT;
678 7c58044c j_mayer
    update_arith:
679 7c58044c j_mayer
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
680 7c58044c j_mayer
        if (ve == 0) {
681 7c58044c j_mayer
            /* Set the result to quiet NaN */
682 e0147e41 aurel32
            ret = 0xFFF8000000000000ULL;
683 7c58044c j_mayer
            env->fpscr &= ~(0xF << FPSCR_FPCC);
684 7c58044c j_mayer
            env->fpscr |= 0x11 << FPSCR_FPCC;
685 7c58044c j_mayer
        }
686 7c58044c j_mayer
        break;
687 7c58044c j_mayer
    case POWERPC_EXCP_FP_VXCVI:
688 7c58044c j_mayer
        /* Invalid conversion */
689 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VXCVI;
690 7c58044c j_mayer
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
691 7c58044c j_mayer
        if (ve == 0) {
692 7c58044c j_mayer
            /* Set the result to quiet NaN */
693 e0147e41 aurel32
            ret = 0xFFF8000000000000ULL;
694 7c58044c j_mayer
            env->fpscr &= ~(0xF << FPSCR_FPCC);
695 7c58044c j_mayer
            env->fpscr |= 0x11 << FPSCR_FPCC;
696 7c58044c j_mayer
        }
697 7c58044c j_mayer
        break;
698 7c58044c j_mayer
    }
699 7c58044c j_mayer
    /* Update the floating-point invalid operation summary */
700 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_VX;
701 7c58044c j_mayer
    /* Update the floating-point exception summary */
702 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
703 7c58044c j_mayer
    if (ve != 0) {
704 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
705 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
706 7c58044c j_mayer
        if (msr_fe0 != 0 || msr_fe1 != 0)
707 e06fcd75 aurel32
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
708 7c58044c j_mayer
    }
709 af12906f aurel32
    return ret;
710 7c58044c j_mayer
}
711 7c58044c j_mayer
712 af12906f aurel32
static always_inline uint64_t float_zero_divide_excp (uint64_t arg1, uint64_t arg2)
713 7c58044c j_mayer
{
714 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_ZX;
715 7c58044c j_mayer
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
716 7c58044c j_mayer
    /* Update the floating-point exception summary */
717 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
718 7c58044c j_mayer
    if (fpscr_ze != 0) {
719 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
720 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
721 7c58044c j_mayer
        if (msr_fe0 != 0 || msr_fe1 != 0) {
722 e06fcd75 aurel32
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
723 e06fcd75 aurel32
                                       POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
724 7c58044c j_mayer
        }
725 7c58044c j_mayer
    } else {
726 7c58044c j_mayer
        /* Set the result to infinity */
727 af12906f aurel32
        arg1 = ((arg1 ^ arg2) & 0x8000000000000000ULL);
728 af12906f aurel32
        arg1 |= 0x7FFULL << 52;
729 7c58044c j_mayer
    }
730 af12906f aurel32
    return arg1;
731 7c58044c j_mayer
}
732 7c58044c j_mayer
733 7c58044c j_mayer
static always_inline void float_overflow_excp (void)
734 7c58044c j_mayer
{
735 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_OX;
736 7c58044c j_mayer
    /* Update the floating-point exception summary */
737 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
738 7c58044c j_mayer
    if (fpscr_oe != 0) {
739 7c58044c j_mayer
        /* XXX: should adjust the result */
740 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
741 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
742 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
743 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
744 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
745 7c58044c j_mayer
    } else {
746 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_XX;
747 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FI;
748 7c58044c j_mayer
    }
749 7c58044c j_mayer
}
750 7c58044c j_mayer
751 7c58044c j_mayer
static always_inline void float_underflow_excp (void)
752 7c58044c j_mayer
{
753 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_UX;
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_ue != 0) {
757 7c58044c j_mayer
        /* XXX: should adjust the result */
758 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
759 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
760 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
761 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
762 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
763 7c58044c j_mayer
    }
764 7c58044c j_mayer
}
765 7c58044c j_mayer
766 7c58044c j_mayer
static always_inline void float_inexact_excp (void)
767 7c58044c j_mayer
{
768 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_XX;
769 7c58044c j_mayer
    /* Update the floating-point exception summary */
770 7c58044c j_mayer
    env->fpscr |= 1 << FPSCR_FX;
771 7c58044c j_mayer
    if (fpscr_xe != 0) {
772 7c58044c j_mayer
        /* Update the floating-point enabled exception summary */
773 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
774 7c58044c j_mayer
        /* We must update the target FPR before raising the exception */
775 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
776 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
777 7c58044c j_mayer
    }
778 7c58044c j_mayer
}
779 7c58044c j_mayer
780 7c58044c j_mayer
static always_inline void fpscr_set_rounding_mode (void)
781 7c58044c j_mayer
{
782 7c58044c j_mayer
    int rnd_type;
783 7c58044c j_mayer
784 7c58044c j_mayer
    /* Set rounding mode */
785 7c58044c j_mayer
    switch (fpscr_rn) {
786 7c58044c j_mayer
    case 0:
787 7c58044c j_mayer
        /* Best approximation (round to nearest) */
788 7c58044c j_mayer
        rnd_type = float_round_nearest_even;
789 7c58044c j_mayer
        break;
790 7c58044c j_mayer
    case 1:
791 7c58044c j_mayer
        /* Smaller magnitude (round toward zero) */
792 7c58044c j_mayer
        rnd_type = float_round_to_zero;
793 7c58044c j_mayer
        break;
794 7c58044c j_mayer
    case 2:
795 7c58044c j_mayer
        /* Round toward +infinite */
796 7c58044c j_mayer
        rnd_type = float_round_up;
797 7c58044c j_mayer
        break;
798 7c58044c j_mayer
    default:
799 7c58044c j_mayer
    case 3:
800 7c58044c j_mayer
        /* Round toward -infinite */
801 7c58044c j_mayer
        rnd_type = float_round_down;
802 7c58044c j_mayer
        break;
803 7c58044c j_mayer
    }
804 7c58044c j_mayer
    set_float_rounding_mode(rnd_type, &env->fp_status);
805 7c58044c j_mayer
}
806 7c58044c j_mayer
807 6e35d524 aurel32
void helper_fpscr_clrbit (uint32_t bit)
808 6e35d524 aurel32
{
809 6e35d524 aurel32
    int prev;
810 6e35d524 aurel32
811 6e35d524 aurel32
    prev = (env->fpscr >> bit) & 1;
812 6e35d524 aurel32
    env->fpscr &= ~(1 << bit);
813 6e35d524 aurel32
    if (prev == 1) {
814 6e35d524 aurel32
        switch (bit) {
815 6e35d524 aurel32
        case FPSCR_RN1:
816 6e35d524 aurel32
        case FPSCR_RN:
817 6e35d524 aurel32
            fpscr_set_rounding_mode();
818 6e35d524 aurel32
            break;
819 6e35d524 aurel32
        default:
820 6e35d524 aurel32
            break;
821 6e35d524 aurel32
        }
822 6e35d524 aurel32
    }
823 6e35d524 aurel32
}
824 6e35d524 aurel32
825 af12906f aurel32
void helper_fpscr_setbit (uint32_t bit)
826 7c58044c j_mayer
{
827 7c58044c j_mayer
    int prev;
828 7c58044c j_mayer
829 7c58044c j_mayer
    prev = (env->fpscr >> bit) & 1;
830 7c58044c j_mayer
    env->fpscr |= 1 << bit;
831 7c58044c j_mayer
    if (prev == 0) {
832 7c58044c j_mayer
        switch (bit) {
833 7c58044c j_mayer
        case FPSCR_VX:
834 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
835 7c58044c j_mayer
            if (fpscr_ve)
836 7c58044c j_mayer
                goto raise_ve;
837 7c58044c j_mayer
        case FPSCR_OX:
838 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
839 7c58044c j_mayer
            if (fpscr_oe)
840 7c58044c j_mayer
                goto raise_oe;
841 7c58044c j_mayer
            break;
842 7c58044c j_mayer
        case FPSCR_UX:
843 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
844 7c58044c j_mayer
            if (fpscr_ue)
845 7c58044c j_mayer
                goto raise_ue;
846 7c58044c j_mayer
            break;
847 7c58044c j_mayer
        case FPSCR_ZX:
848 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
849 7c58044c j_mayer
            if (fpscr_ze)
850 7c58044c j_mayer
                goto raise_ze;
851 7c58044c j_mayer
            break;
852 7c58044c j_mayer
        case FPSCR_XX:
853 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
854 7c58044c j_mayer
            if (fpscr_xe)
855 7c58044c j_mayer
                goto raise_xe;
856 7c58044c j_mayer
            break;
857 7c58044c j_mayer
        case FPSCR_VXSNAN:
858 7c58044c j_mayer
        case FPSCR_VXISI:
859 7c58044c j_mayer
        case FPSCR_VXIDI:
860 7c58044c j_mayer
        case FPSCR_VXZDZ:
861 7c58044c j_mayer
        case FPSCR_VXIMZ:
862 7c58044c j_mayer
        case FPSCR_VXVC:
863 7c58044c j_mayer
        case FPSCR_VXSOFT:
864 7c58044c j_mayer
        case FPSCR_VXSQRT:
865 7c58044c j_mayer
        case FPSCR_VXCVI:
866 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_VX;
867 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FX;
868 7c58044c j_mayer
            if (fpscr_ve != 0)
869 7c58044c j_mayer
                goto raise_ve;
870 7c58044c j_mayer
            break;
871 7c58044c j_mayer
        case FPSCR_VE:
872 7c58044c j_mayer
            if (fpscr_vx != 0) {
873 7c58044c j_mayer
            raise_ve:
874 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP;
875 7c58044c j_mayer
                if (fpscr_vxsnan)
876 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXSNAN;
877 7c58044c j_mayer
                if (fpscr_vxisi)
878 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXISI;
879 7c58044c j_mayer
                if (fpscr_vxidi)
880 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXIDI;
881 7c58044c j_mayer
                if (fpscr_vxzdz)
882 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXZDZ;
883 7c58044c j_mayer
                if (fpscr_vximz)
884 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXIMZ;
885 7c58044c j_mayer
                if (fpscr_vxvc)
886 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXVC;
887 7c58044c j_mayer
                if (fpscr_vxsoft)
888 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXSOFT;
889 7c58044c j_mayer
                if (fpscr_vxsqrt)
890 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXSQRT;
891 7c58044c j_mayer
                if (fpscr_vxcvi)
892 7c58044c j_mayer
                    env->error_code |= POWERPC_EXCP_FP_VXCVI;
893 7c58044c j_mayer
                goto raise_excp;
894 7c58044c j_mayer
            }
895 7c58044c j_mayer
            break;
896 7c58044c j_mayer
        case FPSCR_OE:
897 7c58044c j_mayer
            if (fpscr_ox != 0) {
898 7c58044c j_mayer
            raise_oe:
899 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
900 7c58044c j_mayer
                goto raise_excp;
901 7c58044c j_mayer
            }
902 7c58044c j_mayer
            break;
903 7c58044c j_mayer
        case FPSCR_UE:
904 7c58044c j_mayer
            if (fpscr_ux != 0) {
905 7c58044c j_mayer
            raise_ue:
906 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
907 7c58044c j_mayer
                goto raise_excp;
908 7c58044c j_mayer
            }
909 7c58044c j_mayer
            break;
910 7c58044c j_mayer
        case FPSCR_ZE:
911 7c58044c j_mayer
            if (fpscr_zx != 0) {
912 7c58044c j_mayer
            raise_ze:
913 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
914 7c58044c j_mayer
                goto raise_excp;
915 7c58044c j_mayer
            }
916 7c58044c j_mayer
            break;
917 7c58044c j_mayer
        case FPSCR_XE:
918 7c58044c j_mayer
            if (fpscr_xx != 0) {
919 7c58044c j_mayer
            raise_xe:
920 7c58044c j_mayer
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
921 7c58044c j_mayer
                goto raise_excp;
922 7c58044c j_mayer
            }
923 7c58044c j_mayer
            break;
924 7c58044c j_mayer
        case FPSCR_RN1:
925 7c58044c j_mayer
        case FPSCR_RN:
926 7c58044c j_mayer
            fpscr_set_rounding_mode();
927 7c58044c j_mayer
            break;
928 7c58044c j_mayer
        default:
929 7c58044c j_mayer
            break;
930 7c58044c j_mayer
        raise_excp:
931 7c58044c j_mayer
            /* Update the floating-point enabled exception summary */
932 7c58044c j_mayer
            env->fpscr |= 1 << FPSCR_FEX;
933 7c58044c j_mayer
                /* We have to update Rc1 before raising the exception */
934 7c58044c j_mayer
            env->exception_index = POWERPC_EXCP_PROGRAM;
935 7c58044c j_mayer
            break;
936 7c58044c j_mayer
        }
937 7c58044c j_mayer
    }
938 7c58044c j_mayer
}
939 7c58044c j_mayer
940 af12906f aurel32
void helper_store_fpscr (uint64_t arg, uint32_t mask)
941 7c58044c j_mayer
{
942 7c58044c j_mayer
    /*
943 7c58044c j_mayer
     * We use only the 32 LSB of the incoming fpr
944 7c58044c j_mayer
     */
945 7c58044c j_mayer
    uint32_t prev, new;
946 7c58044c j_mayer
    int i;
947 7c58044c j_mayer
948 7c58044c j_mayer
    prev = env->fpscr;
949 af12906f aurel32
    new = (uint32_t)arg;
950 27ee5df0 aurel32
    new &= ~0x60000000;
951 27ee5df0 aurel32
    new |= prev & 0x60000000;
952 27ee5df0 aurel32
    for (i = 0; i < 8; i++) {
953 7c58044c j_mayer
        if (mask & (1 << i)) {
954 7c58044c j_mayer
            env->fpscr &= ~(0xF << (4 * i));
955 7c58044c j_mayer
            env->fpscr |= new & (0xF << (4 * i));
956 7c58044c j_mayer
        }
957 7c58044c j_mayer
    }
958 7c58044c j_mayer
    /* Update VX and FEX */
959 7c58044c j_mayer
    if (fpscr_ix != 0)
960 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_VX;
961 5567025f aurel32
    else
962 5567025f aurel32
        env->fpscr &= ~(1 << FPSCR_VX);
963 7c58044c j_mayer
    if ((fpscr_ex & fpscr_eex) != 0) {
964 7c58044c j_mayer
        env->fpscr |= 1 << FPSCR_FEX;
965 7c58044c j_mayer
        env->exception_index = POWERPC_EXCP_PROGRAM;
966 7c58044c j_mayer
        /* XXX: we should compute it properly */
967 7c58044c j_mayer
        env->error_code = POWERPC_EXCP_FP;
968 7c58044c j_mayer
    }
969 5567025f aurel32
    else
970 5567025f aurel32
        env->fpscr &= ~(1 << FPSCR_FEX);
971 7c58044c j_mayer
    fpscr_set_rounding_mode();
972 7c58044c j_mayer
}
973 7c58044c j_mayer
974 af12906f aurel32
void helper_float_check_status (void)
975 7c58044c j_mayer
{
976 af12906f aurel32
#ifdef CONFIG_SOFTFLOAT
977 7c58044c j_mayer
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
978 7c58044c j_mayer
        (env->error_code & POWERPC_EXCP_FP)) {
979 7c58044c j_mayer
        /* Differred floating-point exception after target FPR update */
980 7c58044c j_mayer
        if (msr_fe0 != 0 || msr_fe1 != 0)
981 e06fcd75 aurel32
            helper_raise_exception_err(env->exception_index, env->error_code);
982 be94c952 aurel32
    } else {
983 be94c952 aurel32
        int status = get_float_exception_flags(&env->fp_status);
984 be94c952 aurel32
        if (status & float_flag_overflow) {
985 be94c952 aurel32
            float_overflow_excp();
986 be94c952 aurel32
        } else if (status & float_flag_underflow) {
987 be94c952 aurel32
            float_underflow_excp();
988 be94c952 aurel32
        } else if (status & float_flag_inexact) {
989 be94c952 aurel32
            float_inexact_excp();
990 be94c952 aurel32
        }
991 7c58044c j_mayer
    }
992 af12906f aurel32
#else
993 af12906f aurel32
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
994 af12906f aurel32
        (env->error_code & POWERPC_EXCP_FP)) {
995 af12906f aurel32
        /* Differred floating-point exception after target FPR update */
996 af12906f aurel32
        if (msr_fe0 != 0 || msr_fe1 != 0)
997 e06fcd75 aurel32
            helper_raise_exception_err(env->exception_index, env->error_code);
998 af12906f aurel32
    }
999 af12906f aurel32
#endif
1000 af12906f aurel32
}
1001 af12906f aurel32
1002 af12906f aurel32
#ifdef CONFIG_SOFTFLOAT
1003 af12906f aurel32
void helper_reset_fpstatus (void)
1004 af12906f aurel32
{
1005 be94c952 aurel32
    set_float_exception_flags(0, &env->fp_status);
1006 7c58044c j_mayer
}
1007 7c58044c j_mayer
#endif
1008 7c58044c j_mayer
1009 af12906f aurel32
/* fadd - fadd. */
1010 af12906f aurel32
uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
1011 7c58044c j_mayer
{
1012 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1013 af12906f aurel32
1014 af12906f aurel32
    farg1.ll = arg1;
1015 af12906f aurel32
    farg2.ll = arg2;
1016 af12906f aurel32
#if USE_PRECISE_EMULATION
1017 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1018 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1019 7c58044c j_mayer
        /* sNaN addition */
1020 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1021 17218d1f aurel32
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1022 17218d1f aurel32
                      float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
1023 7c58044c j_mayer
        /* Magnitude subtraction of infinities */
1024 cf1cf21e aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1025 17218d1f aurel32
    } else {
1026 17218d1f aurel32
        farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
1027 7c58044c j_mayer
    }
1028 af12906f aurel32
#else
1029 af12906f aurel32
    farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
1030 af12906f aurel32
#endif
1031 af12906f aurel32
    return farg1.ll;
1032 7c58044c j_mayer
}
1033 7c58044c j_mayer
1034 af12906f aurel32
/* fsub - fsub. */
1035 af12906f aurel32
uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
1036 af12906f aurel32
{
1037 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1038 af12906f aurel32
1039 af12906f aurel32
    farg1.ll = arg1;
1040 af12906f aurel32
    farg2.ll = arg2;
1041 af12906f aurel32
#if USE_PRECISE_EMULATION
1042 7c58044c j_mayer
{
1043 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1044 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1045 7c58044c j_mayer
        /* sNaN subtraction */
1046 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1047 17218d1f aurel32
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1048 17218d1f aurel32
                      float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
1049 7c58044c j_mayer
        /* Magnitude subtraction of infinities */
1050 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1051 17218d1f aurel32
    } else {
1052 17218d1f aurel32
        farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1053 7c58044c j_mayer
    }
1054 7c58044c j_mayer
}
1055 af12906f aurel32
#else
1056 af12906f aurel32
    farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1057 af12906f aurel32
#endif
1058 af12906f aurel32
    return farg1.ll;
1059 af12906f aurel32
}
1060 7c58044c j_mayer
1061 af12906f aurel32
/* fmul - fmul. */
1062 af12906f aurel32
uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
1063 7c58044c j_mayer
{
1064 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1065 af12906f aurel32
1066 af12906f aurel32
    farg1.ll = arg1;
1067 af12906f aurel32
    farg2.ll = arg2;
1068 af12906f aurel32
#if USE_PRECISE_EMULATION
1069 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1070 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1071 7c58044c j_mayer
        /* sNaN multiplication */
1072 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1073 f23c346e aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1074 f23c346e aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1075 7c58044c j_mayer
        /* Multiplication of zero by infinity */
1076 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1077 7c58044c j_mayer
    } else {
1078 af12906f aurel32
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1079 7c58044c j_mayer
    }
1080 af12906f aurel32
#else
1081 af12906f aurel32
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1082 af12906f aurel32
#endif
1083 af12906f aurel32
    return farg1.ll;
1084 af12906f aurel32
}
1085 7c58044c j_mayer
1086 af12906f aurel32
/* fdiv - fdiv. */
1087 af12906f aurel32
uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
1088 7c58044c j_mayer
{
1089 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1090 af12906f aurel32
1091 af12906f aurel32
    farg1.ll = arg1;
1092 af12906f aurel32
    farg2.ll = arg2;
1093 af12906f aurel32
#if USE_PRECISE_EMULATION
1094 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1095 af12906f aurel32
                 float64_is_signaling_nan(farg2.d))) {
1096 7c58044c j_mayer
        /* sNaN division */
1097 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1098 f23c346e aurel32
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
1099 7c58044c j_mayer
        /* Division of infinity by infinity */
1100 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
1101 f23c346e aurel32
    } else if (unlikely(!float64_is_nan(farg1.d) && float64_is_zero(farg2.d))) {
1102 f23c346e aurel32
        if (float64_is_zero(farg1.d)) {
1103 7c58044c j_mayer
            /* Division of zero by zero */
1104 cf1cf21e aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
1105 7c58044c j_mayer
        } else {
1106 7c58044c j_mayer
            /* Division by zero */
1107 af12906f aurel32
            farg1.ll = float_zero_divide_excp(farg1.d, farg2.d);
1108 7c58044c j_mayer
        }
1109 7c58044c j_mayer
    } else {
1110 af12906f aurel32
        farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1111 7c58044c j_mayer
    }
1112 af12906f aurel32
#else
1113 af12906f aurel32
    farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1114 af12906f aurel32
#endif
1115 af12906f aurel32
    return farg1.ll;
1116 7c58044c j_mayer
}
1117 7c58044c j_mayer
1118 af12906f aurel32
/* fabs */
1119 af12906f aurel32
uint64_t helper_fabs (uint64_t arg)
1120 9a64fbe4 bellard
{
1121 af12906f aurel32
    CPU_DoubleU farg;
1122 9a64fbe4 bellard
1123 af12906f aurel32
    farg.ll = arg;
1124 af12906f aurel32
    farg.d = float64_abs(farg.d);
1125 af12906f aurel32
    return farg.ll;
1126 af12906f aurel32
}
1127 af12906f aurel32
1128 af12906f aurel32
/* fnabs */
1129 af12906f aurel32
uint64_t helper_fnabs (uint64_t arg)
1130 af12906f aurel32
{
1131 af12906f aurel32
    CPU_DoubleU farg;
1132 af12906f aurel32
1133 af12906f aurel32
    farg.ll = arg;
1134 af12906f aurel32
    farg.d = float64_abs(farg.d);
1135 af12906f aurel32
    farg.d = float64_chs(farg.d);
1136 af12906f aurel32
    return farg.ll;
1137 af12906f aurel32
}
1138 af12906f aurel32
1139 af12906f aurel32
/* fneg */
1140 af12906f aurel32
uint64_t helper_fneg (uint64_t arg)
1141 af12906f aurel32
{
1142 af12906f aurel32
    CPU_DoubleU farg;
1143 af12906f aurel32
1144 af12906f aurel32
    farg.ll = arg;
1145 af12906f aurel32
    farg.d = float64_chs(farg.d);
1146 af12906f aurel32
    return farg.ll;
1147 af12906f aurel32
}
1148 af12906f aurel32
1149 af12906f aurel32
/* fctiw - fctiw. */
1150 af12906f aurel32
uint64_t helper_fctiw (uint64_t arg)
1151 af12906f aurel32
{
1152 af12906f aurel32
    CPU_DoubleU farg;
1153 af12906f aurel32
    farg.ll = arg;
1154 af12906f aurel32
1155 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1156 7c58044c j_mayer
        /* sNaN conversion */
1157 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1158 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1159 7c58044c j_mayer
        /* qNan / infinity conversion */
1160 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1161 7c58044c j_mayer
    } else {
1162 af12906f aurel32
        farg.ll = float64_to_int32(farg.d, &env->fp_status);
1163 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1164 7c58044c j_mayer
        /* XXX: higher bits are not supposed to be significant.
1165 7c58044c j_mayer
         *     to make tests easier, return the same as a real PowerPC 750
1166 7c58044c j_mayer
         */
1167 af12906f aurel32
        farg.ll |= 0xFFF80000ULL << 32;
1168 e864cabd j_mayer
#endif
1169 7c58044c j_mayer
    }
1170 af12906f aurel32
    return farg.ll;
1171 9a64fbe4 bellard
}
1172 9a64fbe4 bellard
1173 af12906f aurel32
/* fctiwz - fctiwz. */
1174 af12906f aurel32
uint64_t helper_fctiwz (uint64_t arg)
1175 9a64fbe4 bellard
{
1176 af12906f aurel32
    CPU_DoubleU farg;
1177 af12906f aurel32
    farg.ll = arg;
1178 4ecc3190 bellard
1179 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1180 7c58044c j_mayer
        /* sNaN conversion */
1181 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1182 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1183 7c58044c j_mayer
        /* qNan / infinity conversion */
1184 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1185 7c58044c j_mayer
    } else {
1186 af12906f aurel32
        farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
1187 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1188 7c58044c j_mayer
        /* XXX: higher bits are not supposed to be significant.
1189 7c58044c j_mayer
         *     to make tests easier, return the same as a real PowerPC 750
1190 7c58044c j_mayer
         */
1191 af12906f aurel32
        farg.ll |= 0xFFF80000ULL << 32;
1192 e864cabd j_mayer
#endif
1193 7c58044c j_mayer
    }
1194 af12906f aurel32
    return farg.ll;
1195 9a64fbe4 bellard
}
1196 9a64fbe4 bellard
1197 426613db j_mayer
#if defined(TARGET_PPC64)
1198 af12906f aurel32
/* fcfid - fcfid. */
1199 af12906f aurel32
uint64_t helper_fcfid (uint64_t arg)
1200 426613db j_mayer
{
1201 af12906f aurel32
    CPU_DoubleU farg;
1202 af12906f aurel32
    farg.d = int64_to_float64(arg, &env->fp_status);
1203 af12906f aurel32
    return farg.ll;
1204 426613db j_mayer
}
1205 426613db j_mayer
1206 af12906f aurel32
/* fctid - fctid. */
1207 af12906f aurel32
uint64_t helper_fctid (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(farg.d, &env->fp_status);
1220 7c58044c j_mayer
    }
1221 af12906f aurel32
    return farg.ll;
1222 426613db j_mayer
}
1223 426613db j_mayer
1224 af12906f aurel32
/* fctidz - fctidz. */
1225 af12906f aurel32
uint64_t helper_fctidz (uint64_t arg)
1226 426613db j_mayer
{
1227 af12906f aurel32
    CPU_DoubleU farg;
1228 af12906f aurel32
    farg.ll = arg;
1229 426613db j_mayer
1230 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1231 7c58044c j_mayer
        /* sNaN conversion */
1232 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1233 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1234 7c58044c j_mayer
        /* qNan / infinity conversion */
1235 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1236 7c58044c j_mayer
    } else {
1237 af12906f aurel32
        farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
1238 7c58044c j_mayer
    }
1239 af12906f aurel32
    return farg.ll;
1240 426613db j_mayer
}
1241 426613db j_mayer
1242 426613db j_mayer
#endif
1243 426613db j_mayer
1244 af12906f aurel32
static always_inline uint64_t do_fri (uint64_t arg, int rounding_mode)
1245 d7e4b87e j_mayer
{
1246 af12906f aurel32
    CPU_DoubleU farg;
1247 af12906f aurel32
    farg.ll = arg;
1248 af12906f aurel32
1249 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1250 7c58044c j_mayer
        /* sNaN round */
1251 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1252 f23c346e aurel32
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1253 7c58044c j_mayer
        /* qNan / infinity round */
1254 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1255 7c58044c j_mayer
    } else {
1256 7c58044c j_mayer
        set_float_rounding_mode(rounding_mode, &env->fp_status);
1257 af12906f aurel32
        farg.ll = float64_round_to_int(farg.d, &env->fp_status);
1258 7c58044c j_mayer
        /* Restore rounding mode from FPSCR */
1259 7c58044c j_mayer
        fpscr_set_rounding_mode();
1260 7c58044c j_mayer
    }
1261 af12906f aurel32
    return farg.ll;
1262 d7e4b87e j_mayer
}
1263 d7e4b87e j_mayer
1264 af12906f aurel32
uint64_t helper_frin (uint64_t arg)
1265 d7e4b87e j_mayer
{
1266 af12906f aurel32
    return do_fri(arg, float_round_nearest_even);
1267 d7e4b87e j_mayer
}
1268 d7e4b87e j_mayer
1269 af12906f aurel32
uint64_t helper_friz (uint64_t arg)
1270 d7e4b87e j_mayer
{
1271 af12906f aurel32
    return do_fri(arg, float_round_to_zero);
1272 d7e4b87e j_mayer
}
1273 d7e4b87e j_mayer
1274 af12906f aurel32
uint64_t helper_frip (uint64_t arg)
1275 d7e4b87e j_mayer
{
1276 af12906f aurel32
    return do_fri(arg, float_round_up);
1277 d7e4b87e j_mayer
}
1278 d7e4b87e j_mayer
1279 af12906f aurel32
uint64_t helper_frim (uint64_t arg)
1280 d7e4b87e j_mayer
{
1281 af12906f aurel32
    return do_fri(arg, float_round_down);
1282 d7e4b87e j_mayer
}
1283 d7e4b87e j_mayer
1284 af12906f aurel32
/* fmadd - fmadd. */
1285 af12906f aurel32
uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1286 e864cabd j_mayer
{
1287 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1288 af12906f aurel32
1289 af12906f aurel32
    farg1.ll = arg1;
1290 af12906f aurel32
    farg2.ll = arg2;
1291 af12906f aurel32
    farg3.ll = arg3;
1292 af12906f aurel32
#if USE_PRECISE_EMULATION
1293 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1294 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1295 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1296 7c58044c j_mayer
        /* sNaN operation */
1297 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1298 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1299 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1300 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1301 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1302 7c58044c j_mayer
    } else {
1303 e864cabd j_mayer
#ifdef FLOAT128
1304 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1305 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1306 7c58044c j_mayer
1307 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1308 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1309 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1310 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1311 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1312 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1313 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1314 da1e7ac9 aurel32
        } else {
1315 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1316 da1e7ac9 aurel32
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1317 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1318 da1e7ac9 aurel32
        }
1319 e864cabd j_mayer
#else
1320 7c58044c j_mayer
        /* This is OK on x86 hosts */
1321 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) + farg3.d;
1322 e864cabd j_mayer
#endif
1323 7c58044c j_mayer
    }
1324 af12906f aurel32
#else
1325 af12906f aurel32
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1326 af12906f aurel32
    farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1327 af12906f aurel32
#endif
1328 af12906f aurel32
    return farg1.ll;
1329 e864cabd j_mayer
}
1330 e864cabd j_mayer
1331 af12906f aurel32
/* fmsub - fmsub. */
1332 af12906f aurel32
uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1333 e864cabd j_mayer
{
1334 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1335 af12906f aurel32
1336 af12906f aurel32
    farg1.ll = arg1;
1337 af12906f aurel32
    farg2.ll = arg2;
1338 af12906f aurel32
    farg3.ll = arg3;
1339 af12906f aurel32
#if USE_PRECISE_EMULATION
1340 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1341 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1342 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1343 7c58044c j_mayer
        /* sNaN operation */
1344 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1345 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1346 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1347 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1348 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1349 7c58044c j_mayer
    } else {
1350 e864cabd j_mayer
#ifdef FLOAT128
1351 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1352 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1353 7c58044c j_mayer
1354 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1355 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1356 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1357 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1358 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1359 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1360 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1361 da1e7ac9 aurel32
        } else {
1362 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1363 da1e7ac9 aurel32
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1364 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1365 da1e7ac9 aurel32
        }
1366 e864cabd j_mayer
#else
1367 7c58044c j_mayer
        /* This is OK on x86 hosts */
1368 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) - farg3.d;
1369 e864cabd j_mayer
#endif
1370 7c58044c j_mayer
    }
1371 af12906f aurel32
#else
1372 af12906f aurel32
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1373 af12906f aurel32
    farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1374 af12906f aurel32
#endif
1375 af12906f aurel32
    return farg1.ll;
1376 e864cabd j_mayer
}
1377 e864cabd j_mayer
1378 af12906f aurel32
/* fnmadd - fnmadd. */
1379 af12906f aurel32
uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1380 4b3686fa bellard
{
1381 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1382 af12906f aurel32
1383 af12906f aurel32
    farg1.ll = arg1;
1384 af12906f aurel32
    farg2.ll = arg2;
1385 af12906f aurel32
    farg3.ll = arg3;
1386 af12906f aurel32
1387 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1388 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1389 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1390 7c58044c j_mayer
        /* sNaN operation */
1391 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1392 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1393 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1394 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1395 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1396 7c58044c j_mayer
    } else {
1397 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1398 e864cabd j_mayer
#ifdef FLOAT128
1399 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1400 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1401 7c58044c j_mayer
1402 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1403 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1404 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1405 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1406 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1407 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1408 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1409 da1e7ac9 aurel32
        } else {
1410 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1411 da1e7ac9 aurel32
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1412 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1413 da1e7ac9 aurel32
        }
1414 e864cabd j_mayer
#else
1415 7c58044c j_mayer
        /* This is OK on x86 hosts */
1416 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) + farg3.d;
1417 e864cabd j_mayer
#endif
1418 e864cabd j_mayer
#else
1419 af12906f aurel32
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1420 af12906f aurel32
        farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1421 e864cabd j_mayer
#endif
1422 a44d2ce1 aurel32
        if (likely(!float64_is_nan(farg1.d)))
1423 af12906f aurel32
            farg1.d = float64_chs(farg1.d);
1424 7c58044c j_mayer
    }
1425 af12906f aurel32
    return farg1.ll;
1426 4b3686fa bellard
}
1427 4b3686fa bellard
1428 af12906f aurel32
/* fnmsub - fnmsub. */
1429 af12906f aurel32
uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1430 4b3686fa bellard
{
1431 af12906f aurel32
    CPU_DoubleU farg1, farg2, farg3;
1432 af12906f aurel32
1433 af12906f aurel32
    farg1.ll = arg1;
1434 af12906f aurel32
    farg2.ll = arg2;
1435 af12906f aurel32
    farg3.ll = arg3;
1436 af12906f aurel32
1437 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1438 af12906f aurel32
                 float64_is_signaling_nan(farg2.d) ||
1439 af12906f aurel32
                 float64_is_signaling_nan(farg3.d))) {
1440 7c58044c j_mayer
        /* sNaN operation */
1441 af12906f aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1442 da1e7ac9 aurel32
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1443 da1e7ac9 aurel32
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1444 da1e7ac9 aurel32
        /* Multiplication of zero by infinity */
1445 da1e7ac9 aurel32
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1446 7c58044c j_mayer
    } else {
1447 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1448 e864cabd j_mayer
#ifdef FLOAT128
1449 7c58044c j_mayer
        /* This is the way the PowerPC specification defines it */
1450 7c58044c j_mayer
        float128 ft0_128, ft1_128;
1451 7c58044c j_mayer
1452 af12906f aurel32
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1453 af12906f aurel32
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1454 7c58044c j_mayer
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1455 da1e7ac9 aurel32
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1456 da1e7ac9 aurel32
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1457 da1e7ac9 aurel32
            /* Magnitude subtraction of infinities */
1458 da1e7ac9 aurel32
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1459 da1e7ac9 aurel32
        } else {
1460 da1e7ac9 aurel32
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1461 da1e7ac9 aurel32
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1462 da1e7ac9 aurel32
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1463 da1e7ac9 aurel32
        }
1464 e864cabd j_mayer
#else
1465 7c58044c j_mayer
        /* This is OK on x86 hosts */
1466 af12906f aurel32
        farg1.d = (farg1.d * farg2.d) - farg3.d;
1467 e864cabd j_mayer
#endif
1468 e864cabd j_mayer
#else
1469 af12906f aurel32
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1470 af12906f aurel32
        farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1471 e864cabd j_mayer
#endif
1472 a44d2ce1 aurel32
        if (likely(!float64_is_nan(farg1.d)))
1473 af12906f aurel32
            farg1.d = float64_chs(farg1.d);
1474 7c58044c j_mayer
    }
1475 af12906f aurel32
    return farg1.ll;
1476 1ef59d0a bellard
}
1477 1ef59d0a bellard
1478 af12906f aurel32
/* frsp - frsp. */
1479 af12906f aurel32
uint64_t helper_frsp (uint64_t arg)
1480 7c58044c j_mayer
{
1481 af12906f aurel32
    CPU_DoubleU farg;
1482 6ad193ed aurel32
    float32 f32;
1483 af12906f aurel32
    farg.ll = arg;
1484 af12906f aurel32
1485 af12906f aurel32
#if USE_PRECISE_EMULATION
1486 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1487 7c58044c j_mayer
        /* sNaN square root */
1488 af12906f aurel32
       farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1489 7c58044c j_mayer
    } else {
1490 6ad193ed aurel32
       f32 = float64_to_float32(farg.d, &env->fp_status);
1491 6ad193ed aurel32
       farg.d = float32_to_float64(f32, &env->fp_status);
1492 7c58044c j_mayer
    }
1493 af12906f aurel32
#else
1494 6ad193ed aurel32
    f32 = float64_to_float32(farg.d, &env->fp_status);
1495 6ad193ed aurel32
    farg.d = float32_to_float64(f32, &env->fp_status);
1496 af12906f aurel32
#endif
1497 af12906f aurel32
    return farg.ll;
1498 7c58044c j_mayer
}
1499 7c58044c j_mayer
1500 af12906f aurel32
/* fsqrt - fsqrt. */
1501 af12906f aurel32
uint64_t helper_fsqrt (uint64_t arg)
1502 9a64fbe4 bellard
{
1503 af12906f aurel32
    CPU_DoubleU farg;
1504 af12906f aurel32
    farg.ll = arg;
1505 af12906f aurel32
1506 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1507 7c58044c j_mayer
        /* sNaN square root */
1508 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1509 f23c346e aurel32
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1510 7c58044c j_mayer
        /* Square root of a negative nonzero number */
1511 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1512 7c58044c j_mayer
    } else {
1513 af12906f aurel32
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1514 7c58044c j_mayer
    }
1515 af12906f aurel32
    return farg.ll;
1516 9a64fbe4 bellard
}
1517 9a64fbe4 bellard
1518 af12906f aurel32
/* fre - fre. */
1519 af12906f aurel32
uint64_t helper_fre (uint64_t arg)
1520 d7e4b87e j_mayer
{
1521 05b93603 aurel32
    CPU_DoubleU fone, farg;
1522 01feec08 aurel32
    fone.ll = 0x3FF0000000000000ULL; /* 1.0 */
1523 af12906f aurel32
    farg.ll = arg;
1524 d7e4b87e j_mayer
1525 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1526 7c58044c j_mayer
        /* sNaN reciprocal */
1527 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1528 f23c346e aurel32
    } else if (unlikely(float64_is_zero(farg.d))) {
1529 7c58044c j_mayer
        /* Zero reciprocal */
1530 05b93603 aurel32
        farg.ll = float_zero_divide_excp(fone.d, farg.d);
1531 af12906f aurel32
    } else if (likely(isnormal(farg.d))) {
1532 05b93603 aurel32
        farg.d = float64_div(fone.d, farg.d, &env->fp_status);
1533 d7e4b87e j_mayer
    } else {
1534 af12906f aurel32
        if (farg.ll == 0x8000000000000000ULL) {
1535 af12906f aurel32
            farg.ll = 0xFFF0000000000000ULL;
1536 af12906f aurel32
        } else if (farg.ll == 0x0000000000000000ULL) {
1537 af12906f aurel32
            farg.ll = 0x7FF0000000000000ULL;
1538 a44d2ce1 aurel32
        } else if (float64_is_nan(farg.d)) {
1539 af12906f aurel32
            farg.ll = 0x7FF8000000000000ULL;
1540 f23c346e aurel32
        } else if (float64_is_neg(farg.d)) {
1541 af12906f aurel32
            farg.ll = 0x8000000000000000ULL;
1542 d7e4b87e j_mayer
        } else {
1543 af12906f aurel32
            farg.ll = 0x0000000000000000ULL;
1544 d7e4b87e j_mayer
        }
1545 d7e4b87e j_mayer
    }
1546 af12906f aurel32
    return farg.d;
1547 d7e4b87e j_mayer
}
1548 d7e4b87e j_mayer
1549 af12906f aurel32
/* fres - fres. */
1550 af12906f aurel32
uint64_t helper_fres (uint64_t arg)
1551 9a64fbe4 bellard
{
1552 05b93603 aurel32
    CPU_DoubleU fone, farg;
1553 01feec08 aurel32
    fone.ll = 0x3FF0000000000000ULL; /* 1.0 */
1554 af12906f aurel32
    farg.ll = arg;
1555 4ecc3190 bellard
1556 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1557 7c58044c j_mayer
        /* sNaN reciprocal */
1558 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1559 f23c346e aurel32
    } else if (unlikely(float64_is_zero(farg.d))) {
1560 7c58044c j_mayer
        /* Zero reciprocal */
1561 05b93603 aurel32
        farg.ll = float_zero_divide_excp(fone.d, farg.d);
1562 af12906f aurel32
    } else if (likely(isnormal(farg.d))) {
1563 1cdb9c3d aurel32
#if USE_PRECISE_EMULATION
1564 05b93603 aurel32
        farg.d = float64_div(fone.d, farg.d, &env->fp_status);
1565 af12906f aurel32
        farg.d = float64_to_float32(farg.d, &env->fp_status);
1566 e864cabd j_mayer
#else
1567 05b93603 aurel32
        farg.d = float32_div(fone.d, farg.d, &env->fp_status);
1568 e864cabd j_mayer
#endif
1569 4ecc3190 bellard
    } else {
1570 af12906f aurel32
        if (farg.ll == 0x8000000000000000ULL) {
1571 af12906f aurel32
            farg.ll = 0xFFF0000000000000ULL;
1572 af12906f aurel32
        } else if (farg.ll == 0x0000000000000000ULL) {
1573 af12906f aurel32
            farg.ll = 0x7FF0000000000000ULL;
1574 a44d2ce1 aurel32
        } else if (float64_is_nan(farg.d)) {
1575 af12906f aurel32
            farg.ll = 0x7FF8000000000000ULL;
1576 f23c346e aurel32
        } else if (float64_is_neg(farg.d)) {
1577 af12906f aurel32
            farg.ll = 0x8000000000000000ULL;
1578 4ecc3190 bellard
        } else {
1579 af12906f aurel32
            farg.ll = 0x0000000000000000ULL;
1580 4ecc3190 bellard
        }
1581 4ecc3190 bellard
    }
1582 af12906f aurel32
    return farg.ll;
1583 9a64fbe4 bellard
}
1584 9a64fbe4 bellard
1585 af12906f aurel32
/* frsqrte  - frsqrte. */
1586 af12906f aurel32
uint64_t helper_frsqrte (uint64_t arg)
1587 9a64fbe4 bellard
{
1588 05b93603 aurel32
    CPU_DoubleU fone, farg;
1589 01feec08 aurel32
    fone.ll = 0x3FF0000000000000ULL; /* 1.0 */
1590 af12906f aurel32
    farg.ll = arg;
1591 4ecc3190 bellard
1592 af12906f aurel32
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1593 7c58044c j_mayer
        /* sNaN reciprocal square root */
1594 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1595 f23c346e aurel32
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1596 7c58044c j_mayer
        /* Reciprocal square root of a negative nonzero number */
1597 af12906f aurel32
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1598 af12906f aurel32
    } else if (likely(isnormal(farg.d))) {
1599 af12906f aurel32
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1600 05b93603 aurel32
        farg.d = float32_div(fone.d, farg.d, &env->fp_status);
1601 4ecc3190 bellard
    } else {
1602 af12906f aurel32
        if (farg.ll == 0x8000000000000000ULL) {
1603 af12906f aurel32
            farg.ll = 0xFFF0000000000000ULL;
1604 af12906f aurel32
        } else if (farg.ll == 0x0000000000000000ULL) {
1605 af12906f aurel32
            farg.ll = 0x7FF0000000000000ULL;
1606 a44d2ce1 aurel32
        } else if (float64_is_nan(farg.d)) {
1607 af12906f aurel32
            farg.ll |= 0x000FFFFFFFFFFFFFULL;
1608 f23c346e aurel32
        } else if (float64_is_neg(farg.d)) {
1609 af12906f aurel32
            farg.ll = 0x7FF8000000000000ULL;
1610 4ecc3190 bellard
        } else {
1611 af12906f aurel32
            farg.ll = 0x0000000000000000ULL;
1612 4ecc3190 bellard
        }
1613 4ecc3190 bellard
    }
1614 af12906f aurel32
    return farg.ll;
1615 9a64fbe4 bellard
}
1616 9a64fbe4 bellard
1617 af12906f aurel32
/* fsel - fsel. */
1618 af12906f aurel32
uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1619 9a64fbe4 bellard
{
1620 6ad7365a aurel32
    CPU_DoubleU farg1;
1621 af12906f aurel32
1622 af12906f aurel32
    farg1.ll = arg1;
1623 af12906f aurel32
1624 f23c346e aurel32
    if (!float64_is_neg(farg1.d) || float64_is_zero(farg1.d))
1625 6ad7365a aurel32
        return arg2;
1626 4ecc3190 bellard
    else
1627 6ad7365a aurel32
        return arg3;
1628 9a64fbe4 bellard
}
1629 9a64fbe4 bellard
1630 9a819377 aurel32
void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1631 9a64fbe4 bellard
{
1632 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1633 e1571908 aurel32
    uint32_t ret = 0;
1634 af12906f aurel32
    farg1.ll = arg1;
1635 af12906f aurel32
    farg2.ll = arg2;
1636 e1571908 aurel32
1637 9a819377 aurel32
    if (unlikely(float64_is_nan(farg1.d) ||
1638 9a819377 aurel32
                 float64_is_nan(farg2.d))) {
1639 9a819377 aurel32
        ret = 0x01UL;
1640 9a819377 aurel32
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1641 9a819377 aurel32
        ret = 0x08UL;
1642 9a819377 aurel32
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1643 9a819377 aurel32
        ret = 0x04UL;
1644 7c58044c j_mayer
    } else {
1645 9a819377 aurel32
        ret = 0x02UL;
1646 9a64fbe4 bellard
    }
1647 9a819377 aurel32
1648 7c58044c j_mayer
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1649 e1571908 aurel32
    env->fpscr |= ret << FPSCR_FPRF;
1650 9a819377 aurel32
    env->crf[crfD] = ret;
1651 9a819377 aurel32
    if (unlikely(ret == 0x01UL
1652 9a819377 aurel32
                 && (float64_is_signaling_nan(farg1.d) ||
1653 9a819377 aurel32
                     float64_is_signaling_nan(farg2.d)))) {
1654 9a819377 aurel32
        /* sNaN comparison */
1655 9a819377 aurel32
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1656 9a819377 aurel32
    }
1657 9a64fbe4 bellard
}
1658 9a64fbe4 bellard
1659 9a819377 aurel32
void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1660 9a64fbe4 bellard
{
1661 af12906f aurel32
    CPU_DoubleU farg1, farg2;
1662 e1571908 aurel32
    uint32_t ret = 0;
1663 af12906f aurel32
    farg1.ll = arg1;
1664 af12906f aurel32
    farg2.ll = arg2;
1665 e1571908 aurel32
1666 af12906f aurel32
    if (unlikely(float64_is_nan(farg1.d) ||
1667 af12906f aurel32
                 float64_is_nan(farg2.d))) {
1668 9a819377 aurel32
        ret = 0x01UL;
1669 9a819377 aurel32
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1670 9a819377 aurel32
        ret = 0x08UL;
1671 9a819377 aurel32
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1672 9a819377 aurel32
        ret = 0x04UL;
1673 9a819377 aurel32
    } else {
1674 9a819377 aurel32
        ret = 0x02UL;
1675 9a819377 aurel32
    }
1676 9a819377 aurel32
1677 9a819377 aurel32
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1678 9a819377 aurel32
    env->fpscr |= ret << FPSCR_FPRF;
1679 9a819377 aurel32
    env->crf[crfD] = ret;
1680 9a819377 aurel32
    if (unlikely (ret == 0x01UL)) {
1681 af12906f aurel32
        if (float64_is_signaling_nan(farg1.d) ||
1682 af12906f aurel32
            float64_is_signaling_nan(farg2.d)) {
1683 7c58044c j_mayer
            /* sNaN comparison */
1684 7c58044c j_mayer
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1685 7c58044c j_mayer
                                  POWERPC_EXCP_FP_VXVC);
1686 7c58044c j_mayer
        } else {
1687 7c58044c j_mayer
            /* qNaN comparison */
1688 7c58044c j_mayer
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1689 7c58044c j_mayer
        }
1690 9a64fbe4 bellard
    }
1691 9a64fbe4 bellard
}
1692 9a64fbe4 bellard
1693 76a66253 j_mayer
#if !defined (CONFIG_USER_ONLY)
1694 6527f6ea aurel32
void helper_store_msr (target_ulong val)
1695 0411a972 j_mayer
{
1696 6527f6ea aurel32
    val = hreg_store_msr(env, val, 0);
1697 6527f6ea aurel32
    if (val != 0) {
1698 0411a972 j_mayer
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1699 e06fcd75 aurel32
        helper_raise_exception(val);
1700 0411a972 j_mayer
    }
1701 0411a972 j_mayer
}
1702 0411a972 j_mayer
1703 d72a19f7 aurel32
static always_inline void do_rfi (target_ulong nip, target_ulong msr,
1704 0411a972 j_mayer
                                    target_ulong msrm, int keep_msrh)
1705 9a64fbe4 bellard
{
1706 426613db j_mayer
#if defined(TARGET_PPC64)
1707 0411a972 j_mayer
    if (msr & (1ULL << MSR_SF)) {
1708 0411a972 j_mayer
        nip = (uint64_t)nip;
1709 0411a972 j_mayer
        msr &= (uint64_t)msrm;
1710 a42bd6cc j_mayer
    } else {
1711 0411a972 j_mayer
        nip = (uint32_t)nip;
1712 0411a972 j_mayer
        msr = (uint32_t)(msr & msrm);
1713 0411a972 j_mayer
        if (keep_msrh)
1714 0411a972 j_mayer
            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
1715 a42bd6cc j_mayer
    }
1716 426613db j_mayer
#else
1717 0411a972 j_mayer
    nip = (uint32_t)nip;
1718 0411a972 j_mayer
    msr &= (uint32_t)msrm;
1719 426613db j_mayer
#endif
1720 0411a972 j_mayer
    /* XXX: beware: this is false if VLE is supported */
1721 0411a972 j_mayer
    env->nip = nip & ~((target_ulong)0x00000003);
1722 a4f30719 j_mayer
    hreg_store_msr(env, msr, 1);
1723 fdabc366 bellard
#if defined (DEBUG_OP)
1724 0411a972 j_mayer
    cpu_dump_rfi(env->nip, env->msr);
1725 fdabc366 bellard
#endif
1726 0411a972 j_mayer
    /* No need to raise an exception here,
1727 0411a972 j_mayer
     * as rfi is always the last insn of a TB
1728 0411a972 j_mayer
     */
1729 fdabc366 bellard
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1730 9a64fbe4 bellard
}
1731 d9bce9d9 j_mayer
1732 d72a19f7 aurel32
void helper_rfi (void)
1733 0411a972 j_mayer
{
1734 d72a19f7 aurel32
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1735 d72a19f7 aurel32
           ~((target_ulong)0xFFFF0000), 1);
1736 0411a972 j_mayer
}
1737 0411a972 j_mayer
1738 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1739 d72a19f7 aurel32
void helper_rfid (void)
1740 426613db j_mayer
{
1741 d72a19f7 aurel32
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1742 d72a19f7 aurel32
           ~((target_ulong)0xFFFF0000), 0);
1743 d9bce9d9 j_mayer
}
1744 7863667f j_mayer
1745 d72a19f7 aurel32
void helper_hrfid (void)
1746 be147d08 j_mayer
{
1747 d72a19f7 aurel32
    do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
1748 d72a19f7 aurel32
           ~((target_ulong)0xFFFF0000), 0);
1749 be147d08 j_mayer
}
1750 be147d08 j_mayer
#endif
1751 76a66253 j_mayer
#endif
1752 9a64fbe4 bellard
1753 cab3bee2 aurel32
void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
1754 9a64fbe4 bellard
{
1755 cab3bee2 aurel32
    if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1756 cab3bee2 aurel32
                  ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1757 cab3bee2 aurel32
                  ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1758 cab3bee2 aurel32
                  ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1759 cab3bee2 aurel32
                  ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1760 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1761 a42bd6cc j_mayer
    }
1762 9a64fbe4 bellard
}
1763 9a64fbe4 bellard
1764 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1765 cab3bee2 aurel32
void helper_td (target_ulong arg1, target_ulong arg2, uint32_t flags)
1766 d9bce9d9 j_mayer
{
1767 cab3bee2 aurel32
    if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1768 cab3bee2 aurel32
                  ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1769 cab3bee2 aurel32
                  ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1770 cab3bee2 aurel32
                  ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1771 cab3bee2 aurel32
                  ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01)))))
1772 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1773 d9bce9d9 j_mayer
}
1774 d9bce9d9 j_mayer
#endif
1775 d9bce9d9 j_mayer
1776 fdabc366 bellard
/*****************************************************************************/
1777 76a66253 j_mayer
/* PowerPC 601 specific instructions (POWER bridge) */
1778 9a64fbe4 bellard
1779 22e0e173 aurel32
target_ulong helper_clcs (uint32_t arg)
1780 9a64fbe4 bellard
{
1781 22e0e173 aurel32
    switch (arg) {
1782 76a66253 j_mayer
    case 0x0CUL:
1783 76a66253 j_mayer
        /* Instruction cache line size */
1784 22e0e173 aurel32
        return env->icache_line_size;
1785 76a66253 j_mayer
        break;
1786 76a66253 j_mayer
    case 0x0DUL:
1787 76a66253 j_mayer
        /* Data cache line size */
1788 22e0e173 aurel32
        return env->dcache_line_size;
1789 76a66253 j_mayer
        break;
1790 76a66253 j_mayer
    case 0x0EUL:
1791 76a66253 j_mayer
        /* Minimum cache line size */
1792 22e0e173 aurel32
        return (env->icache_line_size < env->dcache_line_size) ?
1793 22e0e173 aurel32
                env->icache_line_size : env->dcache_line_size;
1794 76a66253 j_mayer
        break;
1795 76a66253 j_mayer
    case 0x0FUL:
1796 76a66253 j_mayer
        /* Maximum cache line size */
1797 22e0e173 aurel32
        return (env->icache_line_size > env->dcache_line_size) ?
1798 22e0e173 aurel32
                env->icache_line_size : env->dcache_line_size;
1799 76a66253 j_mayer
        break;
1800 76a66253 j_mayer
    default:
1801 76a66253 j_mayer
        /* Undefined */
1802 22e0e173 aurel32
        return 0;
1803 76a66253 j_mayer
        break;
1804 76a66253 j_mayer
    }
1805 76a66253 j_mayer
}
1806 76a66253 j_mayer
1807 22e0e173 aurel32
target_ulong helper_div (target_ulong arg1, target_ulong arg2)
1808 76a66253 j_mayer
{
1809 22e0e173 aurel32
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1810 76a66253 j_mayer
1811 22e0e173 aurel32
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1812 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1813 76a66253 j_mayer
        env->spr[SPR_MQ] = 0;
1814 22e0e173 aurel32
        return INT32_MIN;
1815 76a66253 j_mayer
    } else {
1816 22e0e173 aurel32
        env->spr[SPR_MQ] = tmp % arg2;
1817 22e0e173 aurel32
        return  tmp / (int32_t)arg2;
1818 76a66253 j_mayer
    }
1819 76a66253 j_mayer
}
1820 76a66253 j_mayer
1821 22e0e173 aurel32
target_ulong helper_divo (target_ulong arg1, target_ulong arg2)
1822 76a66253 j_mayer
{
1823 22e0e173 aurel32
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1824 76a66253 j_mayer
1825 22e0e173 aurel32
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1826 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1827 3d7b417e aurel32
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
1828 76a66253 j_mayer
        env->spr[SPR_MQ] = 0;
1829 22e0e173 aurel32
        return INT32_MIN;
1830 76a66253 j_mayer
    } else {
1831 22e0e173 aurel32
        env->spr[SPR_MQ] = tmp % arg2;
1832 22e0e173 aurel32
        tmp /= (int32_t)arg2;
1833 22e0e173 aurel32
        if ((int32_t)tmp != tmp) {
1834 3d7b417e aurel32
            env->xer |= (1 << XER_OV) | (1 << XER_SO);
1835 76a66253 j_mayer
        } else {
1836 3d7b417e aurel32
            env->xer &= ~(1 << XER_OV);
1837 76a66253 j_mayer
        }
1838 22e0e173 aurel32
        return tmp;
1839 76a66253 j_mayer
    }
1840 76a66253 j_mayer
}
1841 76a66253 j_mayer
1842 22e0e173 aurel32
target_ulong helper_divs (target_ulong arg1, target_ulong arg2)
1843 76a66253 j_mayer
{
1844 22e0e173 aurel32
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1845 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1846 22e0e173 aurel32
        env->spr[SPR_MQ] = 0;
1847 22e0e173 aurel32
        return INT32_MIN;
1848 76a66253 j_mayer
    } else {
1849 22e0e173 aurel32
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1850 22e0e173 aurel32
        return (int32_t)arg1 / (int32_t)arg2;
1851 76a66253 j_mayer
    }
1852 76a66253 j_mayer
}
1853 76a66253 j_mayer
1854 22e0e173 aurel32
target_ulong helper_divso (target_ulong arg1, target_ulong arg2)
1855 76a66253 j_mayer
{
1856 22e0e173 aurel32
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1857 22e0e173 aurel32
        (int32_t)arg2 == 0) {
1858 3d7b417e aurel32
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
1859 22e0e173 aurel32
        env->spr[SPR_MQ] = 0;
1860 22e0e173 aurel32
        return INT32_MIN;
1861 76a66253 j_mayer
    } else {
1862 3d7b417e aurel32
        env->xer &= ~(1 << XER_OV);
1863 22e0e173 aurel32
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1864 22e0e173 aurel32
        return (int32_t)arg1 / (int32_t)arg2;
1865 76a66253 j_mayer
    }
1866 76a66253 j_mayer
}
1867 76a66253 j_mayer
1868 76a66253 j_mayer
#if !defined (CONFIG_USER_ONLY)
1869 22e0e173 aurel32
target_ulong helper_rac (target_ulong addr)
1870 76a66253 j_mayer
{
1871 76a66253 j_mayer
    mmu_ctx_t ctx;
1872 faadf50e j_mayer
    int nb_BATs;
1873 22e0e173 aurel32
    target_ulong ret = 0;
1874 76a66253 j_mayer
1875 76a66253 j_mayer
    /* We don't have to generate many instances of this instruction,
1876 76a66253 j_mayer
     * as rac is supervisor only.
1877 76a66253 j_mayer
     */
1878 faadf50e j_mayer
    /* XXX: FIX THIS: Pretend we have no BAT */
1879 faadf50e j_mayer
    nb_BATs = env->nb_BATs;
1880 faadf50e j_mayer
    env->nb_BATs = 0;
1881 22e0e173 aurel32
    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0)
1882 22e0e173 aurel32
        ret = ctx.raddr;
1883 faadf50e j_mayer
    env->nb_BATs = nb_BATs;
1884 22e0e173 aurel32
    return ret;
1885 76a66253 j_mayer
}
1886 76a66253 j_mayer
1887 d72a19f7 aurel32
void helper_rfsvc (void)
1888 76a66253 j_mayer
{
1889 d72a19f7 aurel32
    do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1890 76a66253 j_mayer
}
1891 76a66253 j_mayer
#endif
1892 76a66253 j_mayer
1893 76a66253 j_mayer
/*****************************************************************************/
1894 76a66253 j_mayer
/* 602 specific instructions */
1895 76a66253 j_mayer
/* mfrom is the most crazy instruction ever seen, imho ! */
1896 76a66253 j_mayer
/* Real implementation uses a ROM table. Do the same */
1897 5e9ae189 aurel32
/* Extremly decomposed:
1898 5e9ae189 aurel32
 *                      -arg / 256
1899 5e9ae189 aurel32
 * return 256 * log10(10           + 1.0) + 0.5
1900 5e9ae189 aurel32
 */
1901 db9a16a7 aurel32
#if !defined (CONFIG_USER_ONLY)
1902 cf02a65c aurel32
target_ulong helper_602_mfrom (target_ulong arg)
1903 76a66253 j_mayer
{
1904 cf02a65c aurel32
    if (likely(arg < 602)) {
1905 76a66253 j_mayer
#include "mfrom_table.c"
1906 45d827d2 aurel32
        return mfrom_ROM_table[arg];
1907 76a66253 j_mayer
    } else {
1908 cf02a65c aurel32
        return 0;
1909 76a66253 j_mayer
    }
1910 76a66253 j_mayer
}
1911 db9a16a7 aurel32
#endif
1912 76a66253 j_mayer
1913 76a66253 j_mayer
/*****************************************************************************/
1914 76a66253 j_mayer
/* Embedded PowerPC specific helpers */
1915 76a66253 j_mayer
1916 a750fc0b j_mayer
/* XXX: to be improved to check access rights when in user-mode */
1917 06dca6a7 aurel32
target_ulong helper_load_dcr (target_ulong dcrn)
1918 a750fc0b j_mayer
{
1919 06dca6a7 aurel32
    target_ulong val = 0;
1920 a750fc0b j_mayer
1921 a750fc0b j_mayer
    if (unlikely(env->dcr_env == NULL)) {
1922 a750fc0b j_mayer
        if (loglevel != 0) {
1923 a750fc0b j_mayer
            fprintf(logfile, "No DCR environment\n");
1924 a750fc0b j_mayer
        }
1925 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1926 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1927 06dca6a7 aurel32
    } else if (unlikely(ppc_dcr_read(env->dcr_env, dcrn, &val) != 0)) {
1928 a750fc0b j_mayer
        if (loglevel != 0) {
1929 45d827d2 aurel32
            fprintf(logfile, "DCR read error %d %03x\n", (int)dcrn, (int)dcrn);
1930 a750fc0b j_mayer
        }
1931 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1932 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1933 a750fc0b j_mayer
    }
1934 06dca6a7 aurel32
    return val;
1935 a750fc0b j_mayer
}
1936 a750fc0b j_mayer
1937 06dca6a7 aurel32
void helper_store_dcr (target_ulong dcrn, target_ulong val)
1938 a750fc0b j_mayer
{
1939 a750fc0b j_mayer
    if (unlikely(env->dcr_env == NULL)) {
1940 a750fc0b j_mayer
        if (loglevel != 0) {
1941 a750fc0b j_mayer
            fprintf(logfile, "No DCR environment\n");
1942 a750fc0b j_mayer
        }
1943 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1944 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1945 06dca6a7 aurel32
    } else if (unlikely(ppc_dcr_write(env->dcr_env, dcrn, val) != 0)) {
1946 a750fc0b j_mayer
        if (loglevel != 0) {
1947 45d827d2 aurel32
            fprintf(logfile, "DCR write error %d %03x\n", (int)dcrn, (int)dcrn);
1948 a750fc0b j_mayer
        }
1949 e06fcd75 aurel32
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1950 e06fcd75 aurel32
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1951 a750fc0b j_mayer
    }
1952 a750fc0b j_mayer
}
1953 a750fc0b j_mayer
1954 76a66253 j_mayer
#if !defined(CONFIG_USER_ONLY)
1955 d72a19f7 aurel32
void helper_40x_rfci (void)
1956 76a66253 j_mayer
{
1957 d72a19f7 aurel32
    do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1958 d72a19f7 aurel32
           ~((target_ulong)0xFFFF0000), 0);
1959 a42bd6cc j_mayer
}
1960 a42bd6cc j_mayer
1961 d72a19f7 aurel32
void helper_rfci (void)
1962 a42bd6cc j_mayer
{
1963 d72a19f7 aurel32
    do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1964 d72a19f7 aurel32
           ~((target_ulong)0x3FFF0000), 0);
1965 a42bd6cc j_mayer
}
1966 a42bd6cc j_mayer
1967 d72a19f7 aurel32
void helper_rfdi (void)
1968 a42bd6cc j_mayer
{
1969 d72a19f7 aurel32
    do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1970 d72a19f7 aurel32
           ~((target_ulong)0x3FFF0000), 0);
1971 a42bd6cc j_mayer
}
1972 a42bd6cc j_mayer
1973 d72a19f7 aurel32
void helper_rfmci (void)
1974 a42bd6cc j_mayer
{
1975 d72a19f7 aurel32
    do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1976 d72a19f7 aurel32
           ~((target_ulong)0x3FFF0000), 0);
1977 76a66253 j_mayer
}
1978 76a66253 j_mayer
#endif
1979 76a66253 j_mayer
1980 76a66253 j_mayer
/* 440 specific */
1981 ef0d51af aurel32
target_ulong helper_dlmzb (target_ulong high, target_ulong low, uint32_t update_Rc)
1982 76a66253 j_mayer
{
1983 76a66253 j_mayer
    target_ulong mask;
1984 76a66253 j_mayer
    int i;
1985 76a66253 j_mayer
1986 76a66253 j_mayer
    i = 1;
1987 76a66253 j_mayer
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1988 ef0d51af aurel32
        if ((high & mask) == 0) {
1989 ef0d51af aurel32
            if (update_Rc) {
1990 ef0d51af aurel32
                env->crf[0] = 0x4;
1991 ef0d51af aurel32
            }
1992 76a66253 j_mayer
            goto done;
1993 ef0d51af aurel32
        }
1994 76a66253 j_mayer
        i++;
1995 76a66253 j_mayer
    }
1996 76a66253 j_mayer
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1997 ef0d51af aurel32
        if ((low & mask) == 0) {
1998 ef0d51af aurel32
            if (update_Rc) {
1999 ef0d51af aurel32
                env->crf[0] = 0x8;
2000 ef0d51af aurel32
            }
2001 ef0d51af aurel32
            goto done;
2002 ef0d51af aurel32
        }
2003 76a66253 j_mayer
        i++;
2004 76a66253 j_mayer
    }
2005 ef0d51af aurel32
    if (update_Rc) {
2006 ef0d51af aurel32
        env->crf[0] = 0x2;
2007 ef0d51af aurel32
    }
2008 76a66253 j_mayer
 done:
2009 ef0d51af aurel32
    env->xer = (env->xer & ~0x7F) | i;
2010 ef0d51af aurel32
    if (update_Rc) {
2011 ef0d51af aurel32
        env->crf[0] |= xer_so;
2012 ef0d51af aurel32
    }
2013 ef0d51af aurel32
    return i;
2014 fdabc366 bellard
}
2015 fdabc366 bellard
2016 1c97856d aurel32
/*****************************************************************************/
2017 0487d6a8 j_mayer
/* SPE extension helpers */
2018 0487d6a8 j_mayer
/* Use a table to make this quicker */
2019 0487d6a8 j_mayer
static uint8_t hbrev[16] = {
2020 0487d6a8 j_mayer
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
2021 0487d6a8 j_mayer
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
2022 0487d6a8 j_mayer
};
2023 0487d6a8 j_mayer
2024 b068d6a7 j_mayer
static always_inline uint8_t byte_reverse (uint8_t val)
2025 0487d6a8 j_mayer
{
2026 0487d6a8 j_mayer
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
2027 0487d6a8 j_mayer
}
2028 0487d6a8 j_mayer
2029 b068d6a7 j_mayer
static always_inline uint32_t word_reverse (uint32_t val)
2030 0487d6a8 j_mayer
{
2031 0487d6a8 j_mayer
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
2032 0487d6a8 j_mayer
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
2033 0487d6a8 j_mayer
}
2034 0487d6a8 j_mayer
2035 3cd7d1dd j_mayer
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
2036 57951c27 aurel32
target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
2037 0487d6a8 j_mayer
{
2038 0487d6a8 j_mayer
    uint32_t a, b, d, mask;
2039 0487d6a8 j_mayer
2040 3cd7d1dd j_mayer
    mask = UINT32_MAX >> (32 - MASKBITS);
2041 57951c27 aurel32
    a = arg1 & mask;
2042 57951c27 aurel32
    b = arg2 & mask;
2043 3cd7d1dd j_mayer
    d = word_reverse(1 + word_reverse(a | ~b));
2044 57951c27 aurel32
    return (arg1 & ~mask) | (d & b);
2045 0487d6a8 j_mayer
}
2046 0487d6a8 j_mayer
2047 57951c27 aurel32
uint32_t helper_cntlsw32 (uint32_t val)
2048 0487d6a8 j_mayer
{
2049 0487d6a8 j_mayer
    if (val & 0x80000000)
2050 603fccce j_mayer
        return clz32(~val);
2051 0487d6a8 j_mayer
    else
2052 603fccce j_mayer
        return clz32(val);
2053 0487d6a8 j_mayer
}
2054 0487d6a8 j_mayer
2055 57951c27 aurel32
uint32_t helper_cntlzw32 (uint32_t val)
2056 0487d6a8 j_mayer
{
2057 603fccce j_mayer
    return clz32(val);
2058 0487d6a8 j_mayer
}
2059 0487d6a8 j_mayer
2060 1c97856d aurel32
/* Single-precision floating-point conversions */
2061 1c97856d aurel32
static always_inline uint32_t efscfsi (uint32_t val)
2062 0487d6a8 j_mayer
{
2063 0ca9d380 aurel32
    CPU_FloatU u;
2064 0487d6a8 j_mayer
2065 0487d6a8 j_mayer
    u.f = int32_to_float32(val, &env->spe_status);
2066 0487d6a8 j_mayer
2067 0ca9d380 aurel32
    return u.l;
2068 0487d6a8 j_mayer
}
2069 0487d6a8 j_mayer
2070 1c97856d aurel32
static always_inline uint32_t efscfui (uint32_t val)
2071 0487d6a8 j_mayer
{
2072 0ca9d380 aurel32
    CPU_FloatU u;
2073 0487d6a8 j_mayer
2074 0487d6a8 j_mayer
    u.f = uint32_to_float32(val, &env->spe_status);
2075 0487d6a8 j_mayer
2076 0ca9d380 aurel32
    return u.l;
2077 0487d6a8 j_mayer
}
2078 0487d6a8 j_mayer
2079 1c97856d aurel32
static always_inline int32_t efsctsi (uint32_t val)
2080 0487d6a8 j_mayer
{
2081 0ca9d380 aurel32
    CPU_FloatU u;
2082 0487d6a8 j_mayer
2083 0ca9d380 aurel32
    u.l = val;
2084 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2085 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2086 0487d6a8 j_mayer
        return 0;
2087 0487d6a8 j_mayer
2088 0487d6a8 j_mayer
    return float32_to_int32(u.f, &env->spe_status);
2089 0487d6a8 j_mayer
}
2090 0487d6a8 j_mayer
2091 1c97856d aurel32
static always_inline uint32_t efsctui (uint32_t val)
2092 0487d6a8 j_mayer
{
2093 0ca9d380 aurel32
    CPU_FloatU u;
2094 0487d6a8 j_mayer
2095 0ca9d380 aurel32
    u.l = val;
2096 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2097 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2098 0487d6a8 j_mayer
        return 0;
2099 0487d6a8 j_mayer
2100 0487d6a8 j_mayer
    return float32_to_uint32(u.f, &env->spe_status);
2101 0487d6a8 j_mayer
}
2102 0487d6a8 j_mayer
2103 1c97856d aurel32
static always_inline uint32_t efsctsiz (uint32_t val)
2104 0487d6a8 j_mayer
{
2105 0ca9d380 aurel32
    CPU_FloatU u;
2106 0487d6a8 j_mayer
2107 0ca9d380 aurel32
    u.l = val;
2108 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2109 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2110 0487d6a8 j_mayer
        return 0;
2111 0487d6a8 j_mayer
2112 0487d6a8 j_mayer
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2113 0487d6a8 j_mayer
}
2114 0487d6a8 j_mayer
2115 1c97856d aurel32
static always_inline uint32_t efsctuiz (uint32_t val)
2116 0487d6a8 j_mayer
{
2117 0ca9d380 aurel32
    CPU_FloatU u;
2118 0487d6a8 j_mayer
2119 0ca9d380 aurel32
    u.l = val;
2120 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2121 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2122 0487d6a8 j_mayer
        return 0;
2123 0487d6a8 j_mayer
2124 0487d6a8 j_mayer
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2125 0487d6a8 j_mayer
}
2126 0487d6a8 j_mayer
2127 1c97856d aurel32
static always_inline uint32_t efscfsf (uint32_t val)
2128 0487d6a8 j_mayer
{
2129 0ca9d380 aurel32
    CPU_FloatU u;
2130 0487d6a8 j_mayer
    float32 tmp;
2131 0487d6a8 j_mayer
2132 0487d6a8 j_mayer
    u.f = int32_to_float32(val, &env->spe_status);
2133 0487d6a8 j_mayer
    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
2134 0487d6a8 j_mayer
    u.f = float32_div(u.f, tmp, &env->spe_status);
2135 0487d6a8 j_mayer
2136 0ca9d380 aurel32
    return u.l;
2137 0487d6a8 j_mayer
}
2138 0487d6a8 j_mayer
2139 1c97856d aurel32
static always_inline uint32_t efscfuf (uint32_t val)
2140 0487d6a8 j_mayer
{
2141 0ca9d380 aurel32
    CPU_FloatU u;
2142 0487d6a8 j_mayer
    float32 tmp;
2143 0487d6a8 j_mayer
2144 0487d6a8 j_mayer
    u.f = uint32_to_float32(val, &env->spe_status);
2145 0487d6a8 j_mayer
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2146 0487d6a8 j_mayer
    u.f = float32_div(u.f, tmp, &env->spe_status);
2147 0487d6a8 j_mayer
2148 0ca9d380 aurel32
    return u.l;
2149 0487d6a8 j_mayer
}
2150 0487d6a8 j_mayer
2151 1c97856d aurel32
static always_inline uint32_t efsctsf (uint32_t val)
2152 0487d6a8 j_mayer
{
2153 0ca9d380 aurel32
    CPU_FloatU u;
2154 0487d6a8 j_mayer
    float32 tmp;
2155 0487d6a8 j_mayer
2156 0ca9d380 aurel32
    u.l = val;
2157 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2158 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2159 0487d6a8 j_mayer
        return 0;
2160 0487d6a8 j_mayer
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2161 0487d6a8 j_mayer
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2162 0487d6a8 j_mayer
2163 0487d6a8 j_mayer
    return float32_to_int32(u.f, &env->spe_status);
2164 0487d6a8 j_mayer
}
2165 0487d6a8 j_mayer
2166 1c97856d aurel32
static always_inline uint32_t efsctuf (uint32_t val)
2167 0487d6a8 j_mayer
{
2168 0ca9d380 aurel32
    CPU_FloatU u;
2169 0487d6a8 j_mayer
    float32 tmp;
2170 0487d6a8 j_mayer
2171 0ca9d380 aurel32
    u.l = val;
2172 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2173 a44d2ce1 aurel32
    if (unlikely(float32_is_nan(u.f)))
2174 0487d6a8 j_mayer
        return 0;
2175 0487d6a8 j_mayer
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2176 0487d6a8 j_mayer
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2177 0487d6a8 j_mayer
2178 0487d6a8 j_mayer
    return float32_to_uint32(u.f, &env->spe_status);
2179 0487d6a8 j_mayer
}
2180 0487d6a8 j_mayer
2181 1c97856d aurel32
#define HELPER_SPE_SINGLE_CONV(name)                                          \
2182 1c97856d aurel32
uint32_t helper_e##name (uint32_t val)                                        \
2183 1c97856d aurel32
{                                                                             \
2184 1c97856d aurel32
    return e##name(val);                                                      \
2185 1c97856d aurel32
}
2186 1c97856d aurel32
/* efscfsi */
2187 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsi);
2188 1c97856d aurel32
/* efscfui */
2189 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfui);
2190 1c97856d aurel32
/* efscfuf */
2191 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfuf);
2192 1c97856d aurel32
/* efscfsf */
2193 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fscfsf);
2194 1c97856d aurel32
/* efsctsi */
2195 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsi);
2196 1c97856d aurel32
/* efsctui */
2197 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctui);
2198 1c97856d aurel32
/* efsctsiz */
2199 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsiz);
2200 1c97856d aurel32
/* efsctuiz */
2201 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuiz);
2202 1c97856d aurel32
/* efsctsf */
2203 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctsf);
2204 1c97856d aurel32
/* efsctuf */
2205 1c97856d aurel32
HELPER_SPE_SINGLE_CONV(fsctuf);
2206 1c97856d aurel32
2207 1c97856d aurel32
#define HELPER_SPE_VECTOR_CONV(name)                                          \
2208 1c97856d aurel32
uint64_t helper_ev##name (uint64_t val)                                       \
2209 1c97856d aurel32
{                                                                             \
2210 1c97856d aurel32
    return ((uint64_t)e##name(val >> 32) << 32) |                             \
2211 1c97856d aurel32
            (uint64_t)e##name(val);                                           \
2212 0487d6a8 j_mayer
}
2213 1c97856d aurel32
/* evfscfsi */
2214 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsi);
2215 1c97856d aurel32
/* evfscfui */
2216 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfui);
2217 1c97856d aurel32
/* evfscfuf */
2218 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfuf);
2219 1c97856d aurel32
/* evfscfsf */
2220 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fscfsf);
2221 1c97856d aurel32
/* evfsctsi */
2222 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsi);
2223 1c97856d aurel32
/* evfsctui */
2224 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctui);
2225 1c97856d aurel32
/* evfsctsiz */
2226 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsiz);
2227 1c97856d aurel32
/* evfsctuiz */
2228 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuiz);
2229 1c97856d aurel32
/* evfsctsf */
2230 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctsf);
2231 1c97856d aurel32
/* evfsctuf */
2232 1c97856d aurel32
HELPER_SPE_VECTOR_CONV(fsctuf);
2233 0487d6a8 j_mayer
2234 1c97856d aurel32
/* Single-precision floating-point arithmetic */
2235 1c97856d aurel32
static always_inline uint32_t efsadd (uint32_t op1, uint32_t op2)
2236 0487d6a8 j_mayer
{
2237 1c97856d aurel32
    CPU_FloatU u1, u2;
2238 1c97856d aurel32
    u1.l = op1;
2239 1c97856d aurel32
    u2.l = op2;
2240 1c97856d aurel32
    u1.f = float32_add(u1.f, u2.f, &env->spe_status);
2241 1c97856d aurel32
    return u1.l;
2242 0487d6a8 j_mayer
}
2243 0487d6a8 j_mayer
2244 1c97856d aurel32
static always_inline uint32_t efssub (uint32_t op1, uint32_t op2)
2245 0487d6a8 j_mayer
{
2246 1c97856d aurel32
    CPU_FloatU u1, u2;
2247 1c97856d aurel32
    u1.l = op1;
2248 1c97856d aurel32
    u2.l = op2;
2249 1c97856d aurel32
    u1.f = float32_sub(u1.f, u2.f, &env->spe_status);
2250 1c97856d aurel32
    return u1.l;
2251 0487d6a8 j_mayer
}
2252 0487d6a8 j_mayer
2253 1c97856d aurel32
static always_inline uint32_t efsmul (uint32_t op1, uint32_t op2)
2254 0487d6a8 j_mayer
{
2255 1c97856d aurel32
    CPU_FloatU u1, u2;
2256 1c97856d aurel32
    u1.l = op1;
2257 1c97856d aurel32
    u2.l = op2;
2258 1c97856d aurel32
    u1.f = float32_mul(u1.f, u2.f, &env->spe_status);
2259 1c97856d aurel32
    return u1.l;
2260 0487d6a8 j_mayer
}
2261 0487d6a8 j_mayer
2262 1c97856d aurel32
static always_inline uint32_t efsdiv (uint32_t op1, uint32_t op2)
2263 0487d6a8 j_mayer
{
2264 1c97856d aurel32
    CPU_FloatU u1, u2;
2265 1c97856d aurel32
    u1.l = op1;
2266 1c97856d aurel32
    u2.l = op2;
2267 1c97856d aurel32
    u1.f = float32_div(u1.f, u2.f, &env->spe_status);
2268 1c97856d aurel32
    return u1.l;
2269 0487d6a8 j_mayer
}
2270 0487d6a8 j_mayer
2271 1c97856d aurel32
#define HELPER_SPE_SINGLE_ARITH(name)                                         \
2272 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
2273 1c97856d aurel32
{                                                                             \
2274 1c97856d aurel32
    return e##name(op1, op2);                                                 \
2275 1c97856d aurel32
}
2276 1c97856d aurel32
/* efsadd */
2277 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsadd);
2278 1c97856d aurel32
/* efssub */
2279 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fssub);
2280 1c97856d aurel32
/* efsmul */
2281 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsmul);
2282 1c97856d aurel32
/* efsdiv */
2283 1c97856d aurel32
HELPER_SPE_SINGLE_ARITH(fsdiv);
2284 1c97856d aurel32
2285 1c97856d aurel32
#define HELPER_SPE_VECTOR_ARITH(name)                                         \
2286 1c97856d aurel32
uint64_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
2287 1c97856d aurel32
{                                                                             \
2288 1c97856d aurel32
    return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |                  \
2289 1c97856d aurel32
            (uint64_t)e##name(op1, op2);                                      \
2290 1c97856d aurel32
}
2291 1c97856d aurel32
/* evfsadd */
2292 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsadd);
2293 1c97856d aurel32
/* evfssub */
2294 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fssub);
2295 1c97856d aurel32
/* evfsmul */
2296 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsmul);
2297 1c97856d aurel32
/* evfsdiv */
2298 1c97856d aurel32
HELPER_SPE_VECTOR_ARITH(fsdiv);
2299 1c97856d aurel32
2300 1c97856d aurel32
/* Single-precision floating-point comparisons */
2301 1c97856d aurel32
static always_inline uint32_t efststlt (uint32_t op1, uint32_t op2)
2302 0487d6a8 j_mayer
{
2303 1c97856d aurel32
    CPU_FloatU u1, u2;
2304 1c97856d aurel32
    u1.l = op1;
2305 1c97856d aurel32
    u2.l = op2;
2306 1c97856d aurel32
    return float32_lt(u1.f, u2.f, &env->spe_status) ? 4 : 0;
2307 0487d6a8 j_mayer
}
2308 0487d6a8 j_mayer
2309 1c97856d aurel32
static always_inline uint32_t efststgt (uint32_t op1, uint32_t op2)
2310 0487d6a8 j_mayer
{
2311 1c97856d aurel32
    CPU_FloatU u1, u2;
2312 1c97856d aurel32
    u1.l = op1;
2313 1c97856d aurel32
    u2.l = op2;
2314 1c97856d aurel32
    return float32_le(u1.f, u2.f, &env->spe_status) ? 0 : 4;
2315 0487d6a8 j_mayer
}
2316 0487d6a8 j_mayer
2317 1c97856d aurel32
static always_inline uint32_t efststeq (uint32_t op1, uint32_t op2)
2318 0487d6a8 j_mayer
{
2319 1c97856d aurel32
    CPU_FloatU u1, u2;
2320 1c97856d aurel32
    u1.l = op1;
2321 1c97856d aurel32
    u2.l = op2;
2322 1c97856d aurel32
    return float32_eq(u1.f, u2.f, &env->spe_status) ? 4 : 0;
2323 0487d6a8 j_mayer
}
2324 0487d6a8 j_mayer
2325 1c97856d aurel32
static always_inline uint32_t efscmplt (uint32_t op1, uint32_t op2)
2326 0487d6a8 j_mayer
{
2327 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2328 1c97856d aurel32
    return efststlt(op1, op2);
2329 0487d6a8 j_mayer
}
2330 0487d6a8 j_mayer
2331 1c97856d aurel32
static always_inline uint32_t efscmpgt (uint32_t op1, uint32_t op2)
2332 0487d6a8 j_mayer
{
2333 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2334 1c97856d aurel32
    return efststgt(op1, op2);
2335 0487d6a8 j_mayer
}
2336 0487d6a8 j_mayer
2337 1c97856d aurel32
static always_inline uint32_t efscmpeq (uint32_t op1, uint32_t op2)
2338 0487d6a8 j_mayer
{
2339 0487d6a8 j_mayer
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2340 1c97856d aurel32
    return efststeq(op1, op2);
2341 0487d6a8 j_mayer
}
2342 0487d6a8 j_mayer
2343 1c97856d aurel32
#define HELPER_SINGLE_SPE_CMP(name)                                           \
2344 1c97856d aurel32
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
2345 1c97856d aurel32
{                                                                             \
2346 1c97856d aurel32
    return e##name(op1, op2) << 2;                                            \
2347 1c97856d aurel32
}
2348 1c97856d aurel32
/* efststlt */
2349 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststlt);
2350 1c97856d aurel32
/* efststgt */
2351 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststgt);
2352 1c97856d aurel32
/* efststeq */
2353 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fststeq);
2354 1c97856d aurel32
/* efscmplt */
2355 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmplt);
2356 1c97856d aurel32
/* efscmpgt */
2357 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpgt);
2358 1c97856d aurel32
/* efscmpeq */
2359 1c97856d aurel32
HELPER_SINGLE_SPE_CMP(fscmpeq);
2360 1c97856d aurel32
2361 1c97856d aurel32
static always_inline uint32_t evcmp_merge (int t0, int t1)
2362 0487d6a8 j_mayer
{
2363 1c97856d aurel32
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
2364 0487d6a8 j_mayer
}
2365 0487d6a8 j_mayer
2366 1c97856d aurel32
#define HELPER_VECTOR_SPE_CMP(name)                                           \
2367 1c97856d aurel32
uint32_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
2368 1c97856d aurel32
{                                                                             \
2369 1c97856d aurel32
    return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2));     \
2370 0487d6a8 j_mayer
}
2371 1c97856d aurel32
/* evfststlt */
2372 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststlt);
2373 1c97856d aurel32
/* evfststgt */
2374 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststgt);
2375 1c97856d aurel32
/* evfststeq */
2376 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fststeq);
2377 1c97856d aurel32
/* evfscmplt */
2378 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmplt);
2379 1c97856d aurel32
/* evfscmpgt */
2380 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpgt);
2381 1c97856d aurel32
/* evfscmpeq */
2382 1c97856d aurel32
HELPER_VECTOR_SPE_CMP(fscmpeq);
2383 0487d6a8 j_mayer
2384 1c97856d aurel32
/* Double-precision floating-point conversion */
2385 1c97856d aurel32
uint64_t helper_efdcfsi (uint32_t val)
2386 0487d6a8 j_mayer
{
2387 1c97856d aurel32
    CPU_DoubleU u;
2388 1c97856d aurel32
2389 1c97856d aurel32
    u.d = int32_to_float64(val, &env->spe_status);
2390 1c97856d aurel32
2391 1c97856d aurel32
    return u.ll;
2392 0487d6a8 j_mayer
}
2393 0487d6a8 j_mayer
2394 1c97856d aurel32
uint64_t helper_efdcfsid (uint64_t val)
2395 0487d6a8 j_mayer
{
2396 0ca9d380 aurel32
    CPU_DoubleU u;
2397 0487d6a8 j_mayer
2398 0ca9d380 aurel32
    u.d = int64_to_float64(val, &env->spe_status);
2399 0487d6a8 j_mayer
2400 0ca9d380 aurel32
    return u.ll;
2401 0487d6a8 j_mayer
}
2402 0487d6a8 j_mayer
2403 1c97856d aurel32
uint64_t helper_efdcfui (uint32_t val)
2404 1c97856d aurel32
{
2405 1c97856d aurel32
    CPU_DoubleU u;
2406 1c97856d aurel32
2407 1c97856d aurel32
    u.d = uint32_to_float64(val, &env->spe_status);
2408 1c97856d aurel32
2409 1c97856d aurel32
    return u.ll;
2410 1c97856d aurel32
}
2411 1c97856d aurel32
2412 1c97856d aurel32
uint64_t helper_efdcfuid (uint64_t val)
2413 0487d6a8 j_mayer
{
2414 0ca9d380 aurel32
    CPU_DoubleU u;
2415 0487d6a8 j_mayer
2416 0ca9d380 aurel32
    u.d = uint64_to_float64(val, &env->spe_status);
2417 0487d6a8 j_mayer
2418 0ca9d380 aurel32
    return u.ll;
2419 0487d6a8 j_mayer
}
2420 0487d6a8 j_mayer
2421 1c97856d aurel32
uint32_t helper_efdctsi (uint64_t val)
2422 0487d6a8 j_mayer
{
2423 0ca9d380 aurel32
    CPU_DoubleU u;
2424 0487d6a8 j_mayer
2425 0ca9d380 aurel32
    u.ll = val;
2426 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2427 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2428 0487d6a8 j_mayer
        return 0;
2429 0487d6a8 j_mayer
2430 1c97856d aurel32
    return float64_to_int32(u.d, &env->spe_status);
2431 0487d6a8 j_mayer
}
2432 0487d6a8 j_mayer
2433 1c97856d aurel32
uint32_t helper_efdctui (uint64_t val)
2434 0487d6a8 j_mayer
{
2435 0ca9d380 aurel32
    CPU_DoubleU u;
2436 0487d6a8 j_mayer
2437 0ca9d380 aurel32
    u.ll = val;
2438 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2439 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2440 0487d6a8 j_mayer
        return 0;
2441 0487d6a8 j_mayer
2442 1c97856d aurel32
    return float64_to_uint32(u.d, &env->spe_status);
2443 0487d6a8 j_mayer
}
2444 0487d6a8 j_mayer
2445 1c97856d aurel32
uint32_t helper_efdctsiz (uint64_t val)
2446 0487d6a8 j_mayer
{
2447 0ca9d380 aurel32
    CPU_DoubleU u;
2448 0487d6a8 j_mayer
2449 0ca9d380 aurel32
    u.ll = val;
2450 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2451 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2452 0487d6a8 j_mayer
        return 0;
2453 0487d6a8 j_mayer
2454 1c97856d aurel32
    return float64_to_int32_round_to_zero(u.d, &env->spe_status);
2455 0487d6a8 j_mayer
}
2456 0487d6a8 j_mayer
2457 1c97856d aurel32
uint64_t helper_efdctsidz (uint64_t val)
2458 0487d6a8 j_mayer
{
2459 0ca9d380 aurel32
    CPU_DoubleU u;
2460 0487d6a8 j_mayer
2461 0ca9d380 aurel32
    u.ll = val;
2462 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2463 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2464 0487d6a8 j_mayer
        return 0;
2465 0487d6a8 j_mayer
2466 1c97856d aurel32
    return float64_to_int64_round_to_zero(u.d, &env->spe_status);
2467 0487d6a8 j_mayer
}
2468 0487d6a8 j_mayer
2469 1c97856d aurel32
uint32_t helper_efdctuiz (uint64_t val)
2470 0487d6a8 j_mayer
{
2471 1c97856d aurel32
    CPU_DoubleU u;
2472 0487d6a8 j_mayer
2473 1c97856d aurel32
    u.ll = val;
2474 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
2475 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2476 1c97856d aurel32
        return 0;
2477 0487d6a8 j_mayer
2478 1c97856d aurel32
    return float64_to_uint32_round_to_zero(u.d, &env->spe_status);
2479 0487d6a8 j_mayer
}
2480 0487d6a8 j_mayer
2481 1c97856d aurel32
uint64_t helper_efdctuidz (uint64_t val)
2482 0487d6a8 j_mayer
{
2483 1c97856d aurel32
    CPU_DoubleU u;
2484 0487d6a8 j_mayer
2485 1c97856d aurel32
    u.ll = val;
2486 1c97856d aurel32
    /* NaN are not treated the same way IEEE 754 does */
2487 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2488 1c97856d aurel32
        return 0;
2489 0487d6a8 j_mayer
2490 1c97856d aurel32
    return float64_to_uint64_round_to_zero(u.d, &env->spe_status);
2491 0487d6a8 j_mayer
}
2492 0487d6a8 j_mayer
2493 1c97856d aurel32
uint64_t helper_efdcfsf (uint32_t val)
2494 0487d6a8 j_mayer
{
2495 0ca9d380 aurel32
    CPU_DoubleU u;
2496 0487d6a8 j_mayer
    float64 tmp;
2497 0487d6a8 j_mayer
2498 0ca9d380 aurel32
    u.d = int32_to_float64(val, &env->spe_status);
2499 0487d6a8 j_mayer
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2500 0ca9d380 aurel32
    u.d = float64_div(u.d, tmp, &env->spe_status);
2501 0487d6a8 j_mayer
2502 0ca9d380 aurel32
    return u.ll;
2503 0487d6a8 j_mayer
}
2504 0487d6a8 j_mayer
2505 1c97856d aurel32
uint64_t helper_efdcfuf (uint32_t val)
2506 0487d6a8 j_mayer
{
2507 0ca9d380 aurel32
    CPU_DoubleU u;
2508 0487d6a8 j_mayer
    float64 tmp;
2509 0487d6a8 j_mayer
2510 0ca9d380 aurel32
    u.d = uint32_to_float64(val, &env->spe_status);
2511 0487d6a8 j_mayer
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2512 0ca9d380 aurel32
    u.d = float64_div(u.d, tmp, &env->spe_status);
2513 0487d6a8 j_mayer
2514 0ca9d380 aurel32
    return u.ll;
2515 0487d6a8 j_mayer
}
2516 0487d6a8 j_mayer
2517 1c97856d aurel32
uint32_t helper_efdctsf (uint64_t val)
2518 0487d6a8 j_mayer
{
2519 0ca9d380 aurel32
    CPU_DoubleU u;
2520 0487d6a8 j_mayer
    float64 tmp;
2521 0487d6a8 j_mayer
2522 0ca9d380 aurel32
    u.ll = val;
2523 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2524 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2525 0487d6a8 j_mayer
        return 0;
2526 0487d6a8 j_mayer
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2527 0ca9d380 aurel32
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2528 0487d6a8 j_mayer
2529 0ca9d380 aurel32
    return float64_to_int32(u.d, &env->spe_status);
2530 0487d6a8 j_mayer
}
2531 0487d6a8 j_mayer
2532 1c97856d aurel32
uint32_t helper_efdctuf (uint64_t val)
2533 0487d6a8 j_mayer
{
2534 0ca9d380 aurel32
    CPU_DoubleU u;
2535 0487d6a8 j_mayer
    float64 tmp;
2536 0487d6a8 j_mayer
2537 0ca9d380 aurel32
    u.ll = val;
2538 0487d6a8 j_mayer
    /* NaN are not treated the same way IEEE 754 does */
2539 a44d2ce1 aurel32
    if (unlikely(float64_is_nan(u.d)))
2540 0487d6a8 j_mayer
        return 0;
2541 0487d6a8 j_mayer
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2542 0ca9d380 aurel32
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2543 0487d6a8 j_mayer
2544 0ca9d380 aurel32
    return float64_to_uint32(u.d, &env->spe_status);
2545 0487d6a8 j_mayer
}
2546 0487d6a8 j_mayer
2547 1c97856d aurel32
uint32_t helper_efscfd (uint64_t val)
2548 0487d6a8 j_mayer
{
2549 0ca9d380 aurel32
    CPU_DoubleU u1;
2550 0ca9d380 aurel32
    CPU_FloatU u2;
2551 0487d6a8 j_mayer
2552 0ca9d380 aurel32
    u1.ll = val;
2553 0ca9d380 aurel32
    u2.f = float64_to_float32(u1.d, &env->spe_status);
2554 0487d6a8 j_mayer
2555 0ca9d380 aurel32
    return u2.l;
2556 0487d6a8 j_mayer
}
2557 0487d6a8 j_mayer
2558 1c97856d aurel32
uint64_t helper_efdcfs (uint32_t val)
2559 0487d6a8 j_mayer
{
2560 0ca9d380 aurel32
    CPU_DoubleU u2;
2561 0ca9d380 aurel32
    CPU_FloatU u1;
2562 0487d6a8 j_mayer
2563 0ca9d380 aurel32
    u1.l = val;
2564 0ca9d380 aurel32
    u2.d = float32_to_float64(u1.f, &env->spe_status);
2565 0487d6a8 j_mayer
2566 0ca9d380 aurel32
    return u2.ll;
2567 0487d6a8 j_mayer
}
2568 0487d6a8 j_mayer
2569 1c97856d aurel32
/* Double precision fixed-point arithmetic */
2570 1c97856d aurel32
uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
2571 0487d6a8 j_mayer
{
2572 1c97856d aurel32
    CPU_DoubleU u1, u2;
2573 1c97856d aurel32
    u1.ll = op1;
2574 1c97856d aurel32
    u2.ll = op2;
2575 1c97856d aurel32
    u1.d = float64_add(u1.d, u2.d, &env->spe_status);
2576 1c97856d aurel32
    return u1.ll;
2577 0487d6a8 j_mayer
}
2578 0487d6a8 j_mayer
2579 1c97856d aurel32
uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
2580 0487d6a8 j_mayer
{
2581 1c97856d aurel32
    CPU_DoubleU u1, u2;
2582 1c97856d aurel32
    u1.ll = op1;
2583 1c97856d aurel32
    u2.ll = op2;
2584 1c97856d aurel32
    u1.d = float64_sub(u1.d, u2.d, &env->spe_status);
2585 1c97856d aurel32
    return u1.ll;
2586 0487d6a8 j_mayer
}
2587 0487d6a8 j_mayer
2588 1c97856d aurel32
uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
2589 0487d6a8 j_mayer
{
2590 1c97856d aurel32
    CPU_DoubleU u1, u2;
2591 1c97856d aurel32
    u1.ll = op1;
2592 1c97856d aurel32
    u2.ll = op2;
2593 1c97856d aurel32
    u1.d = float64_mul(u1.d, u2.d, &env->spe_status);
2594 1c97856d aurel32
    return u1.ll;
2595 0487d6a8 j_mayer
}
2596 0487d6a8 j_mayer
2597 1c97856d aurel32
uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
2598 0487d6a8 j_mayer
{
2599 1c97856d aurel32
    CPU_DoubleU u1, u2;
2600 1c97856d aurel32
    u1.ll = op1;
2601 1c97856d aurel32
    u2.ll = op2;
2602 1c97856d aurel32
    u1.d = float64_div(u1.d, u2.d, &env->spe_status);
2603 1c97856d aurel32
    return u1.ll;
2604 0487d6a8 j_mayer
}
2605 0487d6a8 j_mayer
2606 1c97856d aurel32
/* Double precision floating point helpers */
2607 1c97856d aurel32
uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
2608 0487d6a8 j_mayer
{
2609 1c97856d aurel32
    CPU_DoubleU u1, u2;
2610 1c97856d aurel32
    u1.ll = op1;
2611 1c97856d aurel32
    u2.ll = op2;
2612 1c97856d aurel32
    return float64_lt(u1.d, u2.d, &env->spe_status) ? 4 : 0;
2613 0487d6a8 j_mayer
}
2614 0487d6a8 j_mayer
2615 1c97856d aurel32
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
2616 0487d6a8 j_mayer
{
2617 1c97856d aurel32
    CPU_DoubleU u1, u2;
2618 1c97856d aurel32
    u1.ll = op1;
2619 1c97856d aurel32
    u2.ll = op2;
2620 1c97856d aurel32
    return float64_le(u1.d, u2.d, &env->spe_status) ? 0 : 4;
2621 0487d6a8 j_mayer
}
2622 0487d6a8 j_mayer
2623 1c97856d aurel32
uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
2624 0487d6a8 j_mayer
{
2625 1c97856d aurel32
    CPU_DoubleU u1, u2;
2626 1c97856d aurel32
    u1.ll = op1;
2627 1c97856d aurel32
    u2.ll = op2;
2628 1c97856d aurel32
    return float64_eq(u1.d, u2.d, &env->spe_status) ? 4 : 0;
2629 0487d6a8 j_mayer
}
2630 0487d6a8 j_mayer
2631 1c97856d aurel32
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
2632 0487d6a8 j_mayer
{
2633 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2634 1c97856d aurel32
    return helper_efdtstlt(op1, op2);
2635 0487d6a8 j_mayer
}
2636 0487d6a8 j_mayer
2637 1c97856d aurel32
uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
2638 1c97856d aurel32
{
2639 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2640 1c97856d aurel32
    return helper_efdtstgt(op1, op2);
2641 1c97856d aurel32
}
2642 0487d6a8 j_mayer
2643 1c97856d aurel32
uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
2644 1c97856d aurel32
{
2645 1c97856d aurel32
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2646 1c97856d aurel32
    return helper_efdtsteq(op1, op2);
2647 1c97856d aurel32
}
2648 0487d6a8 j_mayer
2649 fdabc366 bellard
/*****************************************************************************/
2650 fdabc366 bellard
/* Softmmu support */
2651 fdabc366 bellard
#if !defined (CONFIG_USER_ONLY)
2652 fdabc366 bellard
2653 fdabc366 bellard
#define MMUSUFFIX _mmu
2654 fdabc366 bellard
2655 fdabc366 bellard
#define SHIFT 0
2656 fdabc366 bellard
#include "softmmu_template.h"
2657 fdabc366 bellard
2658 fdabc366 bellard
#define SHIFT 1
2659 fdabc366 bellard
#include "softmmu_template.h"
2660 fdabc366 bellard
2661 fdabc366 bellard
#define SHIFT 2
2662 fdabc366 bellard
#include "softmmu_template.h"
2663 fdabc366 bellard
2664 fdabc366 bellard
#define SHIFT 3
2665 fdabc366 bellard
#include "softmmu_template.h"
2666 fdabc366 bellard
2667 fdabc366 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
2668 fdabc366 bellard
   NULL, it means that the function was called in C code (i.e. not
2669 fdabc366 bellard
   from generated code or from helper.c) */
2670 fdabc366 bellard
/* XXX: fix it to restore all registers */
2671 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2672 fdabc366 bellard
{
2673 fdabc366 bellard
    TranslationBlock *tb;
2674 fdabc366 bellard
    CPUState *saved_env;
2675 44f8625d bellard
    unsigned long pc;
2676 fdabc366 bellard
    int ret;
2677 fdabc366 bellard
2678 fdabc366 bellard
    /* XXX: hack to restore env in all cases, even if not called from
2679 fdabc366 bellard
       generated code */
2680 fdabc366 bellard
    saved_env = env;
2681 fdabc366 bellard
    env = cpu_single_env;
2682 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2683 76a66253 j_mayer
    if (unlikely(ret != 0)) {
2684 fdabc366 bellard
        if (likely(retaddr)) {
2685 fdabc366 bellard
            /* now we have a real cpu fault */
2686 44f8625d bellard
            pc = (unsigned long)retaddr;
2687 fdabc366 bellard
            tb = tb_find_pc(pc);
2688 fdabc366 bellard
            if (likely(tb)) {
2689 fdabc366 bellard
                /* the PC is inside the translated code. It means that we have
2690 fdabc366 bellard
                   a virtual CPU fault */
2691 fdabc366 bellard
                cpu_restore_state(tb, env, pc, NULL);
2692 76a66253 j_mayer
            }
2693 fdabc366 bellard
        }
2694 e06fcd75 aurel32
        helper_raise_exception_err(env->exception_index, env->error_code);
2695 fdabc366 bellard
    }
2696 fdabc366 bellard
    env = saved_env;
2697 9a64fbe4 bellard
}
2698 9a64fbe4 bellard
2699 74d37793 aurel32
/* Segment registers load and store */
2700 74d37793 aurel32
target_ulong helper_load_sr (target_ulong sr_num)
2701 74d37793 aurel32
{
2702 74d37793 aurel32
    return env->sr[sr_num];
2703 74d37793 aurel32
}
2704 74d37793 aurel32
2705 74d37793 aurel32
void helper_store_sr (target_ulong sr_num, target_ulong val)
2706 74d37793 aurel32
{
2707 45d827d2 aurel32
    ppc_store_sr(env, sr_num, val);
2708 74d37793 aurel32
}
2709 74d37793 aurel32
2710 74d37793 aurel32
/* SLB management */
2711 74d37793 aurel32
#if defined(TARGET_PPC64)
2712 74d37793 aurel32
target_ulong helper_load_slb (target_ulong slb_nr)
2713 74d37793 aurel32
{
2714 74d37793 aurel32
    return ppc_load_slb(env, slb_nr);
2715 74d37793 aurel32
}
2716 74d37793 aurel32
2717 74d37793 aurel32
void helper_store_slb (target_ulong slb_nr, target_ulong rs)
2718 74d37793 aurel32
{
2719 74d37793 aurel32
    ppc_store_slb(env, slb_nr, rs);
2720 74d37793 aurel32
}
2721 74d37793 aurel32
2722 74d37793 aurel32
void helper_slbia (void)
2723 74d37793 aurel32
{
2724 74d37793 aurel32
    ppc_slb_invalidate_all(env);
2725 74d37793 aurel32
}
2726 74d37793 aurel32
2727 74d37793 aurel32
void helper_slbie (target_ulong addr)
2728 74d37793 aurel32
{
2729 74d37793 aurel32
    ppc_slb_invalidate_one(env, addr);
2730 74d37793 aurel32
}
2731 74d37793 aurel32
2732 74d37793 aurel32
#endif /* defined(TARGET_PPC64) */
2733 74d37793 aurel32
2734 74d37793 aurel32
/* TLB management */
2735 74d37793 aurel32
void helper_tlbia (void)
2736 74d37793 aurel32
{
2737 74d37793 aurel32
    ppc_tlb_invalidate_all(env);
2738 74d37793 aurel32
}
2739 74d37793 aurel32
2740 74d37793 aurel32
void helper_tlbie (target_ulong addr)
2741 74d37793 aurel32
{
2742 74d37793 aurel32
    ppc_tlb_invalidate_one(env, addr);
2743 74d37793 aurel32
}
2744 74d37793 aurel32
2745 76a66253 j_mayer
/* Software driven TLBs management */
2746 76a66253 j_mayer
/* PowerPC 602/603 software TLB load instructions helpers */
2747 74d37793 aurel32
static void do_6xx_tlb (target_ulong new_EPN, int is_code)
2748 76a66253 j_mayer
{
2749 76a66253 j_mayer
    target_ulong RPN, CMP, EPN;
2750 76a66253 j_mayer
    int way;
2751 d9bce9d9 j_mayer
2752 76a66253 j_mayer
    RPN = env->spr[SPR_RPA];
2753 76a66253 j_mayer
    if (is_code) {
2754 76a66253 j_mayer
        CMP = env->spr[SPR_ICMP];
2755 76a66253 j_mayer
        EPN = env->spr[SPR_IMISS];
2756 76a66253 j_mayer
    } else {
2757 76a66253 j_mayer
        CMP = env->spr[SPR_DCMP];
2758 76a66253 j_mayer
        EPN = env->spr[SPR_DMISS];
2759 76a66253 j_mayer
    }
2760 76a66253 j_mayer
    way = (env->spr[SPR_SRR1] >> 17) & 1;
2761 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2762 76a66253 j_mayer
    if (loglevel != 0) {
2763 0e69805a aurel32
        fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
2764 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
2765 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
2766 76a66253 j_mayer
    }
2767 76a66253 j_mayer
#endif
2768 76a66253 j_mayer
    /* Store this TLB */
2769 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2770 d9bce9d9 j_mayer
                     way, is_code, CMP, RPN);
2771 76a66253 j_mayer
}
2772 76a66253 j_mayer
2773 74d37793 aurel32
void helper_6xx_tlbd (target_ulong EPN)
2774 0f3955e2 aurel32
{
2775 74d37793 aurel32
    do_6xx_tlb(EPN, 0);
2776 0f3955e2 aurel32
}
2777 0f3955e2 aurel32
2778 74d37793 aurel32
void helper_6xx_tlbi (target_ulong EPN)
2779 0f3955e2 aurel32
{
2780 74d37793 aurel32
    do_6xx_tlb(EPN, 1);
2781 0f3955e2 aurel32
}
2782 0f3955e2 aurel32
2783 0f3955e2 aurel32
/* PowerPC 74xx software TLB load instructions helpers */
2784 74d37793 aurel32
static void do_74xx_tlb (target_ulong new_EPN, int is_code)
2785 7dbe11ac j_mayer
{
2786 7dbe11ac j_mayer
    target_ulong RPN, CMP, EPN;
2787 7dbe11ac j_mayer
    int way;
2788 7dbe11ac j_mayer
2789 7dbe11ac j_mayer
    RPN = env->spr[SPR_PTELO];
2790 7dbe11ac j_mayer
    CMP = env->spr[SPR_PTEHI];
2791 7dbe11ac j_mayer
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2792 7dbe11ac j_mayer
    way = env->spr[SPR_TLBMISS] & 0x3;
2793 7dbe11ac j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2794 7dbe11ac j_mayer
    if (loglevel != 0) {
2795 0e69805a aurel32
        fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
2796 6b542af7 j_mayer
                " PTE1 " ADDRX " way %d\n",
2797 0e69805a aurel32
                __func__, new_EPN, EPN, CMP, RPN, way);
2798 7dbe11ac j_mayer
    }
2799 7dbe11ac j_mayer
#endif
2800 7dbe11ac j_mayer
    /* Store this TLB */
2801 0f3955e2 aurel32
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2802 7dbe11ac j_mayer
                     way, is_code, CMP, RPN);
2803 7dbe11ac j_mayer
}
2804 7dbe11ac j_mayer
2805 74d37793 aurel32
void helper_74xx_tlbd (target_ulong EPN)
2806 0f3955e2 aurel32
{
2807 74d37793 aurel32
    do_74xx_tlb(EPN, 0);
2808 0f3955e2 aurel32
}
2809 0f3955e2 aurel32
2810 74d37793 aurel32
void helper_74xx_tlbi (target_ulong EPN)
2811 0f3955e2 aurel32
{
2812 74d37793 aurel32
    do_74xx_tlb(EPN, 1);
2813 0f3955e2 aurel32
}
2814 0f3955e2 aurel32
2815 a11b8151 j_mayer
static always_inline target_ulong booke_tlb_to_page_size (int size)
2816 a8dea12f j_mayer
{
2817 a8dea12f j_mayer
    return 1024 << (2 * size);
2818 a8dea12f j_mayer
}
2819 a8dea12f j_mayer
2820 a11b8151 j_mayer
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
2821 a8dea12f j_mayer
{
2822 a8dea12f j_mayer
    int size;
2823 a8dea12f j_mayer
2824 a8dea12f j_mayer
    switch (page_size) {
2825 a8dea12f j_mayer
    case 0x00000400UL:
2826 a8dea12f j_mayer
        size = 0x0;
2827 a8dea12f j_mayer
        break;
2828 a8dea12f j_mayer
    case 0x00001000UL:
2829 a8dea12f j_mayer
        size = 0x1;
2830 a8dea12f j_mayer
        break;
2831 a8dea12f j_mayer
    case 0x00004000UL:
2832 a8dea12f j_mayer
        size = 0x2;
2833 a8dea12f j_mayer
        break;
2834 a8dea12f j_mayer
    case 0x00010000UL:
2835 a8dea12f j_mayer
        size = 0x3;
2836 a8dea12f j_mayer
        break;
2837 a8dea12f j_mayer
    case 0x00040000UL:
2838 a8dea12f j_mayer
        size = 0x4;
2839 a8dea12f j_mayer
        break;
2840 a8dea12f j_mayer
    case 0x00100000UL:
2841 a8dea12f j_mayer
        size = 0x5;
2842 a8dea12f j_mayer
        break;
2843 a8dea12f j_mayer
    case 0x00400000UL:
2844 a8dea12f j_mayer
        size = 0x6;
2845 a8dea12f j_mayer
        break;
2846 a8dea12f j_mayer
    case 0x01000000UL:
2847 a8dea12f j_mayer
        size = 0x7;
2848 a8dea12f j_mayer
        break;
2849 a8dea12f j_mayer
    case 0x04000000UL:
2850 a8dea12f j_mayer
        size = 0x8;
2851 a8dea12f j_mayer
        break;
2852 a8dea12f j_mayer
    case 0x10000000UL:
2853 a8dea12f j_mayer
        size = 0x9;
2854 a8dea12f j_mayer
        break;
2855 a8dea12f j_mayer
    case 0x40000000UL:
2856 a8dea12f j_mayer
        size = 0xA;
2857 a8dea12f j_mayer
        break;
2858 a8dea12f j_mayer
#if defined (TARGET_PPC64)
2859 a8dea12f j_mayer
    case 0x000100000000ULL:
2860 a8dea12f j_mayer
        size = 0xB;
2861 a8dea12f j_mayer
        break;
2862 a8dea12f j_mayer
    case 0x000400000000ULL:
2863 a8dea12f j_mayer
        size = 0xC;
2864 a8dea12f j_mayer
        break;
2865 a8dea12f j_mayer
    case 0x001000000000ULL:
2866 a8dea12f j_mayer
        size = 0xD;
2867 a8dea12f j_mayer
        break;
2868 a8dea12f j_mayer
    case 0x004000000000ULL:
2869 a8dea12f j_mayer
        size = 0xE;
2870 a8dea12f j_mayer
        break;
2871 a8dea12f j_mayer
    case 0x010000000000ULL:
2872 a8dea12f j_mayer
        size = 0xF;
2873 a8dea12f j_mayer
        break;
2874 a8dea12f j_mayer
#endif
2875 a8dea12f j_mayer
    default:
2876 a8dea12f j_mayer
        size = -1;
2877 a8dea12f j_mayer
        break;
2878 a8dea12f j_mayer
    }
2879 a8dea12f j_mayer
2880 a8dea12f j_mayer
    return size;
2881 a8dea12f j_mayer
}
2882 a8dea12f j_mayer
2883 76a66253 j_mayer
/* Helpers for 4xx TLB management */
2884 74d37793 aurel32
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
2885 76a66253 j_mayer
{
2886 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
2887 74d37793 aurel32
    target_ulong ret;
2888 a8dea12f j_mayer
    int size;
2889 76a66253 j_mayer
2890 74d37793 aurel32
    entry &= 0x3F;
2891 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
2892 74d37793 aurel32
    ret = tlb->EPN;
2893 a8dea12f j_mayer
    if (tlb->prot & PAGE_VALID)
2894 74d37793 aurel32
        ret |= 0x400;
2895 a8dea12f j_mayer
    size = booke_page_size_to_tlb(tlb->size);
2896 a8dea12f j_mayer
    if (size < 0 || size > 0x7)
2897 a8dea12f j_mayer
        size = 1;
2898 74d37793 aurel32
    ret |= size << 7;
2899 a8dea12f j_mayer
    env->spr[SPR_40x_PID] = tlb->PID;
2900 74d37793 aurel32
    return ret;
2901 76a66253 j_mayer
}
2902 76a66253 j_mayer
2903 74d37793 aurel32
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
2904 76a66253 j_mayer
{
2905 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
2906 74d37793 aurel32
    target_ulong ret;
2907 76a66253 j_mayer
2908 74d37793 aurel32
    entry &= 0x3F;
2909 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
2910 74d37793 aurel32
    ret = tlb->RPN;
2911 a8dea12f j_mayer
    if (tlb->prot & PAGE_EXEC)
2912 74d37793 aurel32
        ret |= 0x200;
2913 a8dea12f j_mayer
    if (tlb->prot & PAGE_WRITE)
2914 74d37793 aurel32
        ret |= 0x100;
2915 74d37793 aurel32
    return ret;
2916 76a66253 j_mayer
}
2917 76a66253 j_mayer
2918 74d37793 aurel32
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
2919 76a66253 j_mayer
{
2920 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
2921 76a66253 j_mayer
    target_ulong page, end;
2922 76a66253 j_mayer
2923 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2924 6b80055d j_mayer
    if (loglevel != 0) {
2925 0e69805a aurel32
        fprintf(logfile, "%s entry %d val " ADDRX "\n", __func__, (int)entry, val);
2926 c55e9aef j_mayer
    }
2927 c55e9aef j_mayer
#endif
2928 74d37793 aurel32
    entry &= 0x3F;
2929 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
2930 76a66253 j_mayer
    /* Invalidate previous TLB (if it's valid) */
2931 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
2932 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
2933 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2934 6b80055d j_mayer
        if (loglevel != 0) {
2935 c55e9aef j_mayer
            fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
2936 74d37793 aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
2937 c55e9aef j_mayer
        }
2938 c55e9aef j_mayer
#endif
2939 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2940 76a66253 j_mayer
            tlb_flush_page(env, page);
2941 76a66253 j_mayer
    }
2942 74d37793 aurel32
    tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
2943 c294fc58 j_mayer
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2944 c294fc58 j_mayer
     * If this ever occurs, one should use the ppcemb target instead
2945 c294fc58 j_mayer
     * of the ppc or ppc64 one
2946 c294fc58 j_mayer
     */
2947 74d37793 aurel32
    if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
2948 71c8b8fd j_mayer
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2949 71c8b8fd j_mayer
                  "are not supported (%d)\n",
2950 74d37793 aurel32
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2951 c294fc58 j_mayer
    }
2952 74d37793 aurel32
    tlb->EPN = val & ~(tlb->size - 1);
2953 74d37793 aurel32
    if (val & 0x40)
2954 76a66253 j_mayer
        tlb->prot |= PAGE_VALID;
2955 76a66253 j_mayer
    else
2956 76a66253 j_mayer
        tlb->prot &= ~PAGE_VALID;
2957 74d37793 aurel32
    if (val & 0x20) {
2958 c294fc58 j_mayer
        /* XXX: TO BE FIXED */
2959 c294fc58 j_mayer
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
2960 c294fc58 j_mayer
    }
2961 c55e9aef j_mayer
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2962 74d37793 aurel32
    tlb->attr = val & 0xFF;
2963 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2964 c294fc58 j_mayer
    if (loglevel != 0) {
2965 c294fc58 j_mayer
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2966 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2967 0e69805a aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2968 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
2969 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
2970 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
2971 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2972 c55e9aef j_mayer
    }
2973 c55e9aef j_mayer
#endif
2974 76a66253 j_mayer
    /* Invalidate new TLB (if valid) */
2975 76a66253 j_mayer
    if (tlb->prot & PAGE_VALID) {
2976 76a66253 j_mayer
        end = tlb->EPN + tlb->size;
2977 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2978 6b80055d j_mayer
        if (loglevel != 0) {
2979 c55e9aef j_mayer
            fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
2980 0e69805a aurel32
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
2981 c55e9aef j_mayer
        }
2982 c55e9aef j_mayer
#endif
2983 76a66253 j_mayer
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2984 76a66253 j_mayer
            tlb_flush_page(env, page);
2985 76a66253 j_mayer
    }
2986 76a66253 j_mayer
}
2987 76a66253 j_mayer
2988 74d37793 aurel32
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
2989 76a66253 j_mayer
{
2990 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
2991 76a66253 j_mayer
2992 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2993 6b80055d j_mayer
    if (loglevel != 0) {
2994 0e69805a aurel32
        fprintf(logfile, "%s entry %i val " ADDRX "\n", __func__, (int)entry, val);
2995 c55e9aef j_mayer
    }
2996 c55e9aef j_mayer
#endif
2997 74d37793 aurel32
    entry &= 0x3F;
2998 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
2999 74d37793 aurel32
    tlb->RPN = val & 0xFFFFFC00;
3000 76a66253 j_mayer
    tlb->prot = PAGE_READ;
3001 74d37793 aurel32
    if (val & 0x200)
3002 76a66253 j_mayer
        tlb->prot |= PAGE_EXEC;
3003 74d37793 aurel32
    if (val & 0x100)
3004 76a66253 j_mayer
        tlb->prot |= PAGE_WRITE;
3005 c55e9aef j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3006 6b80055d j_mayer
    if (loglevel != 0) {
3007 6b80055d j_mayer
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3008 c55e9aef j_mayer
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3009 74d37793 aurel32
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3010 c55e9aef j_mayer
                tlb->prot & PAGE_READ ? 'r' : '-',
3011 c55e9aef j_mayer
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3012 c55e9aef j_mayer
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3013 c55e9aef j_mayer
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3014 c55e9aef j_mayer
    }
3015 c55e9aef j_mayer
#endif
3016 76a66253 j_mayer
}
3017 5eb7995e j_mayer
3018 74d37793 aurel32
target_ulong helper_4xx_tlbsx (target_ulong address)
3019 74d37793 aurel32
{
3020 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
3021 74d37793 aurel32
}
3022 74d37793 aurel32
3023 a4bb6c3e j_mayer
/* PowerPC 440 TLB management */
3024 74d37793 aurel32
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
3025 5eb7995e j_mayer
{
3026 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
3027 a4bb6c3e j_mayer
    target_ulong EPN, RPN, size;
3028 5eb7995e j_mayer
    int do_flush_tlbs;
3029 5eb7995e j_mayer
3030 5eb7995e j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
3031 5eb7995e j_mayer
    if (loglevel != 0) {
3032 0e69805a aurel32
        fprintf(logfile, "%s word %d entry %d value " ADDRX "\n",
3033 0e69805a aurel32
                __func__, word, (int)entry, value);
3034 5eb7995e j_mayer
    }
3035 5eb7995e j_mayer
#endif
3036 5eb7995e j_mayer
    do_flush_tlbs = 0;
3037 74d37793 aurel32
    entry &= 0x3F;
3038 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3039 a4bb6c3e j_mayer
    switch (word) {
3040 a4bb6c3e j_mayer
    default:
3041 a4bb6c3e j_mayer
        /* Just here to please gcc */
3042 a4bb6c3e j_mayer
    case 0:
3043 74d37793 aurel32
        EPN = value & 0xFFFFFC00;
3044 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
3045 5eb7995e j_mayer
            do_flush_tlbs = 1;
3046 a4bb6c3e j_mayer
        tlb->EPN = EPN;
3047 74d37793 aurel32
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
3048 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
3049 a4bb6c3e j_mayer
            do_flush_tlbs = 1;
3050 a4bb6c3e j_mayer
        tlb->size = size;
3051 a4bb6c3e j_mayer
        tlb->attr &= ~0x1;
3052 74d37793 aurel32
        tlb->attr |= (value >> 8) & 1;
3053 74d37793 aurel32
        if (value & 0x200) {
3054 a4bb6c3e j_mayer
            tlb->prot |= PAGE_VALID;
3055 a4bb6c3e j_mayer
        } else {
3056 a4bb6c3e j_mayer
            if (tlb->prot & PAGE_VALID) {
3057 a4bb6c3e j_mayer
                tlb->prot &= ~PAGE_VALID;
3058 a4bb6c3e j_mayer
                do_flush_tlbs = 1;
3059 a4bb6c3e j_mayer
            }
3060 5eb7995e j_mayer
        }
3061 a4bb6c3e j_mayer
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
3062 a4bb6c3e j_mayer
        if (do_flush_tlbs)
3063 a4bb6c3e j_mayer
            tlb_flush(env, 1);
3064 a4bb6c3e j_mayer
        break;
3065 a4bb6c3e j_mayer
    case 1:
3066 74d37793 aurel32
        RPN = value & 0xFFFFFC0F;
3067 a4bb6c3e j_mayer
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
3068 a4bb6c3e j_mayer
            tlb_flush(env, 1);
3069 a4bb6c3e j_mayer
        tlb->RPN = RPN;
3070 a4bb6c3e j_mayer
        break;
3071 a4bb6c3e j_mayer
    case 2:
3072 74d37793 aurel32
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
3073 a4bb6c3e j_mayer
        tlb->prot = tlb->prot & PAGE_VALID;
3074 74d37793 aurel32
        if (value & 0x1)
3075 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ << 4;
3076 74d37793 aurel32
        if (value & 0x2)
3077 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE << 4;
3078 74d37793 aurel32
        if (value & 0x4)
3079 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC << 4;
3080 74d37793 aurel32
        if (value & 0x8)
3081 a4bb6c3e j_mayer
            tlb->prot |= PAGE_READ;
3082 74d37793 aurel32
        if (value & 0x10)
3083 a4bb6c3e j_mayer
            tlb->prot |= PAGE_WRITE;
3084 74d37793 aurel32
        if (value & 0x20)
3085 a4bb6c3e j_mayer
            tlb->prot |= PAGE_EXEC;
3086 a4bb6c3e j_mayer
        break;
3087 5eb7995e j_mayer
    }
3088 5eb7995e j_mayer
}
3089 5eb7995e j_mayer
3090 74d37793 aurel32
target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
3091 5eb7995e j_mayer
{
3092 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
3093 74d37793 aurel32
    target_ulong ret;
3094 5eb7995e j_mayer
    int size;
3095 5eb7995e j_mayer
3096 74d37793 aurel32
    entry &= 0x3F;
3097 74d37793 aurel32
    tlb = &env->tlb[entry].tlbe;
3098 a4bb6c3e j_mayer
    switch (word) {
3099 a4bb6c3e j_mayer
    default:
3100 a4bb6c3e j_mayer
        /* Just here to please gcc */
3101 a4bb6c3e j_mayer
    case 0:
3102 74d37793 aurel32
        ret = tlb->EPN;
3103 a4bb6c3e j_mayer
        size = booke_page_size_to_tlb(tlb->size);
3104 a4bb6c3e j_mayer
        if (size < 0 || size > 0xF)
3105 a4bb6c3e j_mayer
            size = 1;
3106 74d37793 aurel32
        ret |= size << 4;
3107 a4bb6c3e j_mayer
        if (tlb->attr & 0x1)
3108 74d37793 aurel32
            ret |= 0x100;
3109 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_VALID)
3110 74d37793 aurel32
            ret |= 0x200;
3111 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
3112 a4bb6c3e j_mayer
        env->spr[SPR_440_MMUCR] |= tlb->PID;
3113 a4bb6c3e j_mayer
        break;
3114 a4bb6c3e j_mayer
    case 1:
3115 74d37793 aurel32
        ret = tlb->RPN;
3116 a4bb6c3e j_mayer
        break;
3117 a4bb6c3e j_mayer
    case 2:
3118 74d37793 aurel32
        ret = tlb->attr & ~0x1;
3119 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_READ << 4))
3120 74d37793 aurel32
            ret |= 0x1;
3121 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_WRITE << 4))
3122 74d37793 aurel32
            ret |= 0x2;
3123 a4bb6c3e j_mayer
        if (tlb->prot & (PAGE_EXEC << 4))
3124 74d37793 aurel32
            ret |= 0x4;
3125 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_READ)
3126 74d37793 aurel32
            ret |= 0x8;
3127 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_WRITE)
3128 74d37793 aurel32
            ret |= 0x10;
3129 a4bb6c3e j_mayer
        if (tlb->prot & PAGE_EXEC)
3130 74d37793 aurel32
            ret |= 0x20;
3131 a4bb6c3e j_mayer
        break;
3132 a4bb6c3e j_mayer
    }
3133 74d37793 aurel32
    return ret;
3134 5eb7995e j_mayer
}
3135 74d37793 aurel32
3136 74d37793 aurel32
target_ulong helper_440_tlbsx (target_ulong address)
3137 74d37793 aurel32
{
3138 74d37793 aurel32
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
3139 74d37793 aurel32
}
3140 74d37793 aurel32
3141 76a66253 j_mayer
#endif /* !CONFIG_USER_ONLY */