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