target-ppc: convert exceptions generation to TCG
[qemu] / target-ppc / op.c
1 /*
2  *  PowerPC emulation micro-operations 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
21 //#define DEBUG_OP
22
23 #include "config.h"
24 #include "exec.h"
25 #include "host-utils.h"
26 #include "helper_regs.h"
27 #include "op_helper.h"
28
29 #if !defined(CONFIG_USER_ONLY)
30 /* Segment registers load and store */
31 void OPPROTO op_load_sr (void)
32 {
33     T0 = env->sr[T1];
34     RETURN();
35 }
36
37 void OPPROTO op_store_sr (void)
38 {
39     do_store_sr(env, T1, T0);
40     RETURN();
41 }
42
43 #if defined(TARGET_PPC64)
44 void OPPROTO op_load_slb (void)
45 {
46     T0 = ppc_load_slb(env, T1);
47     RETURN();
48 }
49
50 void OPPROTO op_store_slb (void)
51 {
52     ppc_store_slb(env, T1, T0);
53     RETURN();
54 }
55 #endif /* defined(TARGET_PPC64) */
56
57 void OPPROTO op_load_sdr1 (void)
58 {
59     T0 = env->sdr1;
60     RETURN();
61 }
62
63 void OPPROTO op_store_sdr1 (void)
64 {
65     do_store_sdr1(env, T0);
66     RETURN();
67 }
68
69 #if defined (TARGET_PPC64)
70 void OPPROTO op_load_asr (void)
71 {
72     T0 = env->asr;
73     RETURN();
74 }
75
76 void OPPROTO op_store_asr (void)
77 {
78     ppc_store_asr(env, T0);
79     RETURN();
80 }
81 #endif
82
83 void OPPROTO op_load_msr (void)
84 {
85     T0 = env->msr;
86     RETURN();
87 }
88
89 void OPPROTO op_store_msr (void)
90 {
91     do_store_msr();
92     RETURN();
93 }
94
95 #if defined (TARGET_PPC64)
96 void OPPROTO op_store_msr_32 (void)
97 {
98     T0 = (env->msr & ~0xFFFFFFFFULL) | (T0 & 0xFFFFFFFF);
99     do_store_msr();
100     RETURN();
101 }
102 #endif
103
104 void OPPROTO op_update_riee (void)
105 {
106     /* We don't call do_store_msr here as we won't trigger
107      * any special case nor change hflags
108      */
109     T0 &= (1 << MSR_RI) | (1 << MSR_EE);
110     env->msr &= ~(1 << MSR_RI) | (1 << MSR_EE);
111     env->msr |= T0;
112     RETURN();
113 }
114 #endif
115
116 /* SPR */
117 void OPPROTO op_load_spr (void)
118 {
119     T0 = env->spr[PARAM1];
120     RETURN();
121 }
122
123 void OPPROTO op_store_spr (void)
124 {
125     env->spr[PARAM1] = T0;
126     RETURN();
127 }
128
129 void OPPROTO op_load_dump_spr (void)
130 {
131     T0 = ppc_load_dump_spr(PARAM1);
132     RETURN();
133 }
134
135 void OPPROTO op_store_dump_spr (void)
136 {
137     ppc_store_dump_spr(PARAM1, T0);
138     RETURN();
139 }
140
141 void OPPROTO op_mask_spr (void)
142 {
143     env->spr[PARAM1] &= ~T0;
144     RETURN();
145 }
146
147 void OPPROTO op_load_tbl (void)
148 {
149     T0 = cpu_ppc_load_tbl(env);
150     RETURN();
151 }
152
153 void OPPROTO op_load_tbu (void)
154 {
155     T0 = cpu_ppc_load_tbu(env);
156     RETURN();
157 }
158
159 void OPPROTO op_load_atbl (void)
160 {
161     T0 = cpu_ppc_load_atbl(env);
162     RETURN();
163 }
164
165 void OPPROTO op_load_atbu (void)
166 {
167     T0 = cpu_ppc_load_atbu(env);
168     RETURN();
169 }
170
171 #if !defined(CONFIG_USER_ONLY)
172 void OPPROTO op_store_tbl (void)
173 {
174     cpu_ppc_store_tbl(env, T0);
175     RETURN();
176 }
177
178 void OPPROTO op_store_tbu (void)
179 {
180     cpu_ppc_store_tbu(env, T0);
181     RETURN();
182 }
183
184 void OPPROTO op_store_atbl (void)
185 {
186     cpu_ppc_store_atbl(env, T0);
187     RETURN();
188 }
189
190 void OPPROTO op_store_atbu (void)
191 {
192     cpu_ppc_store_atbu(env, T0);
193     RETURN();
194 }
195
196 void OPPROTO op_load_decr (void)
197 {
198     T0 = cpu_ppc_load_decr(env);
199     RETURN();
200 }
201
202 void OPPROTO op_store_decr (void)
203 {
204     cpu_ppc_store_decr(env, T0);
205     RETURN();
206 }
207
208 void OPPROTO op_load_ibat (void)
209 {
210     T0 = env->IBAT[PARAM1][PARAM2];
211     RETURN();
212 }
213
214 void OPPROTO op_store_ibatu (void)
215 {
216     do_store_ibatu(env, PARAM1, T0);
217     RETURN();
218 }
219
220 void OPPROTO op_store_ibatl (void)
221 {
222 #if 1
223     env->IBAT[1][PARAM1] = T0;
224 #else
225     do_store_ibatl(env, PARAM1, T0);
226 #endif
227     RETURN();
228 }
229
230 void OPPROTO op_load_dbat (void)
231 {
232     T0 = env->DBAT[PARAM1][PARAM2];
233     RETURN();
234 }
235
236 void OPPROTO op_store_dbatu (void)
237 {
238     do_store_dbatu(env, PARAM1, T0);
239     RETURN();
240 }
241
242 void OPPROTO op_store_dbatl (void)
243 {
244 #if 1
245     env->DBAT[1][PARAM1] = T0;
246 #else
247     do_store_dbatl(env, PARAM1, T0);
248 #endif
249     RETURN();
250 }
251 #endif /* !defined(CONFIG_USER_ONLY) */
252
253 /***                             Integer shift                             ***/
254 void OPPROTO op_srli_T1 (void)
255 {
256     T1 = (uint32_t)T1 >> PARAM1;
257     RETURN();
258 }
259
260 /* Load and store */
261 #define MEMSUFFIX _raw
262 #include "op_helper.h"
263 #include "op_mem.h"
264 #if !defined(CONFIG_USER_ONLY)
265 #define MEMSUFFIX _user
266 #include "op_helper.h"
267 #include "op_mem.h"
268 #define MEMSUFFIX _kernel
269 #include "op_helper.h"
270 #include "op_mem.h"
271 #define MEMSUFFIX _hypv
272 #include "op_helper.h"
273 #include "op_mem.h"
274 #endif
275
276 /* Special op to check and maybe clear reservation */
277 void OPPROTO op_check_reservation (void)
278 {
279     if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
280         env->reserve = (target_ulong)-1ULL;
281     RETURN();
282 }
283
284 #if defined(TARGET_PPC64)
285 void OPPROTO op_check_reservation_64 (void)
286 {
287     if ((uint64_t)env->reserve == (uint64_t)(T0 & ~0x00000003))
288         env->reserve = (target_ulong)-1ULL;
289     RETURN();
290 }
291 #endif
292
293 void OPPROTO op_wait (void)
294 {
295     env->halted = 1;
296     RETURN();
297 }
298
299 /* Return from interrupt */
300 #if !defined(CONFIG_USER_ONLY)
301 void OPPROTO op_rfi (void)
302 {
303     do_rfi();
304     RETURN();
305 }
306
307 #if defined(TARGET_PPC64)
308 void OPPROTO op_rfid (void)
309 {
310     do_rfid();
311     RETURN();
312 }
313
314 void OPPROTO op_hrfid (void)
315 {
316     do_hrfid();
317     RETURN();
318 }
319 #endif
320
321 /* Exception vectors */
322 void OPPROTO op_store_excp_prefix (void)
323 {
324     T0 &= env->ivpr_mask;
325     env->excp_prefix = T0;
326     RETURN();
327 }
328
329 void OPPROTO op_store_excp_vector (void)
330 {
331     T0 &= env->ivor_mask;
332     env->excp_vectors[PARAM1] = T0;
333     RETURN();
334 }
335 #endif
336
337 /* Trap word */
338 void OPPROTO op_tw (void)
339 {
340     do_tw(PARAM1);
341     RETURN();
342 }
343
344 #if defined(TARGET_PPC64)
345 void OPPROTO op_td (void)
346 {
347     do_td(PARAM1);
348     RETURN();
349 }
350 #endif
351
352 #if !defined(CONFIG_USER_ONLY)
353 /* tlbia */
354 void OPPROTO op_tlbia (void)
355 {
356     ppc_tlb_invalidate_all(env);
357     RETURN();
358 }
359
360 /* tlbie */
361 void OPPROTO op_tlbie (void)
362 {
363     ppc_tlb_invalidate_one(env, (uint32_t)T0);
364     RETURN();
365 }
366
367 #if defined(TARGET_PPC64)
368 void OPPROTO op_tlbie_64 (void)
369 {
370     ppc_tlb_invalidate_one(env, T0);
371     RETURN();
372 }
373 #endif
374
375 #if defined(TARGET_PPC64)
376 void OPPROTO op_slbia (void)
377 {
378     ppc_slb_invalidate_all(env);
379     RETURN();
380 }
381
382 void OPPROTO op_slbie (void)
383 {
384     ppc_slb_invalidate_one(env, (uint32_t)T0);
385     RETURN();
386 }
387
388 void OPPROTO op_slbie_64 (void)
389 {
390     ppc_slb_invalidate_one(env, T0);
391     RETURN();
392 }
393 #endif
394 #endif
395
396 #if !defined(CONFIG_USER_ONLY)
397 /* PowerPC 602/603/755 software TLB load instructions */
398 void OPPROTO op_6xx_tlbld (void)
399 {
400     do_load_6xx_tlb(0);
401     RETURN();
402 }
403
404 void OPPROTO op_6xx_tlbli (void)
405 {
406     do_load_6xx_tlb(1);
407     RETURN();
408 }
409
410 /* PowerPC 74xx software TLB load instructions */
411 void OPPROTO op_74xx_tlbld (void)
412 {
413     do_load_74xx_tlb(0);
414     RETURN();
415 }
416
417 void OPPROTO op_74xx_tlbli (void)
418 {
419     do_load_74xx_tlb(1);
420     RETURN();
421 }
422 #endif
423
424 /* 601 specific */
425 void OPPROTO op_load_601_rtcl (void)
426 {
427     T0 = cpu_ppc601_load_rtcl(env);
428     RETURN();
429 }
430
431 void OPPROTO op_load_601_rtcu (void)
432 {
433     T0 = cpu_ppc601_load_rtcu(env);
434     RETURN();
435 }
436
437 #if !defined(CONFIG_USER_ONLY)
438 void OPPROTO op_store_601_rtcl (void)
439 {
440     cpu_ppc601_store_rtcl(env, T0);
441     RETURN();
442 }
443
444 void OPPROTO op_store_601_rtcu (void)
445 {
446     cpu_ppc601_store_rtcu(env, T0);
447     RETURN();
448 }
449
450 void OPPROTO op_store_hid0_601 (void)
451 {
452     do_store_hid0_601();
453     RETURN();
454 }
455
456 void OPPROTO op_load_601_bat (void)
457 {
458     T0 = env->IBAT[PARAM1][PARAM2];
459     RETURN();
460 }
461
462 void OPPROTO op_store_601_batl (void)
463 {
464     do_store_ibatl_601(env, PARAM1, T0);
465     RETURN();
466 }
467
468 void OPPROTO op_store_601_batu (void)
469 {
470     do_store_ibatu_601(env, PARAM1, T0);
471     RETURN();
472 }
473 #endif /* !defined(CONFIG_USER_ONLY) */
474
475 /* PowerPC 601 specific instructions (POWER bridge) */
476 /* XXX: those micro-ops need tests ! */
477 void OPPROTO op_POWER_abs (void)
478 {
479     if ((int32_t)T0 == INT32_MIN)
480         T0 = INT32_MAX;
481     else if ((int32_t)T0 < 0)
482         T0 = -T0;
483     RETURN();
484 }
485
486 void OPPROTO op_POWER_abso (void)
487 {
488     do_POWER_abso();
489     RETURN();
490 }
491
492 void OPPROTO op_POWER_clcs (void)
493 {
494     do_POWER_clcs();
495     RETURN();
496 }
497
498 void OPPROTO op_POWER_div (void)
499 {
500     do_POWER_div();
501     RETURN();
502 }
503
504 void OPPROTO op_POWER_divo (void)
505 {
506     do_POWER_divo();
507     RETURN();
508 }
509
510 void OPPROTO op_POWER_divs (void)
511 {
512     do_POWER_divs();
513     RETURN();
514 }
515
516 void OPPROTO op_POWER_divso (void)
517 {
518     do_POWER_divso();
519     RETURN();
520 }
521
522 void OPPROTO op_POWER_doz (void)
523 {
524     if ((int32_t)T1 > (int32_t)T0)
525         T0 = T1 - T0;
526     else
527         T0 = 0;
528     RETURN();
529 }
530
531 void OPPROTO op_POWER_dozo (void)
532 {
533     do_POWER_dozo();
534     RETURN();
535 }
536
537 void OPPROTO op_load_xer_cmp (void)
538 {
539     T2 = xer_cmp;
540     RETURN();
541 }
542
543 void OPPROTO op_POWER_maskg (void)
544 {
545     do_POWER_maskg();
546     RETURN();
547 }
548
549 void OPPROTO op_POWER_maskir (void)
550 {
551     T0 = (T0 & ~T2) | (T1 & T2);
552     RETURN();
553 }
554
555 void OPPROTO op_POWER_mul (void)
556 {
557     uint64_t tmp;
558
559     tmp = (uint64_t)T0 * (uint64_t)T1;
560     env->spr[SPR_MQ] = tmp >> 32;
561     T0 = tmp;
562     RETURN();
563 }
564
565 void OPPROTO op_POWER_mulo (void)
566 {
567     do_POWER_mulo();
568     RETURN();
569 }
570
571 void OPPROTO op_POWER_nabs (void)
572 {
573     if (T0 > 0)
574         T0 = -T0;
575     RETURN();
576 }
577
578 void OPPROTO op_POWER_nabso (void)
579 {
580     /* nabs never overflows */
581     if (T0 > 0)
582         T0 = -T0;
583     env->xer &= ~(1 << XER_OV);
584     RETURN();
585 }
586
587 /* XXX: factorise POWER rotates... */
588 void OPPROTO op_POWER_rlmi (void)
589 {
590     T0 = rotl32(T0, T2) & PARAM1;
591     T0 |= T1 & (uint32_t)PARAM2;
592     RETURN();
593 }
594
595 void OPPROTO op_POWER_rrib (void)
596 {
597     T2 &= 0x1FUL;
598     T0 = rotl32(T0 & INT32_MIN, T2);
599     T0 |= T1 & ~rotl32(INT32_MIN, T2);
600     RETURN();
601 }
602
603 void OPPROTO op_POWER_sle (void)
604 {
605     T1 &= 0x1FUL;
606     env->spr[SPR_MQ] = rotl32(T0, T1);
607     T0 = T0 << T1;
608     RETURN();
609 }
610
611 void OPPROTO op_POWER_sleq (void)
612 {
613     uint32_t tmp = env->spr[SPR_MQ];
614
615     T1 &= 0x1FUL;
616     env->spr[SPR_MQ] = rotl32(T0, T1);
617     T0 = T0 << T1;
618     T0 |= tmp >> (32 - T1);
619     RETURN();
620 }
621
622 void OPPROTO op_POWER_sllq (void)
623 {
624     uint32_t msk = UINT32_MAX;
625
626     msk = msk << (T1 & 0x1FUL);
627     if (T1 & 0x20UL)
628         msk = ~msk;
629     T1 &= 0x1FUL;
630     T0 = (T0 << T1) & msk;
631     T0 |= env->spr[SPR_MQ] & ~msk;
632     RETURN();
633 }
634
635 void OPPROTO op_POWER_slq (void)
636 {
637     uint32_t msk = UINT32_MAX, tmp;
638
639     msk = msk << (T1 & 0x1FUL);
640     if (T1 & 0x20UL)
641         msk = ~msk;
642     T1 &= 0x1FUL;
643     tmp = rotl32(T0, T1);
644     T0 = tmp & msk;
645     env->spr[SPR_MQ] = tmp;
646     RETURN();
647 }
648
649 void OPPROTO op_POWER_sraq (void)
650 {
651     env->spr[SPR_MQ] = rotl32(T0, 32 - (T1 & 0x1FUL));
652     if (T1 & 0x20UL)
653         T0 = UINT32_MAX;
654     else
655         T0 = (int32_t)T0 >> T1;
656     RETURN();
657 }
658
659 void OPPROTO op_POWER_sre (void)
660 {
661     T1 &= 0x1FUL;
662     env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
663     T0 = (int32_t)T0 >> T1;
664     RETURN();
665 }
666
667 void OPPROTO op_POWER_srea (void)
668 {
669     T1 &= 0x1FUL;
670     env->spr[SPR_MQ] = T0 >> T1;
671     T0 = (int32_t)T0 >> T1;
672     RETURN();
673 }
674
675 void OPPROTO op_POWER_sreq (void)
676 {
677     uint32_t tmp;
678     int32_t msk;
679
680     T1 &= 0x1FUL;
681     msk = INT32_MIN >> T1;
682     tmp = env->spr[SPR_MQ];
683     env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
684     T0 = T0 >> T1;
685     T0 |= tmp & msk;
686     RETURN();
687 }
688
689 void OPPROTO op_POWER_srlq (void)
690 {
691     uint32_t tmp;
692     int32_t msk;
693
694     msk = INT32_MIN >> (T1 & 0x1FUL);
695     if (T1 & 0x20UL)
696         msk = ~msk;
697     T1 &= 0x1FUL;
698     tmp = env->spr[SPR_MQ];
699     env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
700     T0 = T0 >> T1;
701     T0 &= msk;
702     T0 |= tmp & ~msk;
703     RETURN();
704 }
705
706 void OPPROTO op_POWER_srq (void)
707 {
708     T1 &= 0x1FUL;
709     env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
710     T0 = T0 >> T1;
711     RETURN();
712 }
713
714 /* POWER instructions not implemented in PowerPC 601 */
715 #if !defined(CONFIG_USER_ONLY)
716 void OPPROTO op_POWER_mfsri (void)
717 {
718     T1 = T0 >> 28;
719     T0 = env->sr[T1];
720     RETURN();
721 }
722
723 void OPPROTO op_POWER_rac (void)
724 {
725     do_POWER_rac();
726     RETURN();
727 }
728
729 void OPPROTO op_POWER_rfsvc (void)
730 {
731     do_POWER_rfsvc();
732     RETURN();
733 }
734 #endif
735
736 /* PowerPC 602 specific instruction */
737 #if !defined(CONFIG_USER_ONLY)
738 void OPPROTO op_602_mfrom (void)
739 {
740     do_op_602_mfrom();
741     RETURN();
742 }
743 #endif
744
745 /* PowerPC 4xx specific micro-ops */
746 void OPPROTO op_load_dcr (void)
747 {
748     do_load_dcr();
749     RETURN();
750 }
751
752 void OPPROTO op_store_dcr (void)
753 {
754     do_store_dcr();
755     RETURN();
756 }
757
758 #if !defined(CONFIG_USER_ONLY)
759 /* Return from critical interrupt :
760  * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
761  */
762 void OPPROTO op_40x_rfci (void)
763 {
764     do_40x_rfci();
765     RETURN();
766 }
767
768 void OPPROTO op_rfci (void)
769 {
770     do_rfci();
771     RETURN();
772 }
773
774 void OPPROTO op_rfdi (void)
775 {
776     do_rfdi();
777     RETURN();
778 }
779
780 void OPPROTO op_rfmci (void)
781 {
782     do_rfmci();
783     RETURN();
784 }
785
786 void OPPROTO op_wrte (void)
787 {
788     /* We don't call do_store_msr here as we won't trigger
789      * any special case nor change hflags
790      */
791     T0 &= 1 << MSR_EE;
792     env->msr &= ~(1 << MSR_EE);
793     env->msr |= T0;
794     RETURN();
795 }
796
797 void OPPROTO op_440_tlbre (void)
798 {
799     do_440_tlbre(PARAM1);
800     RETURN();
801 }
802
803 void OPPROTO op_440_tlbsx (void)
804 {
805     T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
806     RETURN();
807 }
808
809 void OPPROTO op_4xx_tlbsx_check (void)
810 {
811     int tmp;
812
813     tmp = xer_so;
814     if ((int)T0 != -1)
815         tmp |= 0x02;
816     env->crf[0] = tmp;
817     RETURN();
818 }
819
820 void OPPROTO op_440_tlbwe (void)
821 {
822     do_440_tlbwe(PARAM1);
823     RETURN();
824 }
825
826 void OPPROTO op_4xx_tlbre_lo (void)
827 {
828     do_4xx_tlbre_lo();
829     RETURN();
830 }
831
832 void OPPROTO op_4xx_tlbre_hi (void)
833 {
834     do_4xx_tlbre_hi();
835     RETURN();
836 }
837
838 void OPPROTO op_4xx_tlbsx (void)
839 {
840     T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
841     RETURN();
842 }
843
844 void OPPROTO op_4xx_tlbwe_lo (void)
845 {
846     do_4xx_tlbwe_lo();
847     RETURN();
848 }
849
850 void OPPROTO op_4xx_tlbwe_hi (void)
851 {
852     do_4xx_tlbwe_hi();
853     RETURN();
854 }
855 #endif
856
857 /* SPR micro-ops */
858 /* 440 specific */
859 void OPPROTO op_440_dlmzb (void)
860 {
861     do_440_dlmzb();
862     RETURN();
863 }
864
865 void OPPROTO op_440_dlmzb_update_Rc (void)
866 {
867     if (T0 == 8)
868         T0 = 0x2;
869     else if (T0 < 4)
870         T0 = 0x4;
871     else
872         T0 = 0x8;
873     RETURN();
874 }
875
876 #if !defined(CONFIG_USER_ONLY)
877 void OPPROTO op_store_pir (void)
878 {
879     env->spr[SPR_PIR] = T0 & 0x0000000FUL;
880     RETURN();
881 }
882
883 void OPPROTO op_load_403_pb (void)
884 {
885     do_load_403_pb(PARAM1);
886     RETURN();
887 }
888
889 void OPPROTO op_store_403_pb (void)
890 {
891     do_store_403_pb(PARAM1);
892     RETURN();
893 }
894
895 void OPPROTO op_load_40x_pit (void)
896 {
897     T0 = load_40x_pit(env);
898     RETURN();
899 }
900
901 void OPPROTO op_store_40x_pit (void)
902 {
903     store_40x_pit(env, T0);
904     RETURN();
905 }
906
907 void OPPROTO op_store_40x_dbcr0 (void)
908 {
909     store_40x_dbcr0(env, T0);
910     RETURN();
911 }
912
913 void OPPROTO op_store_40x_sler (void)
914 {
915     store_40x_sler(env, T0);
916     RETURN();
917 }
918
919 void OPPROTO op_store_booke_tcr (void)
920 {
921     store_booke_tcr(env, T0);
922     RETURN();
923 }
924
925 void OPPROTO op_store_booke_tsr (void)
926 {
927     store_booke_tsr(env, T0);
928     RETURN();
929 }
930 #endif /* !defined(CONFIG_USER_ONLY) */
931
932 /* SPE extension */
933 void OPPROTO op_splatw_T1_64 (void)
934 {
935     T1_64 = (T1_64 << 32) | (T1_64 & 0x00000000FFFFFFFFULL);
936     RETURN();
937 }
938
939 void OPPROTO op_extsh_T1_64 (void)
940 {
941     T1_64 = (int32_t)((int16_t)T1_64);
942     RETURN();
943 }
944
945 void OPPROTO op_sli16_T1_64 (void)
946 {
947     T1_64 = T1_64 << 16;
948     RETURN();
949 }
950
951 void OPPROTO op_sli32_T1_64 (void)
952 {
953     T1_64 = T1_64 << 32;
954     RETURN();
955 }
956
957 void OPPROTO op_srli32_T1_64 (void)
958 {
959     T1_64 = T1_64 >> 32;
960     RETURN();
961 }
962
963 void OPPROTO op_evfssub (void)
964 {
965     do_evfssub();
966     RETURN();
967 }
968
969 void OPPROTO op_evfsadd (void)
970 {
971     do_evfsadd();
972     RETURN();
973 }
974
975 void OPPROTO op_evfsnabs (void)
976 {
977     do_evfsnabs();
978     RETURN();
979 }
980
981 void OPPROTO op_evfsabs (void)
982 {
983     do_evfsabs();
984     RETURN();
985 }
986
987 void OPPROTO op_evfsneg (void)
988 {
989     do_evfsneg();
990     RETURN();
991 }
992
993 void OPPROTO op_evfsdiv (void)
994 {
995     do_evfsdiv();
996     RETURN();
997 }
998
999 void OPPROTO op_evfsmul (void)
1000 {
1001     do_evfsmul();
1002     RETURN();
1003 }
1004
1005 void OPPROTO op_evfscmplt (void)
1006 {
1007     do_evfscmplt();
1008     RETURN();
1009 }
1010
1011 void OPPROTO op_evfscmpgt (void)
1012 {
1013     do_evfscmpgt();
1014     RETURN();
1015 }
1016
1017 void OPPROTO op_evfscmpeq (void)
1018 {
1019     do_evfscmpeq();
1020     RETURN();
1021 }
1022
1023 void OPPROTO op_evfscfsi (void)
1024 {
1025     do_evfscfsi();
1026     RETURN();
1027 }
1028
1029 void OPPROTO op_evfscfui (void)
1030 {
1031     do_evfscfui();
1032     RETURN();
1033 }
1034
1035 void OPPROTO op_evfscfsf (void)
1036 {
1037     do_evfscfsf();
1038     RETURN();
1039 }
1040
1041 void OPPROTO op_evfscfuf (void)
1042 {
1043     do_evfscfuf();
1044     RETURN();
1045 }
1046
1047 void OPPROTO op_evfsctsi (void)
1048 {
1049     do_evfsctsi();
1050     RETURN();
1051 }
1052
1053 void OPPROTO op_evfsctui (void)
1054 {
1055     do_evfsctui();
1056     RETURN();
1057 }
1058
1059 void OPPROTO op_evfsctsf (void)
1060 {
1061     do_evfsctsf();
1062     RETURN();
1063 }
1064
1065 void OPPROTO op_evfsctuf (void)
1066 {
1067     do_evfsctuf();
1068     RETURN();
1069 }
1070
1071 void OPPROTO op_evfsctuiz (void)
1072 {
1073     do_evfsctuiz();
1074     RETURN();
1075 }
1076
1077 void OPPROTO op_evfsctsiz (void)
1078 {
1079     do_evfsctsiz();
1080     RETURN();
1081 }
1082
1083 void OPPROTO op_evfststlt (void)
1084 {
1085     do_evfststlt();
1086     RETURN();
1087 }
1088
1089 void OPPROTO op_evfststgt (void)
1090 {
1091     do_evfststgt();
1092     RETURN();
1093 }
1094
1095 void OPPROTO op_evfststeq (void)
1096 {
1097     do_evfststeq();
1098     RETURN();
1099 }
1100
1101 void OPPROTO op_efssub (void)
1102 {
1103     T0_64 = _do_efssub(T0_64, T1_64);
1104     RETURN();
1105 }
1106
1107 void OPPROTO op_efsadd (void)
1108 {
1109     T0_64 = _do_efsadd(T0_64, T1_64);
1110     RETURN();
1111 }
1112
1113 void OPPROTO op_efsnabs (void)
1114 {
1115     T0_64 = _do_efsnabs(T0_64);
1116     RETURN();
1117 }
1118
1119 void OPPROTO op_efsabs (void)
1120 {
1121     T0_64 = _do_efsabs(T0_64);
1122     RETURN();
1123 }
1124
1125 void OPPROTO op_efsneg (void)
1126 {
1127     T0_64 = _do_efsneg(T0_64);
1128     RETURN();
1129 }
1130
1131 void OPPROTO op_efsdiv (void)
1132 {
1133     T0_64 = _do_efsdiv(T0_64, T1_64);
1134     RETURN();
1135 }
1136
1137 void OPPROTO op_efsmul (void)
1138 {
1139     T0_64 = _do_efsmul(T0_64, T1_64);
1140     RETURN();
1141 }
1142
1143 void OPPROTO op_efscmplt (void)
1144 {
1145     do_efscmplt();
1146     RETURN();
1147 }
1148
1149 void OPPROTO op_efscmpgt (void)
1150 {
1151     do_efscmpgt();
1152     RETURN();
1153 }
1154
1155 void OPPROTO op_efscfd (void)
1156 {
1157     do_efscfd();
1158     RETURN();
1159 }
1160
1161 void OPPROTO op_efscmpeq (void)
1162 {
1163     do_efscmpeq();
1164     RETURN();
1165 }
1166
1167 void OPPROTO op_efscfsi (void)
1168 {
1169     do_efscfsi();
1170     RETURN();
1171 }
1172
1173 void OPPROTO op_efscfui (void)
1174 {
1175     do_efscfui();
1176     RETURN();
1177 }
1178
1179 void OPPROTO op_efscfsf (void)
1180 {
1181     do_efscfsf();
1182     RETURN();
1183 }
1184
1185 void OPPROTO op_efscfuf (void)
1186 {
1187     do_efscfuf();
1188     RETURN();
1189 }
1190
1191 void OPPROTO op_efsctsi (void)
1192 {
1193     do_efsctsi();
1194     RETURN();
1195 }
1196
1197 void OPPROTO op_efsctui (void)
1198 {
1199     do_efsctui();
1200     RETURN();
1201 }
1202
1203 void OPPROTO op_efsctsf (void)
1204 {
1205     do_efsctsf();
1206     RETURN();
1207 }
1208
1209 void OPPROTO op_efsctuf (void)
1210 {
1211     do_efsctuf();
1212     RETURN();
1213 }
1214
1215 void OPPROTO op_efsctsiz (void)
1216 {
1217     do_efsctsiz();
1218     RETURN();
1219 }
1220
1221 void OPPROTO op_efsctuiz (void)
1222 {
1223     do_efsctuiz();
1224     RETURN();
1225 }
1226
1227 void OPPROTO op_efststlt (void)
1228 {
1229     T0 = _do_efststlt(T0_64, T1_64);
1230     RETURN();
1231 }
1232
1233 void OPPROTO op_efststgt (void)
1234 {
1235     T0 = _do_efststgt(T0_64, T1_64);
1236     RETURN();
1237 }
1238
1239 void OPPROTO op_efststeq (void)
1240 {
1241     T0 = _do_efststeq(T0_64, T1_64);
1242     RETURN();
1243 }
1244
1245 void OPPROTO op_efdsub (void)
1246 {
1247     CPU_DoubleU u1, u2;
1248     u1.ll = T0_64;
1249     u2.ll = T1_64;
1250     u1.d = float64_sub(u1.d, u2.d, &env->spe_status);
1251     T0_64 = u1.ll;
1252     RETURN();
1253 }
1254
1255 void OPPROTO op_efdadd (void)
1256 {
1257     CPU_DoubleU u1, u2;
1258     u1.ll = T0_64;
1259     u2.ll = T1_64;
1260     u1.d = float64_add(u1.d, u2.d, &env->spe_status);
1261     T0_64 = u1.ll;
1262     RETURN();
1263 }
1264
1265 void OPPROTO op_efdcfsid (void)
1266 {
1267     do_efdcfsi();
1268     RETURN();
1269 }
1270
1271 void OPPROTO op_efdcfuid (void)
1272 {
1273     do_efdcfui();
1274     RETURN();
1275 }
1276
1277 void OPPROTO op_efdnabs (void)
1278 {
1279     T0_64 |= 0x8000000000000000ULL;
1280     RETURN();
1281 }
1282
1283 void OPPROTO op_efdabs (void)
1284 {
1285     T0_64 &= ~0x8000000000000000ULL;
1286     RETURN();
1287 }
1288
1289 void OPPROTO op_efdneg (void)
1290 {
1291     T0_64 ^= 0x8000000000000000ULL;
1292     RETURN();
1293 }
1294
1295 void OPPROTO op_efddiv (void)
1296 {
1297     CPU_DoubleU u1, u2;
1298     u1.ll = T0_64;
1299     u2.ll = T1_64;
1300     u1.d = float64_div(u1.d, u2.d, &env->spe_status);
1301     T0_64 = u1.ll;
1302     RETURN();
1303 }
1304
1305 void OPPROTO op_efdmul (void)
1306 {
1307     CPU_DoubleU u1, u2;
1308     u1.ll = T0_64;
1309     u2.ll = T1_64;
1310     u1.d = float64_mul(u1.d, u2.d, &env->spe_status);
1311     T0_64 = u1.ll;
1312     RETURN();
1313 }
1314
1315 void OPPROTO op_efdctsidz (void)
1316 {
1317     do_efdctsiz();
1318     RETURN();
1319 }
1320
1321 void OPPROTO op_efdctuidz (void)
1322 {
1323     do_efdctuiz();
1324     RETURN();
1325 }
1326
1327 void OPPROTO op_efdcmplt (void)
1328 {
1329     do_efdcmplt();
1330     RETURN();
1331 }
1332
1333 void OPPROTO op_efdcmpgt (void)
1334 {
1335     do_efdcmpgt();
1336     RETURN();
1337 }
1338
1339 void OPPROTO op_efdcfs (void)
1340 {
1341     do_efdcfs();
1342     RETURN();
1343 }
1344
1345 void OPPROTO op_efdcmpeq (void)
1346 {
1347     do_efdcmpeq();
1348     RETURN();
1349 }
1350
1351 void OPPROTO op_efdcfsi (void)
1352 {
1353     do_efdcfsi();
1354     RETURN();
1355 }
1356
1357 void OPPROTO op_efdcfui (void)
1358 {
1359     do_efdcfui();
1360     RETURN();
1361 }
1362
1363 void OPPROTO op_efdcfsf (void)
1364 {
1365     do_efdcfsf();
1366     RETURN();
1367 }
1368
1369 void OPPROTO op_efdcfuf (void)
1370 {
1371     do_efdcfuf();
1372     RETURN();
1373 }
1374
1375 void OPPROTO op_efdctsi (void)
1376 {
1377     do_efdctsi();
1378     RETURN();
1379 }
1380
1381 void OPPROTO op_efdctui (void)
1382 {
1383     do_efdctui();
1384     RETURN();
1385 }
1386
1387 void OPPROTO op_efdctsf (void)
1388 {
1389     do_efdctsf();
1390     RETURN();
1391 }
1392
1393 void OPPROTO op_efdctuf (void)
1394 {
1395     do_efdctuf();
1396     RETURN();
1397 }
1398
1399 void OPPROTO op_efdctuiz (void)
1400 {
1401     do_efdctuiz();
1402     RETURN();
1403 }
1404
1405 void OPPROTO op_efdctsiz (void)
1406 {
1407     do_efdctsiz();
1408     RETURN();
1409 }
1410
1411 void OPPROTO op_efdtstlt (void)
1412 {
1413     T0 = _do_efdtstlt(T0_64, T1_64);
1414     RETURN();
1415 }
1416
1417 void OPPROTO op_efdtstgt (void)
1418 {
1419     T0 = _do_efdtstgt(T0_64, T1_64);
1420     RETURN();
1421 }
1422
1423 void OPPROTO op_efdtsteq (void)
1424 {
1425     T0 = _do_efdtsteq(T0_64, T1_64);
1426     RETURN();
1427 }