]> git.proxmox.com Git - qemu.git/blob - target-ppc/op_helper.c
Generate micro-ops for PowerPC hypervisor mode.
[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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include "exec.h"
21
22 #include "op_helper.h"
23
24 #define MEMSUFFIX _raw
25 #include "op_helper.h"
26 #include "op_helper_mem.h"
27 #if !defined(CONFIG_USER_ONLY)
28 #define MEMSUFFIX _user
29 #include "op_helper.h"
30 #include "op_helper_mem.h"
31 #define MEMSUFFIX _kernel
32 #include "op_helper.h"
33 #include "op_helper_mem.h"
34 #if defined(TARGET_PPC64H)
35 #define MEMSUFFIX _hypv
36 #include "op_helper.h"
37 #include "op_helper_mem.h"
38 #endif
39 #endif
40
41 //#define DEBUG_OP
42 //#define DEBUG_EXCEPTIONS
43 //#define DEBUG_SOFTWARE_TLB
44
45 /*****************************************************************************/
46 /* Exceptions processing helpers */
47
48 void do_raise_exception_err (uint32_t exception, int error_code)
49 {
50 #if 0
51 printf("Raise exception %3x code : %d\n", exception, error_code);
52 #endif
53 switch (exception) {
54 case POWERPC_EXCP_PROGRAM:
55 if (error_code == POWERPC_EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
56 return;
57 break;
58 default:
59 break;
60 }
61 env->exception_index = exception;
62 env->error_code = error_code;
63 cpu_loop_exit();
64 }
65
66 void do_raise_exception (uint32_t exception)
67 {
68 do_raise_exception_err(exception, 0);
69 }
70
71 void cpu_dump_EA (target_ulong EA);
72 void do_print_mem_EA (target_ulong EA)
73 {
74 cpu_dump_EA(EA);
75 }
76
77 /*****************************************************************************/
78 /* Registers load and stores */
79 void do_load_cr (void)
80 {
81 T0 = (env->crf[0] << 28) |
82 (env->crf[1] << 24) |
83 (env->crf[2] << 20) |
84 (env->crf[3] << 16) |
85 (env->crf[4] << 12) |
86 (env->crf[5] << 8) |
87 (env->crf[6] << 4) |
88 (env->crf[7] << 0);
89 }
90
91 void do_store_cr (uint32_t mask)
92 {
93 int i, sh;
94
95 for (i = 0, sh = 7; i < 8; i++, sh--) {
96 if (mask & (1 << sh))
97 env->crf[i] = (T0 >> (sh * 4)) & 0xFUL;
98 }
99 }
100
101 void do_load_xer (void)
102 {
103 T0 = (xer_so << XER_SO) |
104 (xer_ov << XER_OV) |
105 (xer_ca << XER_CA) |
106 (xer_bc << XER_BC) |
107 (xer_cmp << XER_CMP);
108 }
109
110 void do_store_xer (void)
111 {
112 xer_so = (T0 >> XER_SO) & 0x01;
113 xer_ov = (T0 >> XER_OV) & 0x01;
114 xer_ca = (T0 >> XER_CA) & 0x01;
115 xer_cmp = (T0 >> XER_CMP) & 0xFF;
116 xer_bc = (T0 >> XER_BC) & 0x7F;
117 }
118
119 #if defined(TARGET_PPC64)
120 void do_store_pri (int prio)
121 {
122 env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
123 env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
124 }
125 #endif
126
127 void do_load_fpscr (void)
128 {
129 /* The 32 MSB of the target fpr are undefined.
130 * They'll be zero...
131 */
132 union {
133 float64 d;
134 struct {
135 uint32_t u[2];
136 } s;
137 } u;
138 int i;
139
140 #if defined(WORDS_BIGENDIAN)
141 #define WORD0 0
142 #define WORD1 1
143 #else
144 #define WORD0 1
145 #define WORD1 0
146 #endif
147 u.s.u[WORD0] = 0;
148 u.s.u[WORD1] = 0;
149 for (i = 0; i < 8; i++)
150 u.s.u[WORD1] |= env->fpscr[i] << (4 * i);
151 FT0 = u.d;
152 }
153
154 void do_store_fpscr (uint32_t mask)
155 {
156 /*
157 * We use only the 32 LSB of the incoming fpr
158 */
159 union {
160 double d;
161 struct {
162 uint32_t u[2];
163 } s;
164 } u;
165 int i, rnd_type;
166
167 u.d = FT0;
168 if (mask & 0x80)
169 env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[WORD1] >> 28) & ~0x9);
170 for (i = 1; i < 7; i++) {
171 if (mask & (1 << (7 - i)))
172 env->fpscr[i] = (u.s.u[WORD1] >> (4 * (7 - i))) & 0xF;
173 }
174 /* TODO: update FEX & VX */
175 /* Set rounding mode */
176 switch (env->fpscr[0] & 0x3) {
177 case 0:
178 /* Best approximation (round to nearest) */
179 rnd_type = float_round_nearest_even;
180 break;
181 case 1:
182 /* Smaller magnitude (round toward zero) */
183 rnd_type = float_round_to_zero;
184 break;
185 case 2:
186 /* Round toward +infinite */
187 rnd_type = float_round_up;
188 break;
189 default:
190 case 3:
191 /* Round toward -infinite */
192 rnd_type = float_round_down;
193 break;
194 }
195 set_float_rounding_mode(rnd_type, &env->fp_status);
196 }
197
198 target_ulong ppc_load_dump_spr (int sprn)
199 {
200 if (loglevel != 0) {
201 fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
202 sprn, sprn, env->spr[sprn]);
203 }
204
205 return env->spr[sprn];
206 }
207
208 void ppc_store_dump_spr (int sprn, target_ulong val)
209 {
210 if (loglevel != 0) {
211 fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n",
212 sprn, sprn, env->spr[sprn], val);
213 }
214 env->spr[sprn] = val;
215 }
216
217 /*****************************************************************************/
218 /* Fixed point operations helpers */
219 #if defined(TARGET_PPC64)
220 static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
221 {
222 *plow += a;
223 /* carry test */
224 if (*plow < a)
225 (*phigh)++;
226 *phigh += b;
227 }
228
229 static void neg128 (uint64_t *plow, uint64_t *phigh)
230 {
231 *plow = ~*plow;
232 *phigh = ~*phigh;
233 add128(plow, phigh, 1, 0);
234 }
235
236 static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
237 {
238 uint32_t a0, a1, b0, b1;
239 uint64_t v;
240
241 a0 = a;
242 a1 = a >> 32;
243
244 b0 = b;
245 b1 = b >> 32;
246
247 v = (uint64_t)a0 * (uint64_t)b0;
248 *plow = v;
249 *phigh = 0;
250
251 v = (uint64_t)a0 * (uint64_t)b1;
252 add128(plow, phigh, v << 32, v >> 32);
253
254 v = (uint64_t)a1 * (uint64_t)b0;
255 add128(plow, phigh, v << 32, v >> 32);
256
257 v = (uint64_t)a1 * (uint64_t)b1;
258 *phigh += v;
259 #if defined(DEBUG_MULDIV)
260 printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
261 a, b, *phigh, *plow);
262 #endif
263 }
264
265 void do_mul64 (uint64_t *plow, uint64_t *phigh)
266 {
267 mul64(plow, phigh, T0, T1);
268 }
269
270 static void imul64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
271 {
272 int sa, sb;
273
274 sa = (a < 0);
275 if (sa)
276 a = -a;
277 sb = (b < 0);
278 if (sb)
279 b = -b;
280 mul64(plow, phigh, a, b);
281 if (sa ^ sb) {
282 neg128(plow, phigh);
283 }
284 }
285
286 void do_imul64 (uint64_t *plow, uint64_t *phigh)
287 {
288 imul64(plow, phigh, T0, T1);
289 }
290 #endif
291
292 void do_adde (void)
293 {
294 T2 = T0;
295 T0 += T1 + xer_ca;
296 if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
297 (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
298 xer_ca = 0;
299 } else {
300 xer_ca = 1;
301 }
302 }
303
304 #if defined(TARGET_PPC64)
305 void do_adde_64 (void)
306 {
307 T2 = T0;
308 T0 += T1 + xer_ca;
309 if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
310 (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
311 xer_ca = 0;
312 } else {
313 xer_ca = 1;
314 }
315 }
316 #endif
317
318 void do_addmeo (void)
319 {
320 T1 = T0;
321 T0 += xer_ca + (-1);
322 if (likely(!((uint32_t)T1 &
323 ((uint32_t)T1 ^ (uint32_t)T0) & (1UL << 31)))) {
324 xer_ov = 0;
325 } else {
326 xer_ov = 1;
327 xer_so = 1;
328 }
329 if (likely(T1 != 0))
330 xer_ca = 1;
331 }
332
333 #if defined(TARGET_PPC64)
334 void do_addmeo_64 (void)
335 {
336 T1 = T0;
337 T0 += xer_ca + (-1);
338 if (likely(!((uint64_t)T1 &
339 ((uint64_t)T1 ^ (uint64_t)T0) & (1ULL << 63)))) {
340 xer_ov = 0;
341 } else {
342 xer_ov = 1;
343 xer_so = 1;
344 }
345 if (likely(T1 != 0))
346 xer_ca = 1;
347 }
348 #endif
349
350 void do_divwo (void)
351 {
352 if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) ||
353 (int32_t)T1 == 0))) {
354 xer_ov = 0;
355 T0 = (int32_t)T0 / (int32_t)T1;
356 } else {
357 xer_ov = 1;
358 xer_so = 1;
359 T0 = (-1) * ((uint32_t)T0 >> 31);
360 }
361 }
362
363 #if defined(TARGET_PPC64)
364 void do_divdo (void)
365 {
366 if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == -1ULL) ||
367 (int64_t)T1 == 0))) {
368 xer_ov = 0;
369 T0 = (int64_t)T0 / (int64_t)T1;
370 } else {
371 xer_ov = 1;
372 xer_so = 1;
373 T0 = (-1ULL) * ((uint64_t)T0 >> 63);
374 }
375 }
376 #endif
377
378 void do_divwuo (void)
379 {
380 if (likely((uint32_t)T1 != 0)) {
381 xer_ov = 0;
382 T0 = (uint32_t)T0 / (uint32_t)T1;
383 } else {
384 xer_ov = 1;
385 xer_so = 1;
386 T0 = 0;
387 }
388 }
389
390 #if defined(TARGET_PPC64)
391 void do_divduo (void)
392 {
393 if (likely((uint64_t)T1 != 0)) {
394 xer_ov = 0;
395 T0 = (uint64_t)T0 / (uint64_t)T1;
396 } else {
397 xer_ov = 1;
398 xer_so = 1;
399 T0 = 0;
400 }
401 }
402 #endif
403
404 void do_mullwo (void)
405 {
406 int64_t res = (int64_t)T0 * (int64_t)T1;
407
408 if (likely((int32_t)res == res)) {
409 xer_ov = 0;
410 } else {
411 xer_ov = 1;
412 xer_so = 1;
413 }
414 T0 = (int32_t)res;
415 }
416
417 #if defined(TARGET_PPC64)
418 void do_mulldo (void)
419 {
420 int64_t th;
421 uint64_t tl;
422
423 do_imul64(&tl, &th);
424 if (likely(th == 0)) {
425 xer_ov = 0;
426 } else {
427 xer_ov = 1;
428 xer_so = 1;
429 }
430 T0 = (int64_t)tl;
431 }
432 #endif
433
434 void do_nego (void)
435 {
436 if (likely((int32_t)T0 != INT32_MIN)) {
437 xer_ov = 0;
438 T0 = -(int32_t)T0;
439 } else {
440 xer_ov = 1;
441 xer_so = 1;
442 }
443 }
444
445 #if defined(TARGET_PPC64)
446 void do_nego_64 (void)
447 {
448 if (likely((int64_t)T0 != INT64_MIN)) {
449 xer_ov = 0;
450 T0 = -(int64_t)T0;
451 } else {
452 xer_ov = 1;
453 xer_so = 1;
454 }
455 }
456 #endif
457
458 void do_subfe (void)
459 {
460 T0 = T1 + ~T0 + xer_ca;
461 if (likely((uint32_t)T0 >= (uint32_t)T1 &&
462 (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
463 xer_ca = 0;
464 } else {
465 xer_ca = 1;
466 }
467 }
468
469 #if defined(TARGET_PPC64)
470 void do_subfe_64 (void)
471 {
472 T0 = T1 + ~T0 + xer_ca;
473 if (likely((uint64_t)T0 >= (uint64_t)T1 &&
474 (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
475 xer_ca = 0;
476 } else {
477 xer_ca = 1;
478 }
479 }
480 #endif
481
482 void do_subfmeo (void)
483 {
484 T1 = T0;
485 T0 = ~T0 + xer_ca - 1;
486 if (likely(!((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0) &
487 (1UL << 31)))) {
488 xer_ov = 0;
489 } else {
490 xer_ov = 1;
491 xer_so = 1;
492 }
493 if (likely((uint32_t)T1 != UINT32_MAX))
494 xer_ca = 1;
495 }
496
497 #if defined(TARGET_PPC64)
498 void do_subfmeo_64 (void)
499 {
500 T1 = T0;
501 T0 = ~T0 + xer_ca - 1;
502 if (likely(!((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0) &
503 (1ULL << 63)))) {
504 xer_ov = 0;
505 } else {
506 xer_ov = 1;
507 xer_so = 1;
508 }
509 if (likely((uint64_t)T1 != UINT64_MAX))
510 xer_ca = 1;
511 }
512 #endif
513
514 void do_subfzeo (void)
515 {
516 T1 = T0;
517 T0 = ~T0 + xer_ca;
518 if (likely(!(((uint32_t)~T1 ^ UINT32_MAX) &
519 ((uint32_t)(~T1) ^ (uint32_t)T0) & (1UL << 31)))) {
520 xer_ov = 0;
521 } else {
522 xer_ov = 1;
523 xer_so = 1;
524 }
525 if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
526 xer_ca = 0;
527 } else {
528 xer_ca = 1;
529 }
530 }
531
532 #if defined(TARGET_PPC64)
533 void do_subfzeo_64 (void)
534 {
535 T1 = T0;
536 T0 = ~T0 + xer_ca;
537 if (likely(!(((uint64_t)~T1 ^ UINT64_MAX) &
538 ((uint64_t)(~T1) ^ (uint64_t)T0) & (1ULL << 63)))) {
539 xer_ov = 0;
540 } else {
541 xer_ov = 1;
542 xer_so = 1;
543 }
544 if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
545 xer_ca = 0;
546 } else {
547 xer_ca = 1;
548 }
549 }
550 #endif
551
552 /* shift right arithmetic helper */
553 void do_sraw (void)
554 {
555 int32_t ret;
556
557 if (likely(!(T1 & 0x20UL))) {
558 if (likely((uint32_t)T1 != 0)) {
559 ret = (int32_t)T0 >> (T1 & 0x1fUL);
560 if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
561 xer_ca = 0;
562 } else {
563 xer_ca = 1;
564 }
565 } else {
566 ret = T0;
567 xer_ca = 0;
568 }
569 } else {
570 ret = (-1) * ((uint32_t)T0 >> 31);
571 if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
572 xer_ca = 0;
573 } else {
574 xer_ca = 1;
575 }
576 }
577 T0 = ret;
578 }
579
580 #if defined(TARGET_PPC64)
581 void do_srad (void)
582 {
583 int64_t ret;
584
585 if (likely(!(T1 & 0x40UL))) {
586 if (likely((uint64_t)T1 != 0)) {
587 ret = (int64_t)T0 >> (T1 & 0x3FUL);
588 if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) {
589 xer_ca = 0;
590 } else {
591 xer_ca = 1;
592 }
593 } else {
594 ret = T0;
595 xer_ca = 0;
596 }
597 } else {
598 ret = (-1) * ((uint64_t)T0 >> 63);
599 if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) {
600 xer_ca = 0;
601 } else {
602 xer_ca = 1;
603 }
604 }
605 T0 = ret;
606 }
607 #endif
608
609 static always_inline int popcnt (uint32_t val)
610 {
611 int i;
612
613 for (i = 0; val != 0;)
614 val = val ^ (val - 1);
615
616 return i;
617 }
618
619 void do_popcntb (void)
620 {
621 uint32_t ret;
622 int i;
623
624 ret = 0;
625 for (i = 0; i < 32; i += 8)
626 ret |= popcnt((T0 >> i) & 0xFF) << i;
627 T0 = ret;
628 }
629
630 #if defined(TARGET_PPC64)
631 void do_popcntb_64 (void)
632 {
633 uint64_t ret;
634 int i;
635
636 ret = 0;
637 for (i = 0; i < 64; i += 8)
638 ret |= popcnt((T0 >> i) & 0xFF) << i;
639 T0 = ret;
640 }
641 #endif
642
643 /*****************************************************************************/
644 /* Floating point operations helpers */
645 void do_fctiw (void)
646 {
647 union {
648 double d;
649 uint64_t i;
650 } p;
651
652 p.i = float64_to_int32(FT0, &env->fp_status);
653 #if USE_PRECISE_EMULATION
654 /* XXX: higher bits are not supposed to be significant.
655 * to make tests easier, return the same as a real PowerPC 750 (aka G3)
656 */
657 p.i |= 0xFFF80000ULL << 32;
658 #endif
659 FT0 = p.d;
660 }
661
662 void do_fctiwz (void)
663 {
664 union {
665 double d;
666 uint64_t i;
667 } p;
668
669 p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
670 #if USE_PRECISE_EMULATION
671 /* XXX: higher bits are not supposed to be significant.
672 * to make tests easier, return the same as a real PowerPC 750 (aka G3)
673 */
674 p.i |= 0xFFF80000ULL << 32;
675 #endif
676 FT0 = p.d;
677 }
678
679 #if defined(TARGET_PPC64)
680 void do_fcfid (void)
681 {
682 union {
683 double d;
684 uint64_t i;
685 } p;
686
687 p.d = FT0;
688 FT0 = int64_to_float64(p.i, &env->fp_status);
689 }
690
691 void do_fctid (void)
692 {
693 union {
694 double d;
695 uint64_t i;
696 } p;
697
698 p.i = float64_to_int64(FT0, &env->fp_status);
699 FT0 = p.d;
700 }
701
702 void do_fctidz (void)
703 {
704 union {
705 double d;
706 uint64_t i;
707 } p;
708
709 p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
710 FT0 = p.d;
711 }
712
713 #endif
714
715 static always_inline void do_fri (int rounding_mode)
716 {
717 int curmode;
718
719 curmode = env->fp_status.float_rounding_mode;
720 set_float_rounding_mode(rounding_mode, &env->fp_status);
721 FT0 = float64_round_to_int(FT0, &env->fp_status);
722 set_float_rounding_mode(curmode, &env->fp_status);
723 }
724
725 void do_frin (void)
726 {
727 do_fri(float_round_nearest_even);
728 }
729
730 void do_friz (void)
731 {
732 do_fri(float_round_to_zero);
733 }
734
735 void do_frip (void)
736 {
737 do_fri(float_round_up);
738 }
739
740 void do_frim (void)
741 {
742 do_fri(float_round_down);
743 }
744
745 #if USE_PRECISE_EMULATION
746 void do_fmadd (void)
747 {
748 #ifdef FLOAT128
749 float128 ft0_128, ft1_128;
750
751 ft0_128 = float64_to_float128(FT0, &env->fp_status);
752 ft1_128 = float64_to_float128(FT1, &env->fp_status);
753 ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
754 ft1_128 = float64_to_float128(FT2, &env->fp_status);
755 ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
756 FT0 = float128_to_float64(ft0_128, &env->fp_status);
757 #else
758 /* This is OK on x86 hosts */
759 FT0 = (FT0 * FT1) + FT2;
760 #endif
761 }
762
763 void do_fmsub (void)
764 {
765 #ifdef FLOAT128
766 float128 ft0_128, ft1_128;
767
768 ft0_128 = float64_to_float128(FT0, &env->fp_status);
769 ft1_128 = float64_to_float128(FT1, &env->fp_status);
770 ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
771 ft1_128 = float64_to_float128(FT2, &env->fp_status);
772 ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
773 FT0 = float128_to_float64(ft0_128, &env->fp_status);
774 #else
775 /* This is OK on x86 hosts */
776 FT0 = (FT0 * FT1) - FT2;
777 #endif
778 }
779 #endif /* USE_PRECISE_EMULATION */
780
781 void do_fnmadd (void)
782 {
783 #if USE_PRECISE_EMULATION
784 #ifdef FLOAT128
785 float128 ft0_128, ft1_128;
786
787 ft0_128 = float64_to_float128(FT0, &env->fp_status);
788 ft1_128 = float64_to_float128(FT1, &env->fp_status);
789 ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
790 ft1_128 = float64_to_float128(FT2, &env->fp_status);
791 ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
792 FT0 = float128_to_float64(ft0_128, &env->fp_status);
793 #else
794 /* This is OK on x86 hosts */
795 FT0 = (FT0 * FT1) + FT2;
796 #endif
797 #else
798 FT0 = float64_mul(FT0, FT1, &env->fp_status);
799 FT0 = float64_add(FT0, FT2, &env->fp_status);
800 #endif
801 if (likely(!isnan(FT0)))
802 FT0 = float64_chs(FT0);
803 }
804
805 void do_fnmsub (void)
806 {
807 #if USE_PRECISE_EMULATION
808 #ifdef FLOAT128
809 float128 ft0_128, ft1_128;
810
811 ft0_128 = float64_to_float128(FT0, &env->fp_status);
812 ft1_128 = float64_to_float128(FT1, &env->fp_status);
813 ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
814 ft1_128 = float64_to_float128(FT2, &env->fp_status);
815 ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
816 FT0 = float128_to_float64(ft0_128, &env->fp_status);
817 #else
818 /* This is OK on x86 hosts */
819 FT0 = (FT0 * FT1) - FT2;
820 #endif
821 #else
822 FT0 = float64_mul(FT0, FT1, &env->fp_status);
823 FT0 = float64_sub(FT0, FT2, &env->fp_status);
824 #endif
825 if (likely(!isnan(FT0)))
826 FT0 = float64_chs(FT0);
827 }
828
829 void do_fsqrt (void)
830 {
831 FT0 = float64_sqrt(FT0, &env->fp_status);
832 }
833
834 void do_fre (void)
835 {
836 union {
837 double d;
838 uint64_t i;
839 } p;
840
841 if (likely(isnormal(FT0))) {
842 FT0 = float64_div(1.0, FT0, &env->fp_status);
843 } else {
844 p.d = FT0;
845 if (p.i == 0x8000000000000000ULL) {
846 p.i = 0xFFF0000000000000ULL;
847 } else if (p.i == 0x0000000000000000ULL) {
848 p.i = 0x7FF0000000000000ULL;
849 } else if (isnan(FT0)) {
850 p.i = 0x7FF8000000000000ULL;
851 } else if (FT0 < 0.0) {
852 p.i = 0x8000000000000000ULL;
853 } else {
854 p.i = 0x0000000000000000ULL;
855 }
856 FT0 = p.d;
857 }
858 }
859
860 void do_fres (void)
861 {
862 union {
863 double d;
864 uint64_t i;
865 } p;
866
867 if (likely(isnormal(FT0))) {
868 #if USE_PRECISE_EMULATION
869 FT0 = float64_div(1.0, FT0, &env->fp_status);
870 FT0 = float64_to_float32(FT0, &env->fp_status);
871 #else
872 FT0 = float32_div(1.0, FT0, &env->fp_status);
873 #endif
874 } else {
875 p.d = FT0;
876 if (p.i == 0x8000000000000000ULL) {
877 p.i = 0xFFF0000000000000ULL;
878 } else if (p.i == 0x0000000000000000ULL) {
879 p.i = 0x7FF0000000000000ULL;
880 } else if (isnan(FT0)) {
881 p.i = 0x7FF8000000000000ULL;
882 } else if (FT0 < 0.0) {
883 p.i = 0x8000000000000000ULL;
884 } else {
885 p.i = 0x0000000000000000ULL;
886 }
887 FT0 = p.d;
888 }
889 }
890
891 void do_frsqrte (void)
892 {
893 union {
894 double d;
895 uint64_t i;
896 } p;
897
898 if (likely(isnormal(FT0) && FT0 > 0.0)) {
899 FT0 = float64_sqrt(FT0, &env->fp_status);
900 FT0 = float32_div(1.0, FT0, &env->fp_status);
901 } else {
902 p.d = FT0;
903 if (p.i == 0x8000000000000000ULL) {
904 p.i = 0xFFF0000000000000ULL;
905 } else if (p.i == 0x0000000000000000ULL) {
906 p.i = 0x7FF0000000000000ULL;
907 } else if (isnan(FT0)) {
908 if (!(p.i & 0x0008000000000000ULL))
909 p.i |= 0x000FFFFFFFFFFFFFULL;
910 } else if (FT0 < 0) {
911 p.i = 0x7FF8000000000000ULL;
912 } else {
913 p.i = 0x0000000000000000ULL;
914 }
915 FT0 = p.d;
916 }
917 }
918
919 void do_fsel (void)
920 {
921 if (FT0 >= 0)
922 FT0 = FT1;
923 else
924 FT0 = FT2;
925 }
926
927 void do_fcmpu (void)
928 {
929 if (likely(!isnan(FT0) && !isnan(FT1))) {
930 if (float64_lt(FT0, FT1, &env->fp_status)) {
931 T0 = 0x08UL;
932 } else if (!float64_le(FT0, FT1, &env->fp_status)) {
933 T0 = 0x04UL;
934 } else {
935 T0 = 0x02UL;
936 }
937 } else {
938 T0 = 0x01UL;
939 env->fpscr[4] |= 0x1;
940 env->fpscr[6] |= 0x1;
941 }
942 env->fpscr[3] = T0;
943 }
944
945 void do_fcmpo (void)
946 {
947 env->fpscr[4] &= ~0x1;
948 if (likely(!isnan(FT0) && !isnan(FT1))) {
949 if (float64_lt(FT0, FT1, &env->fp_status)) {
950 T0 = 0x08UL;
951 } else if (!float64_le(FT0, FT1, &env->fp_status)) {
952 T0 = 0x04UL;
953 } else {
954 T0 = 0x02UL;
955 }
956 } else {
957 T0 = 0x01UL;
958 env->fpscr[4] |= 0x1;
959 if (!float64_is_signaling_nan(FT0) || !float64_is_signaling_nan(FT1)) {
960 /* Quiet NaN case */
961 env->fpscr[6] |= 0x1;
962 if (!(env->fpscr[1] & 0x8))
963 env->fpscr[4] |= 0x8;
964 } else {
965 env->fpscr[4] |= 0x8;
966 }
967 }
968 env->fpscr[3] = T0;
969 }
970
971 #if !defined (CONFIG_USER_ONLY)
972 void cpu_dump_rfi (target_ulong RA, target_ulong msr);
973 void do_rfi (void)
974 {
975 #if defined(TARGET_PPC64)
976 if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
977 env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
978 do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
979 } else {
980 env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
981 ppc_store_msr_32(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
982 }
983 #else
984 env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
985 do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
986 #endif
987 #if defined (DEBUG_OP)
988 cpu_dump_rfi(env->nip, do_load_msr(env));
989 #endif
990 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
991 }
992
993 #if defined(TARGET_PPC64)
994 void do_rfid (void)
995 {
996 if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
997 env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
998 do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
999 } else {
1000 env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
1001 do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
1002 }
1003 #if defined (DEBUG_OP)
1004 cpu_dump_rfi(env->nip, do_load_msr(env));
1005 #endif
1006 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1007 }
1008 #endif
1009 #if defined(TARGET_PPC64H)
1010 void do_hrfid (void)
1011 {
1012 if (env->spr[SPR_HSRR1] & (1ULL << MSR_SF)) {
1013 env->nip = (uint64_t)(env->spr[SPR_HSRR0] & ~0x00000003);
1014 do_store_msr(env, (uint64_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL));
1015 } else {
1016 env->nip = (uint32_t)(env->spr[SPR_HSRR0] & ~0x00000003);
1017 do_store_msr(env, (uint32_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL));
1018 }
1019 #if defined (DEBUG_OP)
1020 cpu_dump_rfi(env->nip, do_load_msr(env));
1021 #endif
1022 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1023 }
1024 #endif
1025 #endif
1026
1027 void do_tw (int flags)
1028 {
1029 if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
1030 ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
1031 ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
1032 ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
1033 ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
1034 do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1035 }
1036 }
1037
1038 #if defined(TARGET_PPC64)
1039 void do_td (int flags)
1040 {
1041 if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) ||
1042 ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) ||
1043 ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
1044 ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
1045 ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
1046 do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1047 }
1048 #endif
1049
1050 /*****************************************************************************/
1051 /* PowerPC 601 specific instructions (POWER bridge) */
1052 void do_POWER_abso (void)
1053 {
1054 if ((uint32_t)T0 == INT32_MIN) {
1055 T0 = INT32_MAX;
1056 xer_ov = 1;
1057 xer_so = 1;
1058 } else {
1059 T0 = -T0;
1060 xer_ov = 0;
1061 }
1062 }
1063
1064 void do_POWER_clcs (void)
1065 {
1066 switch (T0) {
1067 case 0x0CUL:
1068 /* Instruction cache line size */
1069 T0 = env->icache_line_size;
1070 break;
1071 case 0x0DUL:
1072 /* Data cache line size */
1073 T0 = env->dcache_line_size;
1074 break;
1075 case 0x0EUL:
1076 /* Minimum cache line size */
1077 T0 = env->icache_line_size < env->dcache_line_size ?
1078 env->icache_line_size : env->dcache_line_size;
1079 break;
1080 case 0x0FUL:
1081 /* Maximum cache line size */
1082 T0 = env->icache_line_size > env->dcache_line_size ?
1083 env->icache_line_size : env->dcache_line_size;
1084 break;
1085 default:
1086 /* Undefined */
1087 break;
1088 }
1089 }
1090
1091 void do_POWER_div (void)
1092 {
1093 uint64_t tmp;
1094
1095 if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1096 T0 = (long)((-1) * (T0 >> 31));
1097 env->spr[SPR_MQ] = 0;
1098 } else {
1099 tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1100 env->spr[SPR_MQ] = tmp % T1;
1101 T0 = tmp / (int32_t)T1;
1102 }
1103 }
1104
1105 void do_POWER_divo (void)
1106 {
1107 int64_t tmp;
1108
1109 if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1110 T0 = (long)((-1) * (T0 >> 31));
1111 env->spr[SPR_MQ] = 0;
1112 xer_ov = 1;
1113 xer_so = 1;
1114 } else {
1115 tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1116 env->spr[SPR_MQ] = tmp % T1;
1117 tmp /= (int32_t)T1;
1118 if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
1119 xer_ov = 1;
1120 xer_so = 1;
1121 } else {
1122 xer_ov = 0;
1123 }
1124 T0 = tmp;
1125 }
1126 }
1127
1128 void do_POWER_divs (void)
1129 {
1130 if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1131 T0 = (long)((-1) * (T0 >> 31));
1132 env->spr[SPR_MQ] = 0;
1133 } else {
1134 env->spr[SPR_MQ] = T0 % T1;
1135 T0 = (int32_t)T0 / (int32_t)T1;
1136 }
1137 }
1138
1139 void do_POWER_divso (void)
1140 {
1141 if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1142 T0 = (long)((-1) * (T0 >> 31));
1143 env->spr[SPR_MQ] = 0;
1144 xer_ov = 1;
1145 xer_so = 1;
1146 } else {
1147 T0 = (int32_t)T0 / (int32_t)T1;
1148 env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
1149 xer_ov = 0;
1150 }
1151 }
1152
1153 void do_POWER_dozo (void)
1154 {
1155 if ((int32_t)T1 > (int32_t)T0) {
1156 T2 = T0;
1157 T0 = T1 - T0;
1158 if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
1159 ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
1160 xer_ov = 1;
1161 xer_so = 1;
1162 } else {
1163 xer_ov = 0;
1164 }
1165 } else {
1166 T0 = 0;
1167 xer_ov = 0;
1168 }
1169 }
1170
1171 void do_POWER_maskg (void)
1172 {
1173 uint32_t ret;
1174
1175 if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
1176 ret = -1;
1177 } else {
1178 ret = (((uint32_t)(-1)) >> ((uint32_t)T0)) ^
1179 (((uint32_t)(-1) >> ((uint32_t)T1)) >> 1);
1180 if ((uint32_t)T0 > (uint32_t)T1)
1181 ret = ~ret;
1182 }
1183 T0 = ret;
1184 }
1185
1186 void do_POWER_mulo (void)
1187 {
1188 uint64_t tmp;
1189
1190 tmp = (uint64_t)T0 * (uint64_t)T1;
1191 env->spr[SPR_MQ] = tmp >> 32;
1192 T0 = tmp;
1193 if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
1194 xer_ov = 1;
1195 xer_so = 1;
1196 } else {
1197 xer_ov = 0;
1198 }
1199 }
1200
1201 #if !defined (CONFIG_USER_ONLY)
1202 void do_POWER_rac (void)
1203 {
1204 #if 0
1205 mmu_ctx_t ctx;
1206
1207 /* We don't have to generate many instances of this instruction,
1208 * as rac is supervisor only.
1209 */
1210 if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT, 1) == 0)
1211 T0 = ctx.raddr;
1212 #endif
1213 }
1214
1215 void do_POWER_rfsvc (void)
1216 {
1217 env->nip = env->lr & ~0x00000003UL;
1218 T0 = env->ctr & 0x0000FFFFUL;
1219 do_store_msr(env, T0);
1220 #if defined (DEBUG_OP)
1221 cpu_dump_rfi(env->nip, do_load_msr(env));
1222 #endif
1223 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1224 }
1225
1226 /* PowerPC 601 BAT management helper */
1227 void do_store_601_batu (int nr)
1228 {
1229 do_store_ibatu(env, nr, (uint32_t)T0);
1230 env->DBAT[0][nr] = env->IBAT[0][nr];
1231 env->DBAT[1][nr] = env->IBAT[1][nr];
1232 }
1233 #endif
1234
1235 /*****************************************************************************/
1236 /* 602 specific instructions */
1237 /* mfrom is the most crazy instruction ever seen, imho ! */
1238 /* Real implementation uses a ROM table. Do the same */
1239 #define USE_MFROM_ROM_TABLE
1240 void do_op_602_mfrom (void)
1241 {
1242 if (likely(T0 < 602)) {
1243 #if defined(USE_MFROM_ROM_TABLE)
1244 #include "mfrom_table.c"
1245 T0 = mfrom_ROM_table[T0];
1246 #else
1247 double d;
1248 /* Extremly decomposed:
1249 * -T0 / 256
1250 * T0 = 256 * log10(10 + 1.0) + 0.5
1251 */
1252 d = T0;
1253 d = float64_div(d, 256, &env->fp_status);
1254 d = float64_chs(d);
1255 d = exp10(d); // XXX: use float emulation function
1256 d = float64_add(d, 1.0, &env->fp_status);
1257 d = log10(d); // XXX: use float emulation function
1258 d = float64_mul(d, 256, &env->fp_status);
1259 d = float64_add(d, 0.5, &env->fp_status);
1260 T0 = float64_round_to_int(d, &env->fp_status);
1261 #endif
1262 } else {
1263 T0 = 0;
1264 }
1265 }
1266
1267 /*****************************************************************************/
1268 /* Embedded PowerPC specific helpers */
1269 void do_405_check_ov (void)
1270 {
1271 if (likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1272 !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1273 xer_ov = 0;
1274 } else {
1275 xer_ov = 1;
1276 xer_so = 1;
1277 }
1278 }
1279
1280 void do_405_check_sat (void)
1281 {
1282 if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1283 !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1284 /* Saturate result */
1285 if (T2 >> 31) {
1286 T0 = INT32_MIN;
1287 } else {
1288 T0 = INT32_MAX;
1289 }
1290 }
1291 }
1292
1293 /* XXX: to be improved to check access rights when in user-mode */
1294 void do_load_dcr (void)
1295 {
1296 target_ulong val;
1297
1298 if (unlikely(env->dcr_env == NULL)) {
1299 if (loglevel != 0) {
1300 fprintf(logfile, "No DCR environment\n");
1301 }
1302 do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1303 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1304 } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
1305 if (loglevel != 0) {
1306 fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
1307 }
1308 do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1309 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1310 } else {
1311 T0 = val;
1312 }
1313 }
1314
1315 void do_store_dcr (void)
1316 {
1317 if (unlikely(env->dcr_env == NULL)) {
1318 if (loglevel != 0) {
1319 fprintf(logfile, "No DCR environment\n");
1320 }
1321 do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1322 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1323 } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
1324 if (loglevel != 0) {
1325 fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
1326 }
1327 do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1328 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1329 }
1330 }
1331
1332 #if !defined(CONFIG_USER_ONLY)
1333 void do_40x_rfci (void)
1334 {
1335 env->nip = env->spr[SPR_40x_SRR2];
1336 do_store_msr(env, env->spr[SPR_40x_SRR3] & ~0xFFFF0000);
1337 #if defined (DEBUG_OP)
1338 cpu_dump_rfi(env->nip, do_load_msr(env));
1339 #endif
1340 env->interrupt_request = CPU_INTERRUPT_EXITTB;
1341 }
1342
1343 void do_rfci (void)
1344 {
1345 #if defined(TARGET_PPC64)
1346 if (env->spr[SPR_BOOKE_CSRR1] & (1 << MSR_CM)) {
1347 env->nip = (uint64_t)env->spr[SPR_BOOKE_CSRR0];
1348 } else
1349 #endif
1350 {
1351 env->nip = (uint32_t)env->spr[SPR_BOOKE_CSRR0];
1352 }
1353 do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_CSRR1] & ~0x3FFF0000);
1354 #if defined (DEBUG_OP)
1355 cpu_dump_rfi(env->nip, do_load_msr(env));
1356 #endif
1357 env->interrupt_request = CPU_INTERRUPT_EXITTB;
1358 }
1359
1360 void do_rfdi (void)
1361 {
1362 #if defined(TARGET_PPC64)
1363 if (env->spr[SPR_BOOKE_DSRR1] & (1 << MSR_CM)) {
1364 env->nip = (uint64_t)env->spr[SPR_BOOKE_DSRR0];
1365 } else
1366 #endif
1367 {
1368 env->nip = (uint32_t)env->spr[SPR_BOOKE_DSRR0];
1369 }
1370 do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_DSRR1] & ~0x3FFF0000);
1371 #if defined (DEBUG_OP)
1372 cpu_dump_rfi(env->nip, do_load_msr(env));
1373 #endif
1374 env->interrupt_request = CPU_INTERRUPT_EXITTB;
1375 }
1376
1377 void do_rfmci (void)
1378 {
1379 #if defined(TARGET_PPC64)
1380 if (env->spr[SPR_BOOKE_MCSRR1] & (1 << MSR_CM)) {
1381 env->nip = (uint64_t)env->spr[SPR_BOOKE_MCSRR0];
1382 } else
1383 #endif
1384 {
1385 env->nip = (uint32_t)env->spr[SPR_BOOKE_MCSRR0];
1386 }
1387 do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_MCSRR1] & ~0x3FFF0000);
1388 #if defined (DEBUG_OP)
1389 cpu_dump_rfi(env->nip, do_load_msr(env));
1390 #endif
1391 env->interrupt_request = CPU_INTERRUPT_EXITTB;
1392 }
1393
1394 void do_load_403_pb (int num)
1395 {
1396 T0 = env->pb[num];
1397 }
1398
1399 void do_store_403_pb (int num)
1400 {
1401 if (likely(env->pb[num] != T0)) {
1402 env->pb[num] = T0;
1403 /* Should be optimized */
1404 tlb_flush(env, 1);
1405 }
1406 }
1407 #endif
1408
1409 /* 440 specific */
1410 void do_440_dlmzb (void)
1411 {
1412 target_ulong mask;
1413 int i;
1414
1415 i = 1;
1416 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1417 if ((T0 & mask) == 0)
1418 goto done;
1419 i++;
1420 }
1421 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1422 if ((T1 & mask) == 0)
1423 break;
1424 i++;
1425 }
1426 done:
1427 T0 = i;
1428 }
1429
1430 #if defined(TARGET_PPCEMB)
1431 /* SPE extension helpers */
1432 /* Use a table to make this quicker */
1433 static uint8_t hbrev[16] = {
1434 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1435 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1436 };
1437
1438 static always_inline uint8_t byte_reverse (uint8_t val)
1439 {
1440 return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1441 }
1442
1443 static always_inline uint32_t word_reverse (uint32_t val)
1444 {
1445 return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1446 (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1447 }
1448
1449 #define MASKBITS 16 // Random value - to be fixed
1450 void do_brinc (void)
1451 {
1452 uint32_t a, b, d, mask;
1453
1454 mask = (uint32_t)(-1UL) >> MASKBITS;
1455 b = T1_64 & mask;
1456 a = T0_64 & mask;
1457 d = word_reverse(1 + word_reverse(a | ~mask));
1458 T0_64 = (T0_64 & ~mask) | (d & mask);
1459 }
1460
1461 #define DO_SPE_OP2(name) \
1462 void do_ev##name (void) \
1463 { \
1464 T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) | \
1465 (uint64_t)_do_e##name(T0_64, T1_64); \
1466 }
1467
1468 #define DO_SPE_OP1(name) \
1469 void do_ev##name (void) \
1470 { \
1471 T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) | \
1472 (uint64_t)_do_e##name(T0_64); \
1473 }
1474
1475 /* Fixed-point vector arithmetic */
1476 static always_inline uint32_t _do_eabs (uint32_t val)
1477 {
1478 if (val != 0x80000000)
1479 val &= ~0x80000000;
1480
1481 return val;
1482 }
1483
1484 static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
1485 {
1486 return op1 + op2;
1487 }
1488
1489 static always_inline int _do_ecntlsw (uint32_t val)
1490 {
1491 if (val & 0x80000000)
1492 return _do_cntlzw(~val);
1493 else
1494 return _do_cntlzw(val);
1495 }
1496
1497 static always_inline int _do_ecntlzw (uint32_t val)
1498 {
1499 return _do_cntlzw(val);
1500 }
1501
1502 static always_inline uint32_t _do_eneg (uint32_t val)
1503 {
1504 if (val != 0x80000000)
1505 val ^= 0x80000000;
1506
1507 return val;
1508 }
1509
1510 static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1511 {
1512 return rotl32(op1, op2);
1513 }
1514
1515 static always_inline uint32_t _do_erndw (uint32_t val)
1516 {
1517 return (val + 0x000080000000) & 0xFFFF0000;
1518 }
1519
1520 static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1521 {
1522 /* No error here: 6 bits are used */
1523 return op1 << (op2 & 0x3F);
1524 }
1525
1526 static always_inline int32_t _do_esrws (int32_t op1, uint32_t op2)
1527 {
1528 /* No error here: 6 bits are used */
1529 return op1 >> (op2 & 0x3F);
1530 }
1531
1532 static always_inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
1533 {
1534 /* No error here: 6 bits are used */
1535 return op1 >> (op2 & 0x3F);
1536 }
1537
1538 static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1539 {
1540 return op2 - op1;
1541 }
1542
1543 /* evabs */
1544 DO_SPE_OP1(abs);
1545 /* evaddw */
1546 DO_SPE_OP2(addw);
1547 /* evcntlsw */
1548 DO_SPE_OP1(cntlsw);
1549 /* evcntlzw */
1550 DO_SPE_OP1(cntlzw);
1551 /* evneg */
1552 DO_SPE_OP1(neg);
1553 /* evrlw */
1554 DO_SPE_OP2(rlw);
1555 /* evrnd */
1556 DO_SPE_OP1(rndw);
1557 /* evslw */
1558 DO_SPE_OP2(slw);
1559 /* evsrws */
1560 DO_SPE_OP2(srws);
1561 /* evsrwu */
1562 DO_SPE_OP2(srwu);
1563 /* evsubfw */
1564 DO_SPE_OP2(subfw);
1565
1566 /* evsel is a little bit more complicated... */
1567 static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1568 {
1569 if (n)
1570 return op1;
1571 else
1572 return op2;
1573 }
1574
1575 void do_evsel (void)
1576 {
1577 T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
1578 (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
1579 }
1580
1581 /* Fixed-point vector comparisons */
1582 #define DO_SPE_CMP(name) \
1583 void do_ev##name (void) \
1584 { \
1585 T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32, \
1586 T1_64 >> 32) << 32, \
1587 _do_e##name(T0_64, T1_64)); \
1588 }
1589
1590 static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
1591 {
1592 return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1593 }
1594 static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
1595 {
1596 return op1 == op2 ? 1 : 0;
1597 }
1598
1599 static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
1600 {
1601 return op1 > op2 ? 1 : 0;
1602 }
1603
1604 static always_inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
1605 {
1606 return op1 > op2 ? 1 : 0;
1607 }
1608
1609 static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
1610 {
1611 return op1 < op2 ? 1 : 0;
1612 }
1613
1614 static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
1615 {
1616 return op1 < op2 ? 1 : 0;
1617 }
1618
1619 /* evcmpeq */
1620 DO_SPE_CMP(cmpeq);
1621 /* evcmpgts */
1622 DO_SPE_CMP(cmpgts);
1623 /* evcmpgtu */
1624 DO_SPE_CMP(cmpgtu);
1625 /* evcmplts */
1626 DO_SPE_CMP(cmplts);
1627 /* evcmpltu */
1628 DO_SPE_CMP(cmpltu);
1629
1630 /* Single precision floating-point conversions from/to integer */
1631 static always_inline uint32_t _do_efscfsi (int32_t val)
1632 {
1633 union {
1634 uint32_t u;
1635 float32 f;
1636 } u;
1637
1638 u.f = int32_to_float32(val, &env->spe_status);
1639
1640 return u.u;
1641 }
1642
1643 static always_inline uint32_t _do_efscfui (uint32_t val)
1644 {
1645 union {
1646 uint32_t u;
1647 float32 f;
1648 } u;
1649
1650 u.f = uint32_to_float32(val, &env->spe_status);
1651
1652 return u.u;
1653 }
1654
1655 static always_inline int32_t _do_efsctsi (uint32_t val)
1656 {
1657 union {
1658 int32_t u;
1659 float32 f;
1660 } u;
1661
1662 u.u = val;
1663 /* NaN are not treated the same way IEEE 754 does */
1664 if (unlikely(isnan(u.f)))
1665 return 0;
1666
1667 return float32_to_int32(u.f, &env->spe_status);
1668 }
1669
1670 static always_inline uint32_t _do_efsctui (uint32_t val)
1671 {
1672 union {
1673 int32_t u;
1674 float32 f;
1675 } u;
1676
1677 u.u = val;
1678 /* NaN are not treated the same way IEEE 754 does */
1679 if (unlikely(isnan(u.f)))
1680 return 0;
1681
1682 return float32_to_uint32(u.f, &env->spe_status);
1683 }
1684
1685 static always_inline int32_t _do_efsctsiz (uint32_t val)
1686 {
1687 union {
1688 int32_t u;
1689 float32 f;
1690 } u;
1691
1692 u.u = val;
1693 /* NaN are not treated the same way IEEE 754 does */
1694 if (unlikely(isnan(u.f)))
1695 return 0;
1696
1697 return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1698 }
1699
1700 static always_inline uint32_t _do_efsctuiz (uint32_t val)
1701 {
1702 union {
1703 int32_t u;
1704 float32 f;
1705 } u;
1706
1707 u.u = val;
1708 /* NaN are not treated the same way IEEE 754 does */
1709 if (unlikely(isnan(u.f)))
1710 return 0;
1711
1712 return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1713 }
1714
1715 void do_efscfsi (void)
1716 {
1717 T0_64 = _do_efscfsi(T0_64);
1718 }
1719
1720 void do_efscfui (void)
1721 {
1722 T0_64 = _do_efscfui(T0_64);
1723 }
1724
1725 void do_efsctsi (void)
1726 {
1727 T0_64 = _do_efsctsi(T0_64);
1728 }
1729
1730 void do_efsctui (void)
1731 {
1732 T0_64 = _do_efsctui(T0_64);
1733 }
1734
1735 void do_efsctsiz (void)
1736 {
1737 T0_64 = _do_efsctsiz(T0_64);
1738 }
1739
1740 void do_efsctuiz (void)
1741 {
1742 T0_64 = _do_efsctuiz(T0_64);
1743 }
1744
1745 /* Single precision floating-point conversion to/from fractional */
1746 static always_inline uint32_t _do_efscfsf (uint32_t val)
1747 {
1748 union {
1749 uint32_t u;
1750 float32 f;
1751 } u;
1752 float32 tmp;
1753
1754 u.f = int32_to_float32(val, &env->spe_status);
1755 tmp = int64_to_float32(1ULL << 32, &env->spe_status);
1756 u.f = float32_div(u.f, tmp, &env->spe_status);
1757
1758 return u.u;
1759 }
1760
1761 static always_inline uint32_t _do_efscfuf (uint32_t val)
1762 {
1763 union {
1764 uint32_t u;
1765 float32 f;
1766 } u;
1767 float32 tmp;
1768
1769 u.f = uint32_to_float32(val, &env->spe_status);
1770 tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1771 u.f = float32_div(u.f, tmp, &env->spe_status);
1772
1773 return u.u;
1774 }
1775
1776 static always_inline int32_t _do_efsctsf (uint32_t val)
1777 {
1778 union {
1779 int32_t u;
1780 float32 f;
1781 } u;
1782 float32 tmp;
1783
1784 u.u = val;
1785 /* NaN are not treated the same way IEEE 754 does */
1786 if (unlikely(isnan(u.f)))
1787 return 0;
1788 tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1789 u.f = float32_mul(u.f, tmp, &env->spe_status);
1790
1791 return float32_to_int32(u.f, &env->spe_status);
1792 }
1793
1794 static always_inline uint32_t _do_efsctuf (uint32_t val)
1795 {
1796 union {
1797 int32_t u;
1798 float32 f;
1799 } u;
1800 float32 tmp;
1801
1802 u.u = val;
1803 /* NaN are not treated the same way IEEE 754 does */
1804 if (unlikely(isnan(u.f)))
1805 return 0;
1806 tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1807 u.f = float32_mul(u.f, tmp, &env->spe_status);
1808
1809 return float32_to_uint32(u.f, &env->spe_status);
1810 }
1811
1812 static always_inline int32_t _do_efsctsfz (uint32_t val)
1813 {
1814 union {
1815 int32_t u;
1816 float32 f;
1817 } u;
1818 float32 tmp;
1819
1820 u.u = val;
1821 /* NaN are not treated the same way IEEE 754 does */
1822 if (unlikely(isnan(u.f)))
1823 return 0;
1824 tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1825 u.f = float32_mul(u.f, tmp, &env->spe_status);
1826
1827 return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1828 }
1829
1830 static always_inline uint32_t _do_efsctufz (uint32_t val)
1831 {
1832 union {
1833 int32_t u;
1834 float32 f;
1835 } u;
1836 float32 tmp;
1837
1838 u.u = val;
1839 /* NaN are not treated the same way IEEE 754 does */
1840 if (unlikely(isnan(u.f)))
1841 return 0;
1842 tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1843 u.f = float32_mul(u.f, tmp, &env->spe_status);
1844
1845 return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1846 }
1847
1848 void do_efscfsf (void)
1849 {
1850 T0_64 = _do_efscfsf(T0_64);
1851 }
1852
1853 void do_efscfuf (void)
1854 {
1855 T0_64 = _do_efscfuf(T0_64);
1856 }
1857
1858 void do_efsctsf (void)
1859 {
1860 T0_64 = _do_efsctsf(T0_64);
1861 }
1862
1863 void do_efsctuf (void)
1864 {
1865 T0_64 = _do_efsctuf(T0_64);
1866 }
1867
1868 void do_efsctsfz (void)
1869 {
1870 T0_64 = _do_efsctsfz(T0_64);
1871 }
1872
1873 void do_efsctufz (void)
1874 {
1875 T0_64 = _do_efsctufz(T0_64);
1876 }
1877
1878 /* Double precision floating point helpers */
1879 static always_inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
1880 {
1881 /* XXX: TODO: test special values (NaN, infinites, ...) */
1882 return _do_efdtstlt(op1, op2);
1883 }
1884
1885 static always_inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
1886 {
1887 /* XXX: TODO: test special values (NaN, infinites, ...) */
1888 return _do_efdtstgt(op1, op2);
1889 }
1890
1891 static always_inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
1892 {
1893 /* XXX: TODO: test special values (NaN, infinites, ...) */
1894 return _do_efdtsteq(op1, op2);
1895 }
1896
1897 void do_efdcmplt (void)
1898 {
1899 T0 = _do_efdcmplt(T0_64, T1_64);
1900 }
1901
1902 void do_efdcmpgt (void)
1903 {
1904 T0 = _do_efdcmpgt(T0_64, T1_64);
1905 }
1906
1907 void do_efdcmpeq (void)
1908 {
1909 T0 = _do_efdcmpeq(T0_64, T1_64);
1910 }
1911
1912 /* Double precision floating-point conversion to/from integer */
1913 static always_inline uint64_t _do_efdcfsi (int64_t val)
1914 {
1915 union {
1916 uint64_t u;
1917 float64 f;
1918 } u;
1919
1920 u.f = int64_to_float64(val, &env->spe_status);
1921
1922 return u.u;
1923 }
1924
1925 static always_inline uint64_t _do_efdcfui (uint64_t val)
1926 {
1927 union {
1928 uint64_t u;
1929 float64 f;
1930 } u;
1931
1932 u.f = uint64_to_float64(val, &env->spe_status);
1933
1934 return u.u;
1935 }
1936
1937 static always_inline int64_t _do_efdctsi (uint64_t val)
1938 {
1939 union {
1940 int64_t u;
1941 float64 f;
1942 } u;
1943
1944 u.u = val;
1945 /* NaN are not treated the same way IEEE 754 does */
1946 if (unlikely(isnan(u.f)))
1947 return 0;
1948
1949 return float64_to_int64(u.f, &env->spe_status);
1950 }
1951
1952 static always_inline uint64_t _do_efdctui (uint64_t val)
1953 {
1954 union {
1955 int64_t u;
1956 float64 f;
1957 } u;
1958
1959 u.u = val;
1960 /* NaN are not treated the same way IEEE 754 does */
1961 if (unlikely(isnan(u.f)))
1962 return 0;
1963
1964 return float64_to_uint64(u.f, &env->spe_status);
1965 }
1966
1967 static always_inline int64_t _do_efdctsiz (uint64_t val)
1968 {
1969 union {
1970 int64_t u;
1971 float64 f;
1972 } u;
1973
1974 u.u = val;
1975 /* NaN are not treated the same way IEEE 754 does */
1976 if (unlikely(isnan(u.f)))
1977 return 0;
1978
1979 return float64_to_int64_round_to_zero(u.f, &env->spe_status);
1980 }
1981
1982 static always_inline uint64_t _do_efdctuiz (uint64_t val)
1983 {
1984 union {
1985 int64_t u;
1986 float64 f;
1987 } u;
1988
1989 u.u = val;
1990 /* NaN are not treated the same way IEEE 754 does */
1991 if (unlikely(isnan(u.f)))
1992 return 0;
1993
1994 return float64_to_uint64_round_to_zero(u.f, &env->spe_status);
1995 }
1996
1997 void do_efdcfsi (void)
1998 {
1999 T0_64 = _do_efdcfsi(T0_64);
2000 }
2001
2002 void do_efdcfui (void)
2003 {
2004 T0_64 = _do_efdcfui(T0_64);
2005 }
2006
2007 void do_efdctsi (void)
2008 {
2009 T0_64 = _do_efdctsi(T0_64);
2010 }
2011
2012 void do_efdctui (void)
2013 {
2014 T0_64 = _do_efdctui(T0_64);
2015 }
2016
2017 void do_efdctsiz (void)
2018 {
2019 T0_64 = _do_efdctsiz(T0_64);
2020 }
2021
2022 void do_efdctuiz (void)
2023 {
2024 T0_64 = _do_efdctuiz(T0_64);
2025 }
2026
2027 /* Double precision floating-point conversion to/from fractional */
2028 static always_inline uint64_t _do_efdcfsf (int64_t val)
2029 {
2030 union {
2031 uint64_t u;
2032 float64 f;
2033 } u;
2034 float64 tmp;
2035
2036 u.f = int32_to_float64(val, &env->spe_status);
2037 tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2038 u.f = float64_div(u.f, tmp, &env->spe_status);
2039
2040 return u.u;
2041 }
2042
2043 static always_inline uint64_t _do_efdcfuf (uint64_t val)
2044 {
2045 union {
2046 uint64_t u;
2047 float64 f;
2048 } u;
2049 float64 tmp;
2050
2051 u.f = uint32_to_float64(val, &env->spe_status);
2052 tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2053 u.f = float64_div(u.f, tmp, &env->spe_status);
2054
2055 return u.u;
2056 }
2057
2058 static always_inline int64_t _do_efdctsf (uint64_t val)
2059 {
2060 union {
2061 int64_t u;
2062 float64 f;
2063 } u;
2064 float64 tmp;
2065
2066 u.u = val;
2067 /* NaN are not treated the same way IEEE 754 does */
2068 if (unlikely(isnan(u.f)))
2069 return 0;
2070 tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2071 u.f = float64_mul(u.f, tmp, &env->spe_status);
2072
2073 return float64_to_int32(u.f, &env->spe_status);
2074 }
2075
2076 static always_inline uint64_t _do_efdctuf (uint64_t val)
2077 {
2078 union {
2079 int64_t u;
2080 float64 f;
2081 } u;
2082 float64 tmp;
2083
2084 u.u = val;
2085 /* NaN are not treated the same way IEEE 754 does */
2086 if (unlikely(isnan(u.f)))
2087 return 0;
2088 tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2089 u.f = float64_mul(u.f, tmp, &env->spe_status);
2090
2091 return float64_to_uint32(u.f, &env->spe_status);
2092 }
2093
2094 static always_inline int64_t _do_efdctsfz (uint64_t val)
2095 {
2096 union {
2097 int64_t u;
2098 float64 f;
2099 } u;
2100 float64 tmp;
2101
2102 u.u = val;
2103 /* NaN are not treated the same way IEEE 754 does */
2104 if (unlikely(isnan(u.f)))
2105 return 0;
2106 tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2107 u.f = float64_mul(u.f, tmp, &env->spe_status);
2108
2109 return float64_to_int32_round_to_zero(u.f, &env->spe_status);
2110 }
2111
2112 static always_inline uint64_t _do_efdctufz (uint64_t val)
2113 {
2114 union {
2115 int64_t u;
2116 float64 f;
2117 } u;
2118 float64 tmp;
2119
2120 u.u = val;
2121 /* NaN are not treated the same way IEEE 754 does */
2122 if (unlikely(isnan(u.f)))
2123 return 0;
2124 tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2125 u.f = float64_mul(u.f, tmp, &env->spe_status);
2126
2127 return float64_to_uint32_round_to_zero(u.f, &env->spe_status);
2128 }
2129
2130 void do_efdcfsf (void)
2131 {
2132 T0_64 = _do_efdcfsf(T0_64);
2133 }
2134
2135 void do_efdcfuf (void)
2136 {
2137 T0_64 = _do_efdcfuf(T0_64);
2138 }
2139
2140 void do_efdctsf (void)
2141 {
2142 T0_64 = _do_efdctsf(T0_64);
2143 }
2144
2145 void do_efdctuf (void)
2146 {
2147 T0_64 = _do_efdctuf(T0_64);
2148 }
2149
2150 void do_efdctsfz (void)
2151 {
2152 T0_64 = _do_efdctsfz(T0_64);
2153 }
2154
2155 void do_efdctufz (void)
2156 {
2157 T0_64 = _do_efdctufz(T0_64);
2158 }
2159
2160 /* Floating point conversion between single and double precision */
2161 static always_inline uint32_t _do_efscfd (uint64_t val)
2162 {
2163 union {
2164 uint64_t u;
2165 float64 f;
2166 } u1;
2167 union {
2168 uint32_t u;
2169 float32 f;
2170 } u2;
2171
2172 u1.u = val;
2173 u2.f = float64_to_float32(u1.f, &env->spe_status);
2174
2175 return u2.u;
2176 }
2177
2178 static always_inline uint64_t _do_efdcfs (uint32_t val)
2179 {
2180 union {
2181 uint64_t u;
2182 float64 f;
2183 } u2;
2184 union {
2185 uint32_t u;
2186 float32 f;
2187 } u1;
2188
2189 u1.u = val;
2190 u2.f = float32_to_float64(u1.f, &env->spe_status);
2191
2192 return u2.u;
2193 }
2194
2195 void do_efscfd (void)
2196 {
2197 T0_64 = _do_efscfd(T0_64);
2198 }
2199
2200 void do_efdcfs (void)
2201 {
2202 T0_64 = _do_efdcfs(T0_64);
2203 }
2204
2205 /* Single precision fixed-point vector arithmetic */
2206 /* evfsabs */
2207 DO_SPE_OP1(fsabs);
2208 /* evfsnabs */
2209 DO_SPE_OP1(fsnabs);
2210 /* evfsneg */
2211 DO_SPE_OP1(fsneg);
2212 /* evfsadd */
2213 DO_SPE_OP2(fsadd);
2214 /* evfssub */
2215 DO_SPE_OP2(fssub);
2216 /* evfsmul */
2217 DO_SPE_OP2(fsmul);
2218 /* evfsdiv */
2219 DO_SPE_OP2(fsdiv);
2220
2221 /* Single-precision floating-point comparisons */
2222 static always_inline int _do_efscmplt (uint32_t op1, uint32_t op2)
2223 {
2224 /* XXX: TODO: test special values (NaN, infinites, ...) */
2225 return _do_efststlt(op1, op2);
2226 }
2227
2228 static always_inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
2229 {
2230 /* XXX: TODO: test special values (NaN, infinites, ...) */
2231 return _do_efststgt(op1, op2);
2232 }
2233
2234 static always_inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
2235 {
2236 /* XXX: TODO: test special values (NaN, infinites, ...) */
2237 return _do_efststeq(op1, op2);
2238 }
2239
2240 void do_efscmplt (void)
2241 {
2242 T0 = _do_efscmplt(T0_64, T1_64);
2243 }
2244
2245 void do_efscmpgt (void)
2246 {
2247 T0 = _do_efscmpgt(T0_64, T1_64);
2248 }
2249
2250 void do_efscmpeq (void)
2251 {
2252 T0 = _do_efscmpeq(T0_64, T1_64);
2253 }
2254
2255 /* Single-precision floating-point vector comparisons */
2256 /* evfscmplt */
2257 DO_SPE_CMP(fscmplt);
2258 /* evfscmpgt */
2259 DO_SPE_CMP(fscmpgt);
2260 /* evfscmpeq */
2261 DO_SPE_CMP(fscmpeq);
2262 /* evfststlt */
2263 DO_SPE_CMP(fststlt);
2264 /* evfststgt */
2265 DO_SPE_CMP(fststgt);
2266 /* evfststeq */
2267 DO_SPE_CMP(fststeq);
2268
2269 /* Single-precision floating-point vector conversions */
2270 /* evfscfsi */
2271 DO_SPE_OP1(fscfsi);
2272 /* evfscfui */
2273 DO_SPE_OP1(fscfui);
2274 /* evfscfuf */
2275 DO_SPE_OP1(fscfuf);
2276 /* evfscfsf */
2277 DO_SPE_OP1(fscfsf);
2278 /* evfsctsi */
2279 DO_SPE_OP1(fsctsi);
2280 /* evfsctui */
2281 DO_SPE_OP1(fsctui);
2282 /* evfsctsiz */
2283 DO_SPE_OP1(fsctsiz);
2284 /* evfsctuiz */
2285 DO_SPE_OP1(fsctuiz);
2286 /* evfsctsf */
2287 DO_SPE_OP1(fsctsf);
2288 /* evfsctuf */
2289 DO_SPE_OP1(fsctuf);
2290 #endif /* defined(TARGET_PPCEMB) */
2291
2292 /*****************************************************************************/
2293 /* Softmmu support */
2294 #if !defined (CONFIG_USER_ONLY)
2295
2296 #define MMUSUFFIX _mmu
2297 #define GETPC() (__builtin_return_address(0))
2298
2299 #define SHIFT 0
2300 #include "softmmu_template.h"
2301
2302 #define SHIFT 1
2303 #include "softmmu_template.h"
2304
2305 #define SHIFT 2
2306 #include "softmmu_template.h"
2307
2308 #define SHIFT 3
2309 #include "softmmu_template.h"
2310
2311 /* try to fill the TLB and return an exception if error. If retaddr is
2312 NULL, it means that the function was called in C code (i.e. not
2313 from generated code or from helper.c) */
2314 /* XXX: fix it to restore all registers */
2315 void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2316 {
2317 TranslationBlock *tb;
2318 CPUState *saved_env;
2319 target_phys_addr_t pc;
2320 int ret;
2321
2322 /* XXX: hack to restore env in all cases, even if not called from
2323 generated code */
2324 saved_env = env;
2325 env = cpu_single_env;
2326 ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2327 if (unlikely(ret != 0)) {
2328 if (likely(retaddr)) {
2329 /* now we have a real cpu fault */
2330 pc = (target_phys_addr_t)(unsigned long)retaddr;
2331 tb = tb_find_pc(pc);
2332 if (likely(tb)) {
2333 /* the PC is inside the translated code. It means that we have
2334 a virtual CPU fault */
2335 cpu_restore_state(tb, env, pc, NULL);
2336 }
2337 }
2338 do_raise_exception_err(env->exception_index, env->error_code);
2339 }
2340 env = saved_env;
2341 }
2342
2343 /* Software driven TLBs management */
2344 /* PowerPC 602/603 software TLB load instructions helpers */
2345 void do_load_6xx_tlb (int is_code)
2346 {
2347 target_ulong RPN, CMP, EPN;
2348 int way;
2349
2350 RPN = env->spr[SPR_RPA];
2351 if (is_code) {
2352 CMP = env->spr[SPR_ICMP];
2353 EPN = env->spr[SPR_IMISS];
2354 } else {
2355 CMP = env->spr[SPR_DCMP];
2356 EPN = env->spr[SPR_DMISS];
2357 }
2358 way = (env->spr[SPR_SRR1] >> 17) & 1;
2359 #if defined (DEBUG_SOFTWARE_TLB)
2360 if (loglevel != 0) {
2361 fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
2362 __func__, (unsigned long)T0, (unsigned long)EPN,
2363 (unsigned long)CMP, (unsigned long)RPN, way);
2364 }
2365 #endif
2366 /* Store this TLB */
2367 ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2368 way, is_code, CMP, RPN);
2369 }
2370
2371 void do_load_74xx_tlb (int is_code)
2372 {
2373 target_ulong RPN, CMP, EPN;
2374 int way;
2375
2376 RPN = env->spr[SPR_PTELO];
2377 CMP = env->spr[SPR_PTEHI];
2378 EPN = env->spr[SPR_TLBMISS] & ~0x3;
2379 way = env->spr[SPR_TLBMISS] & 0x3;
2380 #if defined (DEBUG_SOFTWARE_TLB)
2381 if (loglevel != 0) {
2382 fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
2383 __func__, (unsigned long)T0, (unsigned long)EPN,
2384 (unsigned long)CMP, (unsigned long)RPN, way);
2385 }
2386 #endif
2387 /* Store this TLB */
2388 ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2389 way, is_code, CMP, RPN);
2390 }
2391
2392 static target_ulong booke_tlb_to_page_size (int size)
2393 {
2394 return 1024 << (2 * size);
2395 }
2396
2397 static int booke_page_size_to_tlb (target_ulong page_size)
2398 {
2399 int size;
2400
2401 switch (page_size) {
2402 case 0x00000400UL:
2403 size = 0x0;
2404 break;
2405 case 0x00001000UL:
2406 size = 0x1;
2407 break;
2408 case 0x00004000UL:
2409 size = 0x2;
2410 break;
2411 case 0x00010000UL:
2412 size = 0x3;
2413 break;
2414 case 0x00040000UL:
2415 size = 0x4;
2416 break;
2417 case 0x00100000UL:
2418 size = 0x5;
2419 break;
2420 case 0x00400000UL:
2421 size = 0x6;
2422 break;
2423 case 0x01000000UL:
2424 size = 0x7;
2425 break;
2426 case 0x04000000UL:
2427 size = 0x8;
2428 break;
2429 case 0x10000000UL:
2430 size = 0x9;
2431 break;
2432 case 0x40000000UL:
2433 size = 0xA;
2434 break;
2435 #if defined (TARGET_PPC64)
2436 case 0x000100000000ULL:
2437 size = 0xB;
2438 break;
2439 case 0x000400000000ULL:
2440 size = 0xC;
2441 break;
2442 case 0x001000000000ULL:
2443 size = 0xD;
2444 break;
2445 case 0x004000000000ULL:
2446 size = 0xE;
2447 break;
2448 case 0x010000000000ULL:
2449 size = 0xF;
2450 break;
2451 #endif
2452 default:
2453 size = -1;
2454 break;
2455 }
2456
2457 return size;
2458 }
2459
2460 /* Helpers for 4xx TLB management */
2461 void do_4xx_tlbre_lo (void)
2462 {
2463 ppcemb_tlb_t *tlb;
2464 int size;
2465
2466 T0 &= 0x3F;
2467 tlb = &env->tlb[T0].tlbe;
2468 T0 = tlb->EPN;
2469 if (tlb->prot & PAGE_VALID)
2470 T0 |= 0x400;
2471 size = booke_page_size_to_tlb(tlb->size);
2472 if (size < 0 || size > 0x7)
2473 size = 1;
2474 T0 |= size << 7;
2475 env->spr[SPR_40x_PID] = tlb->PID;
2476 }
2477
2478 void do_4xx_tlbre_hi (void)
2479 {
2480 ppcemb_tlb_t *tlb;
2481
2482 T0 &= 0x3F;
2483 tlb = &env->tlb[T0].tlbe;
2484 T0 = tlb->RPN;
2485 if (tlb->prot & PAGE_EXEC)
2486 T0 |= 0x200;
2487 if (tlb->prot & PAGE_WRITE)
2488 T0 |= 0x100;
2489 }
2490
2491 void do_4xx_tlbwe_hi (void)
2492 {
2493 ppcemb_tlb_t *tlb;
2494 target_ulong page, end;
2495
2496 #if defined (DEBUG_SOFTWARE_TLB)
2497 if (loglevel != 0) {
2498 fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2499 }
2500 #endif
2501 T0 &= 0x3F;
2502 tlb = &env->tlb[T0].tlbe;
2503 /* Invalidate previous TLB (if it's valid) */
2504 if (tlb->prot & PAGE_VALID) {
2505 end = tlb->EPN + tlb->size;
2506 #if defined (DEBUG_SOFTWARE_TLB)
2507 if (loglevel != 0) {
2508 fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
2509 " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2510 }
2511 #endif
2512 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2513 tlb_flush_page(env, page);
2514 }
2515 tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
2516 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2517 * If this ever occurs, one should use the ppcemb target instead
2518 * of the ppc or ppc64 one
2519 */
2520 if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
2521 cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2522 "are not supported (%d)\n",
2523 tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
2524 }
2525 tlb->EPN = T1 & ~(tlb->size - 1);
2526 if (T1 & 0x40)
2527 tlb->prot |= PAGE_VALID;
2528 else
2529 tlb->prot &= ~PAGE_VALID;
2530 if (T1 & 0x20) {
2531 /* XXX: TO BE FIXED */
2532 cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
2533 }
2534 tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2535 tlb->attr = T1 & 0xFF;
2536 #if defined (DEBUG_SOFTWARE_TLB)
2537 if (loglevel != 0) {
2538 fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2539 " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2540 (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2541 tlb->prot & PAGE_READ ? 'r' : '-',
2542 tlb->prot & PAGE_WRITE ? 'w' : '-',
2543 tlb->prot & PAGE_EXEC ? 'x' : '-',
2544 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2545 }
2546 #endif
2547 /* Invalidate new TLB (if valid) */
2548 if (tlb->prot & PAGE_VALID) {
2549 end = tlb->EPN + tlb->size;
2550 #if defined (DEBUG_SOFTWARE_TLB)
2551 if (loglevel != 0) {
2552 fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
2553 " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2554 }
2555 #endif
2556 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2557 tlb_flush_page(env, page);
2558 }
2559 }
2560
2561 void do_4xx_tlbwe_lo (void)
2562 {
2563 ppcemb_tlb_t *tlb;
2564
2565 #if defined (DEBUG_SOFTWARE_TLB)
2566 if (loglevel != 0) {
2567 fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2568 }
2569 #endif
2570 T0 &= 0x3F;
2571 tlb = &env->tlb[T0].tlbe;
2572 tlb->RPN = T1 & 0xFFFFFC00;
2573 tlb->prot = PAGE_READ;
2574 if (T1 & 0x200)
2575 tlb->prot |= PAGE_EXEC;
2576 if (T1 & 0x100)
2577 tlb->prot |= PAGE_WRITE;
2578 #if defined (DEBUG_SOFTWARE_TLB)
2579 if (loglevel != 0) {
2580 fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2581 " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2582 (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2583 tlb->prot & PAGE_READ ? 'r' : '-',
2584 tlb->prot & PAGE_WRITE ? 'w' : '-',
2585 tlb->prot & PAGE_EXEC ? 'x' : '-',
2586 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2587 }
2588 #endif
2589 }
2590
2591 /* PowerPC 440 TLB management */
2592 void do_440_tlbwe (int word)
2593 {
2594 ppcemb_tlb_t *tlb;
2595 target_ulong EPN, RPN, size;
2596 int do_flush_tlbs;
2597
2598 #if defined (DEBUG_SOFTWARE_TLB)
2599 if (loglevel != 0) {
2600 fprintf(logfile, "%s word %d T0 " REGX " T1 " REGX "\n",
2601 __func__, word, T0, T1);
2602 }
2603 #endif
2604 do_flush_tlbs = 0;
2605 T0 &= 0x3F;
2606 tlb = &env->tlb[T0].tlbe;
2607 switch (word) {
2608 default:
2609 /* Just here to please gcc */
2610 case 0:
2611 EPN = T1 & 0xFFFFFC00;
2612 if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2613 do_flush_tlbs = 1;
2614 tlb->EPN = EPN;
2615 size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
2616 if ((tlb->prot & PAGE_VALID) && tlb->size < size)
2617 do_flush_tlbs = 1;
2618 tlb->size = size;
2619 tlb->attr &= ~0x1;
2620 tlb->attr |= (T1 >> 8) & 1;
2621 if (T1 & 0x200) {
2622 tlb->prot |= PAGE_VALID;
2623 } else {
2624 if (tlb->prot & PAGE_VALID) {
2625 tlb->prot &= ~PAGE_VALID;
2626 do_flush_tlbs = 1;
2627 }
2628 }
2629 tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2630 if (do_flush_tlbs)
2631 tlb_flush(env, 1);
2632 break;
2633 case 1:
2634 RPN = T1 & 0xFFFFFC0F;
2635 if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
2636 tlb_flush(env, 1);
2637 tlb->RPN = RPN;
2638 break;
2639 case 2:
2640 tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
2641 tlb->prot = tlb->prot & PAGE_VALID;
2642 if (T1 & 0x1)
2643 tlb->prot |= PAGE_READ << 4;
2644 if (T1 & 0x2)
2645 tlb->prot |= PAGE_WRITE << 4;
2646 if (T1 & 0x4)
2647 tlb->prot |= PAGE_EXEC << 4;
2648 if (T1 & 0x8)
2649 tlb->prot |= PAGE_READ;
2650 if (T1 & 0x10)
2651 tlb->prot |= PAGE_WRITE;
2652 if (T1 & 0x20)
2653 tlb->prot |= PAGE_EXEC;
2654 break;
2655 }
2656 }
2657
2658 void do_440_tlbre (int word)
2659 {
2660 ppcemb_tlb_t *tlb;
2661 int size;
2662
2663 T0 &= 0x3F;
2664 tlb = &env->tlb[T0].tlbe;
2665 switch (word) {
2666 default:
2667 /* Just here to please gcc */
2668 case 0:
2669 T0 = tlb->EPN;
2670 size = booke_page_size_to_tlb(tlb->size);
2671 if (size < 0 || size > 0xF)
2672 size = 1;
2673 T0 |= size << 4;
2674 if (tlb->attr & 0x1)
2675 T0 |= 0x100;
2676 if (tlb->prot & PAGE_VALID)
2677 T0 |= 0x200;
2678 env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2679 env->spr[SPR_440_MMUCR] |= tlb->PID;
2680 break;
2681 case 1:
2682 T0 = tlb->RPN;
2683 break;
2684 case 2:
2685 T0 = tlb->attr & ~0x1;
2686 if (tlb->prot & (PAGE_READ << 4))
2687 T0 |= 0x1;
2688 if (tlb->prot & (PAGE_WRITE << 4))
2689 T0 |= 0x2;
2690 if (tlb->prot & (PAGE_EXEC << 4))
2691 T0 |= 0x4;
2692 if (tlb->prot & PAGE_READ)
2693 T0 |= 0x8;
2694 if (tlb->prot & PAGE_WRITE)
2695 T0 |= 0x10;
2696 if (tlb->prot & PAGE_EXEC)
2697 T0 |= 0x20;
2698 break;
2699 }
2700 }
2701 #endif /* !CONFIG_USER_ONLY */