Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ f9ebe432

History | View | Annotate | Download (12.9 kB)

1 9a64fbe4 bellard
/*
2 3fc6c082 bellard
 *  PowerPC emulation helpers for qemu.
3 9a64fbe4 bellard
 * 
4 3fc6c082 bellard
 *  Copyright (c) 2003-2005 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 9a64fbe4 bellard
22 9a64fbe4 bellard
#define MEMSUFFIX _raw
23 9a64fbe4 bellard
#include "op_helper_mem.h"
24 a541f297 bellard
#if !defined(CONFIG_USER_ONLY)
25 9a64fbe4 bellard
#define MEMSUFFIX _user
26 9a64fbe4 bellard
#include "op_helper_mem.h"
27 9a64fbe4 bellard
#define MEMSUFFIX _kernel
28 9a64fbe4 bellard
#include "op_helper_mem.h"
29 9a64fbe4 bellard
#endif
30 9a64fbe4 bellard
31 fdabc366 bellard
//#define DEBUG_OP
32 fdabc366 bellard
//#define DEBUG_EXCEPTIONS
33 fdabc366 bellard
//#define FLUSH_ALL_TLBS
34 fdabc366 bellard
35 fdabc366 bellard
#define Ts0 (long)((target_long)T0)
36 fdabc366 bellard
#define Ts1 (long)((target_long)T1)
37 fdabc366 bellard
#define Ts2 (long)((target_long)T2)
38 fdabc366 bellard
39 9a64fbe4 bellard
/*****************************************************************************/
40 9a64fbe4 bellard
/* Exceptions processing helpers */
41 9fddaa0c bellard
void cpu_loop_exit(void)
42 9a64fbe4 bellard
{
43 9fddaa0c bellard
    longjmp(env->jmp_env, 1);
44 9a64fbe4 bellard
}
45 9a64fbe4 bellard
46 9fddaa0c bellard
void do_raise_exception_err (uint32_t exception, int error_code)
47 9a64fbe4 bellard
{
48 9fddaa0c bellard
#if 0
49 9fddaa0c bellard
    printf("Raise exception %3x code : %d\n", exception, error_code);
50 9fddaa0c bellard
#endif
51 9fddaa0c bellard
    switch (exception) {
52 9fddaa0c bellard
    case EXCP_PROGRAM:
53 9fddaa0c bellard
        if (error_code == EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
54 9fddaa0c bellard
            return;
55 9fddaa0c bellard
        break;
56 9fddaa0c bellard
    default:
57 9fddaa0c bellard
        break;
58 9a64fbe4 bellard
}
59 9fddaa0c bellard
    env->exception_index = exception;
60 9fddaa0c bellard
    env->error_code = error_code;
61 9a64fbe4 bellard
        cpu_loop_exit();
62 9a64fbe4 bellard
    }
63 9fddaa0c bellard
64 9fddaa0c bellard
void do_raise_exception (uint32_t exception)
65 9fddaa0c bellard
{
66 9fddaa0c bellard
    do_raise_exception_err(exception, 0);
67 9a64fbe4 bellard
}
68 9a64fbe4 bellard
69 9a64fbe4 bellard
/*****************************************************************************/
70 fdabc366 bellard
/* Fixed point operations helpers */
71 fdabc366 bellard
void do_addo (void)
72 fdabc366 bellard
{
73 fdabc366 bellard
    T2 = T0;
74 fdabc366 bellard
    T0 += T1;
75 fdabc366 bellard
    if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
76 fdabc366 bellard
        xer_ov = 0;
77 fdabc366 bellard
    } else {
78 fdabc366 bellard
        xer_so = 1;
79 fdabc366 bellard
        xer_ov = 1;
80 fdabc366 bellard
    }
81 fdabc366 bellard
}
82 fdabc366 bellard
83 fdabc366 bellard
void do_addco (void)
84 fdabc366 bellard
{
85 fdabc366 bellard
    T2 = T0;
86 fdabc366 bellard
    T0 += T1;
87 fdabc366 bellard
    if (likely(T0 >= T2)) {
88 fdabc366 bellard
        xer_ca = 0;
89 fdabc366 bellard
    } else {
90 fdabc366 bellard
        xer_ca = 1;
91 fdabc366 bellard
    }
92 fdabc366 bellard
    if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
93 fdabc366 bellard
        xer_ov = 0;
94 fdabc366 bellard
    } else {
95 fdabc366 bellard
        xer_so = 1;
96 fdabc366 bellard
        xer_ov = 1;
97 fdabc366 bellard
    }
98 fdabc366 bellard
}
99 fdabc366 bellard
100 fdabc366 bellard
void do_adde (void)
101 fdabc366 bellard
{
102 fdabc366 bellard
    T2 = T0;
103 fdabc366 bellard
    T0 += T1 + xer_ca;
104 fdabc366 bellard
    if (likely(!(T0 < T2 || (xer_ca == 1 && T0 == T2)))) {
105 fdabc366 bellard
        xer_ca = 0;
106 fdabc366 bellard
    } else {
107 fdabc366 bellard
        xer_ca = 1;
108 fdabc366 bellard
    }
109 fdabc366 bellard
}
110 fdabc366 bellard
111 fdabc366 bellard
void do_addeo (void)
112 fdabc366 bellard
{
113 fdabc366 bellard
    T2 = T0;
114 fdabc366 bellard
    T0 += T1 + xer_ca;
115 fdabc366 bellard
    if (likely(!(T0 < T2 || (xer_ca == 1 && T0 == T2)))) {
116 fdabc366 bellard
        xer_ca = 0;
117 fdabc366 bellard
    } else {
118 fdabc366 bellard
        xer_ca = 1;
119 fdabc366 bellard
    }
120 fdabc366 bellard
    if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
121 fdabc366 bellard
        xer_ov = 0;
122 fdabc366 bellard
    } else {
123 fdabc366 bellard
        xer_so = 1;
124 fdabc366 bellard
        xer_ov = 1;
125 fdabc366 bellard
    }
126 fdabc366 bellard
}
127 fdabc366 bellard
128 fdabc366 bellard
void do_addmeo (void)
129 fdabc366 bellard
{
130 fdabc366 bellard
    T1 = T0;
131 fdabc366 bellard
    T0 += xer_ca + (-1);
132 fdabc366 bellard
    if (likely(!(T1 & (T1 ^ T0) & (1 << 31)))) {
133 fdabc366 bellard
        xer_ov = 0;
134 fdabc366 bellard
    } else {
135 fdabc366 bellard
        xer_so = 1;
136 fdabc366 bellard
        xer_ov = 1;
137 fdabc366 bellard
    }
138 fdabc366 bellard
    if (likely(T1 != 0))
139 fdabc366 bellard
        xer_ca = 1;
140 fdabc366 bellard
}
141 fdabc366 bellard
142 fdabc366 bellard
void do_addzeo (void)
143 fdabc366 bellard
{
144 fdabc366 bellard
    T1 = T0;
145 fdabc366 bellard
    T0 += xer_ca;
146 fdabc366 bellard
    if (likely(!((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)))) {
147 fdabc366 bellard
        xer_ov = 0;
148 fdabc366 bellard
    } else {
149 fdabc366 bellard
        xer_so = 1;
150 fdabc366 bellard
        xer_ov = 1;
151 fdabc366 bellard
    }
152 fdabc366 bellard
    if (likely(T0 >= T1)) {
153 fdabc366 bellard
        xer_ca = 0;
154 fdabc366 bellard
    } else {
155 fdabc366 bellard
        xer_ca = 1;
156 fdabc366 bellard
    }
157 fdabc366 bellard
}
158 fdabc366 bellard
159 fdabc366 bellard
void do_divwo (void)
160 fdabc366 bellard
{
161 fdabc366 bellard
    if (likely(!((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0))) {
162 fdabc366 bellard
        xer_ov = 0;
163 fdabc366 bellard
        T0 = (Ts0 / Ts1);
164 fdabc366 bellard
    } else {
165 fdabc366 bellard
        xer_so = 1;
166 fdabc366 bellard
        xer_ov = 1;
167 fdabc366 bellard
        T0 = (-1) * ((uint32_t)T0 >> 31);
168 fdabc366 bellard
    }
169 fdabc366 bellard
}
170 fdabc366 bellard
171 fdabc366 bellard
void do_divwuo (void)
172 fdabc366 bellard
{
173 fdabc366 bellard
    if (likely((uint32_t)T1 != 0)) {
174 fdabc366 bellard
        xer_ov = 0;
175 fdabc366 bellard
        T0 = (uint32_t)T0 / (uint32_t)T1;
176 fdabc366 bellard
    } else {
177 fdabc366 bellard
        xer_so = 1;
178 fdabc366 bellard
        xer_ov = 1;
179 fdabc366 bellard
        T0 = 0;
180 fdabc366 bellard
    }
181 fdabc366 bellard
}
182 fdabc366 bellard
183 fdabc366 bellard
void do_mullwo (void)
184 fdabc366 bellard
{
185 fdabc366 bellard
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
186 fdabc366 bellard
187 fdabc366 bellard
    if (likely((int32_t)res == res)) {
188 fdabc366 bellard
        xer_ov = 0;
189 fdabc366 bellard
    } else {
190 fdabc366 bellard
        xer_ov = 1;
191 fdabc366 bellard
        xer_so = 1;
192 fdabc366 bellard
    }
193 fdabc366 bellard
    T0 = (int32_t)res;
194 fdabc366 bellard
}
195 fdabc366 bellard
196 fdabc366 bellard
void do_nego (void)
197 fdabc366 bellard
{
198 fdabc366 bellard
    if (likely(T0 != INT32_MIN)) {
199 fdabc366 bellard
        xer_ov = 0;
200 fdabc366 bellard
        T0 = -Ts0;
201 fdabc366 bellard
    } else {
202 fdabc366 bellard
        xer_ov = 1;
203 fdabc366 bellard
        xer_so = 1;
204 fdabc366 bellard
    }
205 fdabc366 bellard
}
206 fdabc366 bellard
207 fdabc366 bellard
void do_subfo (void)
208 fdabc366 bellard
{
209 fdabc366 bellard
    T2 = T0;
210 fdabc366 bellard
    T0 = T1 - T0;
211 fdabc366 bellard
    if (likely(!(((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)))) {
212 fdabc366 bellard
        xer_ov = 0;
213 fdabc366 bellard
    } else {
214 fdabc366 bellard
        xer_so = 1;
215 fdabc366 bellard
        xer_ov = 1;
216 fdabc366 bellard
    }
217 fdabc366 bellard
    RETURN();
218 fdabc366 bellard
}
219 fdabc366 bellard
220 fdabc366 bellard
void do_subfco (void)
221 fdabc366 bellard
{
222 fdabc366 bellard
    T2 = T0;
223 fdabc366 bellard
    T0 = T1 - T0;
224 fdabc366 bellard
    if (likely(T0 > T1)) {
225 fdabc366 bellard
        xer_ca = 0;
226 fdabc366 bellard
    } else {
227 fdabc366 bellard
        xer_ca = 1;
228 fdabc366 bellard
    }
229 fdabc366 bellard
    if (likely(!(((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)))) {
230 fdabc366 bellard
        xer_ov = 0;
231 fdabc366 bellard
    } else {
232 fdabc366 bellard
        xer_so = 1;
233 fdabc366 bellard
        xer_ov = 1;
234 fdabc366 bellard
    }
235 fdabc366 bellard
}
236 fdabc366 bellard
237 fdabc366 bellard
void do_subfe (void)
238 fdabc366 bellard
{
239 fdabc366 bellard
    T0 = T1 + ~T0 + xer_ca;
240 fdabc366 bellard
    if (likely(T0 >= T1 && (xer_ca == 0 || T0 != T1))) {
241 fdabc366 bellard
        xer_ca = 0;
242 fdabc366 bellard
    } else {
243 fdabc366 bellard
        xer_ca = 1;
244 fdabc366 bellard
    }
245 fdabc366 bellard
}
246 fdabc366 bellard
247 fdabc366 bellard
void do_subfeo (void)
248 fdabc366 bellard
{
249 fdabc366 bellard
    T2 = T0;
250 fdabc366 bellard
    T0 = T1 + ~T0 + xer_ca;
251 fdabc366 bellard
    if (likely(!((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)))) {
252 fdabc366 bellard
        xer_ov = 0;
253 fdabc366 bellard
    } else {
254 fdabc366 bellard
        xer_so = 1;
255 fdabc366 bellard
        xer_ov = 1;
256 fdabc366 bellard
    }
257 fdabc366 bellard
    if (likely(T0 >= T1 && (xer_ca == 0 || T0 != T1))) {
258 fdabc366 bellard
        xer_ca = 0;
259 fdabc366 bellard
    } else {
260 fdabc366 bellard
        xer_ca = 1;
261 fdabc366 bellard
    }
262 fdabc366 bellard
}
263 fdabc366 bellard
264 fdabc366 bellard
void do_subfmeo (void)
265 fdabc366 bellard
{
266 fdabc366 bellard
    T1 = T0;
267 fdabc366 bellard
    T0 = ~T0 + xer_ca - 1;
268 fdabc366 bellard
    if (likely(!(~T1 & (~T1 ^ T0) & (1 << 31)))) {
269 fdabc366 bellard
        xer_ov = 0;
270 fdabc366 bellard
    } else {
271 fdabc366 bellard
        xer_so = 1;
272 fdabc366 bellard
        xer_ov = 1;
273 fdabc366 bellard
    }
274 fdabc366 bellard
    if (likely(T1 != -1))
275 fdabc366 bellard
        xer_ca = 1;
276 fdabc366 bellard
}
277 fdabc366 bellard
278 fdabc366 bellard
void do_subfzeo (void)
279 fdabc366 bellard
{
280 fdabc366 bellard
    T1 = T0;
281 fdabc366 bellard
    T0 = ~T0 + xer_ca;
282 fdabc366 bellard
    if (likely(!((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)))) {
283 fdabc366 bellard
        xer_ov = 0;
284 fdabc366 bellard
    } else {
285 fdabc366 bellard
        xer_ov = 1;
286 fdabc366 bellard
        xer_so = 1;
287 fdabc366 bellard
    }
288 fdabc366 bellard
    if (likely(T0 >= ~T1)) {
289 fdabc366 bellard
        xer_ca = 0;
290 fdabc366 bellard
    } else {
291 fdabc366 bellard
        xer_ca = 1;
292 fdabc366 bellard
    }
293 fdabc366 bellard
}
294 fdabc366 bellard
295 9a64fbe4 bellard
/* shift right arithmetic helper */
296 9a64fbe4 bellard
void do_sraw (void)
297 9a64fbe4 bellard
{
298 9a64fbe4 bellard
    int32_t ret;
299 9a64fbe4 bellard
300 fdabc366 bellard
    if (likely(!(T1 & 0x20UL))) {
301 fdabc366 bellard
        if (likely(T1 != 0)) {
302 fdabc366 bellard
            ret = (int32_t)T0 >> (T1 & 0x1fUL);
303 fdabc366 bellard
            if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
304 9a64fbe4 bellard
    xer_ca = 0;
305 fdabc366 bellard
            } else {
306 9a64fbe4 bellard
            xer_ca = 1;
307 fdabc366 bellard
            }
308 fdabc366 bellard
        } else {
309 4b3686fa bellard
        ret = T0;
310 fdabc366 bellard
            xer_ca = 0;
311 fdabc366 bellard
        }
312 fdabc366 bellard
    } else {
313 fdabc366 bellard
        ret = (-1) * ((uint32_t)T0 >> 31);
314 fdabc366 bellard
        if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
315 fdabc366 bellard
            xer_ca = 0;
316 9a64fbe4 bellard
    } else {
317 9a64fbe4 bellard
            xer_ca = 1;
318 9a64fbe4 bellard
    }
319 fdabc366 bellard
    }
320 4b3686fa bellard
    T0 = ret;
321 9a64fbe4 bellard
}
322 9a64fbe4 bellard
323 fdabc366 bellard
/*****************************************************************************/
324 9a64fbe4 bellard
/* Floating point operations helpers */
325 9a64fbe4 bellard
void do_fctiw (void)
326 9a64fbe4 bellard
{
327 9a64fbe4 bellard
    union {
328 9a64fbe4 bellard
        double d;
329 9a64fbe4 bellard
        uint64_t i;
330 4ecc3190 bellard
    } p;
331 9a64fbe4 bellard
332 4ecc3190 bellard
    /* XXX: higher bits are not supposed to be significant.
333 3fc6c082 bellard
     *      to make tests easier, return the same as a real PowerPC 750 (aka G3)
334 4ecc3190 bellard
     */
335 4ecc3190 bellard
    p.i = float64_to_int32(FT0, &env->fp_status);
336 4ecc3190 bellard
    p.i |= 0xFFF80000ULL << 32;
337 4ecc3190 bellard
    FT0 = p.d;
338 9a64fbe4 bellard
}
339 9a64fbe4 bellard
340 9a64fbe4 bellard
void do_fctiwz (void)
341 9a64fbe4 bellard
{
342 9a64fbe4 bellard
    union {
343 9a64fbe4 bellard
        double d;
344 9a64fbe4 bellard
        uint64_t i;
345 4ecc3190 bellard
    } p;
346 4ecc3190 bellard
347 4ecc3190 bellard
    /* XXX: higher bits are not supposed to be significant.
348 3fc6c082 bellard
     *      to make tests easier, return the same as a real PowerPC 750 (aka G3)
349 4ecc3190 bellard
     */
350 4ecc3190 bellard
    p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
351 4ecc3190 bellard
    p.i |= 0xFFF80000ULL << 32;
352 4ecc3190 bellard
    FT0 = p.d;
353 9a64fbe4 bellard
}
354 9a64fbe4 bellard
355 4b3686fa bellard
void do_fnmadd (void)
356 4b3686fa bellard
{
357 fdabc366 bellard
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
358 fdabc366 bellard
    FT0 = float64_add(FT0, FT2, &env->fp_status);
359 fdabc366 bellard
    if (likely(!isnan(FT0)))
360 fdabc366 bellard
        FT0 = float64_chs(FT0);
361 4b3686fa bellard
}
362 4b3686fa bellard
363 4b3686fa bellard
void do_fnmsub (void)
364 4b3686fa bellard
{
365 fdabc366 bellard
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
366 fdabc366 bellard
    FT0 = float64_sub(FT0, FT2, &env->fp_status);
367 fdabc366 bellard
    if (likely(!isnan(FT0)))
368 fdabc366 bellard
        FT0 = float64_chs(FT0);
369 1ef59d0a bellard
}
370 1ef59d0a bellard
371 9a64fbe4 bellard
void do_fsqrt (void)
372 9a64fbe4 bellard
{
373 fdabc366 bellard
    FT0 = float64_sqrt(FT0, &env->fp_status);
374 9a64fbe4 bellard
}
375 9a64fbe4 bellard
376 9a64fbe4 bellard
void do_fres (void)
377 9a64fbe4 bellard
{
378 4ecc3190 bellard
    union {
379 4ecc3190 bellard
        double d;
380 4ecc3190 bellard
        uint64_t i;
381 4ecc3190 bellard
    } p;
382 4ecc3190 bellard
383 fdabc366 bellard
    if (likely(isnormal(FT0))) {
384 4ecc3190 bellard
        FT0 = (float)(1.0 / FT0);
385 4ecc3190 bellard
    } else {
386 4ecc3190 bellard
        p.d = FT0;
387 4ecc3190 bellard
        if (p.i == 0x8000000000000000ULL) {
388 4ecc3190 bellard
            p.i = 0xFFF0000000000000ULL;
389 4ecc3190 bellard
        } else if (p.i == 0x0000000000000000ULL) {
390 4ecc3190 bellard
            p.i = 0x7FF0000000000000ULL;
391 4ecc3190 bellard
        } else if (isnan(FT0)) {
392 4ecc3190 bellard
            p.i = 0x7FF8000000000000ULL;
393 4ecc3190 bellard
        } else if (FT0 < 0.0) {
394 4ecc3190 bellard
            p.i = 0x8000000000000000ULL;
395 4ecc3190 bellard
        } else {
396 4ecc3190 bellard
            p.i = 0x0000000000000000ULL;
397 4ecc3190 bellard
        }
398 4ecc3190 bellard
        FT0 = p.d;
399 4ecc3190 bellard
    }
400 9a64fbe4 bellard
}
401 9a64fbe4 bellard
402 4ecc3190 bellard
void do_frsqrte (void)
403 9a64fbe4 bellard
{
404 4ecc3190 bellard
    union {
405 4ecc3190 bellard
        double d;
406 4ecc3190 bellard
        uint64_t i;
407 4ecc3190 bellard
    } p;
408 4ecc3190 bellard
409 fdabc366 bellard
    if (likely(isnormal(FT0) && FT0 > 0.0)) {
410 fdabc366 bellard
        FT0 = float64_sqrt(FT0, &env->fp_status);
411 fdabc366 bellard
        FT0 = float32_div(1.0, FT0, &env->fp_status);
412 4ecc3190 bellard
    } else {
413 4ecc3190 bellard
        p.d = FT0;
414 4ecc3190 bellard
        if (p.i == 0x8000000000000000ULL) {
415 4ecc3190 bellard
            p.i = 0xFFF0000000000000ULL;
416 4ecc3190 bellard
        } else if (p.i == 0x0000000000000000ULL) {
417 4ecc3190 bellard
            p.i = 0x7FF0000000000000ULL;
418 4ecc3190 bellard
        } else if (isnan(FT0)) {
419 4ecc3190 bellard
            if (!(p.i & 0x0008000000000000ULL))
420 4ecc3190 bellard
                p.i |= 0x000FFFFFFFFFFFFFULL;
421 4ecc3190 bellard
        } else if (FT0 < 0) {
422 4ecc3190 bellard
            p.i = 0x7FF8000000000000ULL;
423 4ecc3190 bellard
        } else {
424 4ecc3190 bellard
            p.i = 0x0000000000000000ULL;
425 4ecc3190 bellard
        }
426 4ecc3190 bellard
        FT0 = p.d;
427 4ecc3190 bellard
    }
428 9a64fbe4 bellard
}
429 9a64fbe4 bellard
430 9a64fbe4 bellard
void do_fsel (void)
431 9a64fbe4 bellard
{
432 9a64fbe4 bellard
    if (FT0 >= 0)
433 9a64fbe4 bellard
        FT0 = FT1;
434 4ecc3190 bellard
    else
435 4ecc3190 bellard
        FT0 = FT2;
436 9a64fbe4 bellard
}
437 9a64fbe4 bellard
438 9a64fbe4 bellard
void do_fcmpu (void)
439 9a64fbe4 bellard
{
440 fdabc366 bellard
    if (likely(!isnan(FT0) && !isnan(FT1))) {
441 fdabc366 bellard
        if (float64_lt(FT0, FT1, &env->fp_status)) {
442 fdabc366 bellard
            T0 = 0x08UL;
443 fdabc366 bellard
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
444 fdabc366 bellard
            T0 = 0x04UL;
445 fdabc366 bellard
        } else {
446 fdabc366 bellard
            T0 = 0x02UL;
447 fdabc366 bellard
        }
448 fdabc366 bellard
    } else {
449 fdabc366 bellard
        T0 = 0x01UL;
450 9a64fbe4 bellard
        env->fpscr[4] |= 0x1;
451 9a64fbe4 bellard
        env->fpscr[6] |= 0x1;
452 9a64fbe4 bellard
    }
453 4b3686fa bellard
    env->fpscr[3] = T0;
454 9a64fbe4 bellard
}
455 9a64fbe4 bellard
456 9a64fbe4 bellard
void do_fcmpo (void)
457 9a64fbe4 bellard
{
458 9a64fbe4 bellard
    env->fpscr[4] &= ~0x1;
459 fdabc366 bellard
    if (likely(!isnan(FT0) && !isnan(FT1))) {
460 fdabc366 bellard
        if (float64_lt(FT0, FT1, &env->fp_status)) {
461 fdabc366 bellard
            T0 = 0x08UL;
462 fdabc366 bellard
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
463 fdabc366 bellard
            T0 = 0x04UL;
464 fdabc366 bellard
        } else {
465 fdabc366 bellard
            T0 = 0x02UL;
466 fdabc366 bellard
        }
467 fdabc366 bellard
    } else {
468 fdabc366 bellard
        T0 = 0x01UL;
469 9a64fbe4 bellard
        env->fpscr[4] |= 0x1;
470 9a64fbe4 bellard
        /* I don't know how to test "quiet" nan... */
471 9a64fbe4 bellard
        if (0 /* || ! quiet_nan(...) */) {
472 9a64fbe4 bellard
            env->fpscr[6] |= 0x1;
473 9a64fbe4 bellard
            if (!(env->fpscr[1] & 0x8))
474 9a64fbe4 bellard
                env->fpscr[4] |= 0x8;
475 9a64fbe4 bellard
        } else {
476 9a64fbe4 bellard
            env->fpscr[4] |= 0x8;
477 9a64fbe4 bellard
        }
478 9a64fbe4 bellard
    }
479 4b3686fa bellard
    env->fpscr[3] = T0;
480 9a64fbe4 bellard
}
481 9a64fbe4 bellard
482 fdabc366 bellard
void do_rfi (void)
483 9a64fbe4 bellard
{
484 fdabc366 bellard
    env->nip = env->spr[SPR_SRR0] & ~0x00000003;
485 fdabc366 bellard
    T0 = env->spr[SPR_SRR1] & ~0xFFFF0000UL;
486 fdabc366 bellard
    do_store_msr(env, T0);
487 fdabc366 bellard
#if defined (DEBUG_OP)
488 fdabc366 bellard
    dump_rfi();
489 fdabc366 bellard
#endif
490 fdabc366 bellard
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
491 9a64fbe4 bellard
}
492 9a64fbe4 bellard
493 fdabc366 bellard
void do_tw (uint32_t cmp, int flags)
494 9a64fbe4 bellard
{
495 fdabc366 bellard
    if (!likely(!((Ts0 < (int32_t)cmp && (flags & 0x10)) ||
496 fdabc366 bellard
                  (Ts0 > (int32_t)cmp && (flags & 0x08)) ||
497 fdabc366 bellard
                  (Ts0 == (int32_t)cmp && (flags & 0x04)) ||
498 fdabc366 bellard
                  (T0 < cmp && (flags & 0x02)) ||
499 fdabc366 bellard
                  (T0 > cmp && (flags & 0x01)))))
500 fdabc366 bellard
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
501 9a64fbe4 bellard
}
502 9a64fbe4 bellard
503 9a64fbe4 bellard
/* Instruction cache invalidation helper */
504 9a64fbe4 bellard
void do_icbi (void)
505 9a64fbe4 bellard
{
506 fdabc366 bellard
    uint32_t tmp;
507 fdabc366 bellard
    /* Invalidate one cache line :
508 fdabc366 bellard
     * PowerPC specification says this is to be treated like a load
509 fdabc366 bellard
     * (not a fetch) by the MMU. To be sure it will be so,
510 fdabc366 bellard
     * do the load "by hand".
511 fdabc366 bellard
     */
512 fdabc366 bellard
#if defined(TARGET_PPC64)
513 fdabc366 bellard
    if (!msr_sf)
514 fdabc366 bellard
        T0 &= 0xFFFFFFFFULL;
515 fdabc366 bellard
#endif
516 fdabc366 bellard
    tmp = ldl_kernel(T0);
517 985a19d6 bellard
    T0 &= ~(ICACHE_LINE_SIZE - 1);
518 985a19d6 bellard
    tb_invalidate_page_range(T0, T0 + ICACHE_LINE_SIZE);
519 9a64fbe4 bellard
}
520 9a64fbe4 bellard
521 fdabc366 bellard
/*****************************************************************************/
522 fdabc366 bellard
/* MMU related helpers */
523 9a64fbe4 bellard
/* TLB invalidation helpers */
524 9a64fbe4 bellard
void do_tlbia (void)
525 9a64fbe4 bellard
{
526 ad081323 bellard
    tlb_flush(env, 1);
527 9a64fbe4 bellard
}
528 9a64fbe4 bellard
529 9a64fbe4 bellard
void do_tlbie (void)
530 9a64fbe4 bellard
{
531 fdabc366 bellard
#if !defined(FLUSH_ALL_TLBS)
532 9a64fbe4 bellard
    tlb_flush_page(env, T0);
533 fdabc366 bellard
#else
534 fdabc366 bellard
    do_tlbia();
535 fdabc366 bellard
#endif
536 fdabc366 bellard
}
537 fdabc366 bellard
538 fdabc366 bellard
/*****************************************************************************/
539 fdabc366 bellard
/* Softmmu support */
540 fdabc366 bellard
#if !defined (CONFIG_USER_ONLY)
541 fdabc366 bellard
542 fdabc366 bellard
#define MMUSUFFIX _mmu
543 fdabc366 bellard
#define GETPC() (__builtin_return_address(0))
544 fdabc366 bellard
545 fdabc366 bellard
#define SHIFT 0
546 fdabc366 bellard
#include "softmmu_template.h"
547 fdabc366 bellard
548 fdabc366 bellard
#define SHIFT 1
549 fdabc366 bellard
#include "softmmu_template.h"
550 fdabc366 bellard
551 fdabc366 bellard
#define SHIFT 2
552 fdabc366 bellard
#include "softmmu_template.h"
553 fdabc366 bellard
554 fdabc366 bellard
#define SHIFT 3
555 fdabc366 bellard
#include "softmmu_template.h"
556 fdabc366 bellard
557 fdabc366 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
558 fdabc366 bellard
   NULL, it means that the function was called in C code (i.e. not
559 fdabc366 bellard
   from generated code or from helper.c) */
560 fdabc366 bellard
/* XXX: fix it to restore all registers */
561 fdabc366 bellard
void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
562 fdabc366 bellard
{
563 fdabc366 bellard
    TranslationBlock *tb;
564 fdabc366 bellard
    CPUState *saved_env;
565 fdabc366 bellard
    target_phys_addr_t pc;
566 fdabc366 bellard
    int ret;
567 fdabc366 bellard
568 fdabc366 bellard
    /* XXX: hack to restore env in all cases, even if not called from
569 fdabc366 bellard
       generated code */
570 fdabc366 bellard
    saved_env = env;
571 fdabc366 bellard
    env = cpu_single_env;
572 fdabc366 bellard
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1);
573 fdabc366 bellard
    if (!likely(ret == 0)) {
574 fdabc366 bellard
        if (likely(retaddr)) {
575 fdabc366 bellard
            /* now we have a real cpu fault */
576 fdabc366 bellard
            pc = (target_phys_addr_t)retaddr;
577 fdabc366 bellard
            tb = tb_find_pc(pc);
578 fdabc366 bellard
            if (likely(tb)) {
579 fdabc366 bellard
                /* the PC is inside the translated code. It means that we have
580 fdabc366 bellard
                   a virtual CPU fault */
581 fdabc366 bellard
                cpu_restore_state(tb, env, pc, NULL);
582 fdabc366 bellard
}
583 fdabc366 bellard
        }
584 fdabc366 bellard
        do_raise_exception_err(env->exception_index, env->error_code);
585 fdabc366 bellard
    }
586 fdabc366 bellard
    env = saved_env;
587 9a64fbe4 bellard
}
588 fdabc366 bellard
#endif /* !CONFIG_USER_ONLY */