]> Git Repo - qemu.git/blob - target-ppc/op.c
target-ppc: convert software TLB instructions to TCG
[qemu.git] / 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 #if !defined(CONFIG_USER_ONLY)
338 /* tlbia */
339 void OPPROTO op_tlbia (void)
340 {
341     ppc_tlb_invalidate_all(env);
342     RETURN();
343 }
344
345 /* tlbie */
346 void OPPROTO op_tlbie (void)
347 {
348     ppc_tlb_invalidate_one(env, (uint32_t)T0);
349     RETURN();
350 }
351
352 #if defined(TARGET_PPC64)
353 void OPPROTO op_tlbie_64 (void)
354 {
355     ppc_tlb_invalidate_one(env, T0);
356     RETURN();
357 }
358 #endif
359
360 #if defined(TARGET_PPC64)
361 void OPPROTO op_slbia (void)
362 {
363     ppc_slb_invalidate_all(env);
364     RETURN();
365 }
366
367 void OPPROTO op_slbie (void)
368 {
369     ppc_slb_invalidate_one(env, (uint32_t)T0);
370     RETURN();
371 }
372
373 void OPPROTO op_slbie_64 (void)
374 {
375     ppc_slb_invalidate_one(env, T0);
376     RETURN();
377 }
378 #endif
379 #endif
380
381 /* 601 specific */
382 void OPPROTO op_load_601_rtcl (void)
383 {
384     T0 = cpu_ppc601_load_rtcl(env);
385     RETURN();
386 }
387
388 void OPPROTO op_load_601_rtcu (void)
389 {
390     T0 = cpu_ppc601_load_rtcu(env);
391     RETURN();
392 }
393
394 #if !defined(CONFIG_USER_ONLY)
395 void OPPROTO op_store_601_rtcl (void)
396 {
397     cpu_ppc601_store_rtcl(env, T0);
398     RETURN();
399 }
400
401 void OPPROTO op_store_601_rtcu (void)
402 {
403     cpu_ppc601_store_rtcu(env, T0);
404     RETURN();
405 }
406
407 void OPPROTO op_store_hid0_601 (void)
408 {
409     do_store_hid0_601();
410     RETURN();
411 }
412
413 void OPPROTO op_load_601_bat (void)
414 {
415     T0 = env->IBAT[PARAM1][PARAM2];
416     RETURN();
417 }
418
419 void OPPROTO op_store_601_batl (void)
420 {
421     do_store_ibatl_601(env, PARAM1, T0);
422     RETURN();
423 }
424
425 void OPPROTO op_store_601_batu (void)
426 {
427     do_store_ibatu_601(env, PARAM1, T0);
428     RETURN();
429 }
430 #endif /* !defined(CONFIG_USER_ONLY) */
431
432 /* PowerPC 601 specific instructions (POWER bridge) */
433 /* XXX: those micro-ops need tests ! */
434 void OPPROTO op_POWER_abs (void)
435 {
436     if ((int32_t)T0 == INT32_MIN)
437         T0 = INT32_MAX;
438     else if ((int32_t)T0 < 0)
439         T0 = -T0;
440     RETURN();
441 }
442
443 void OPPROTO op_POWER_abso (void)
444 {
445     do_POWER_abso();
446     RETURN();
447 }
448
449 void OPPROTO op_POWER_clcs (void)
450 {
451     do_POWER_clcs();
452     RETURN();
453 }
454
455 void OPPROTO op_POWER_div (void)
456 {
457     do_POWER_div();
458     RETURN();
459 }
460
461 void OPPROTO op_POWER_divo (void)
462 {
463     do_POWER_divo();
464     RETURN();
465 }
466
467 void OPPROTO op_POWER_divs (void)
468 {
469     do_POWER_divs();
470     RETURN();
471 }
472
473 void OPPROTO op_POWER_divso (void)
474 {
475     do_POWER_divso();
476     RETURN();
477 }
478
479 void OPPROTO op_POWER_doz (void)
480 {
481     if ((int32_t)T1 > (int32_t)T0)
482         T0 = T1 - T0;
483     else
484         T0 = 0;
485     RETURN();
486 }
487
488 void OPPROTO op_POWER_dozo (void)
489 {
490     do_POWER_dozo();
491     RETURN();
492 }
493
494 void OPPROTO op_load_xer_cmp (void)
495 {
496     T2 = xer_cmp;
497     RETURN();
498 }
499
500 void OPPROTO op_POWER_maskg (void)
501 {
502     do_POWER_maskg();
503     RETURN();
504 }
505
506 void OPPROTO op_POWER_maskir (void)
507 {
508     T0 = (T0 & ~T2) | (T1 & T2);
509     RETURN();
510 }
511
512 void OPPROTO op_POWER_mul (void)
513 {
514     uint64_t tmp;
515
516     tmp = (uint64_t)T0 * (uint64_t)T1;
517     env->spr[SPR_MQ] = tmp >> 32;
518     T0 = tmp;
519     RETURN();
520 }
521
522 void OPPROTO op_POWER_mulo (void)
523 {
524     do_POWER_mulo();
525     RETURN();
526 }
527
528 void OPPROTO op_POWER_nabs (void)
529 {
530     if (T0 > 0)
531         T0 = -T0;
532     RETURN();
533 }
534
535 void OPPROTO op_POWER_nabso (void)
536 {
537     /* nabs never overflows */
538     if (T0 > 0)
539         T0 = -T0;
540     env->xer &= ~(1 << XER_OV);
541     RETURN();
542 }
543
544 /* XXX: factorise POWER rotates... */
545 void OPPROTO op_POWER_rlmi (void)
546 {
547     T0 = rotl32(T0, T2) & PARAM1;
548     T0 |= T1 & (uint32_t)PARAM2;
549     RETURN();
550 }
551
552 void OPPROTO op_POWER_rrib (void)
553 {
554     T2 &= 0x1FUL;
555     T0 = rotl32(T0 & INT32_MIN, T2);
556     T0 |= T1 & ~rotl32(INT32_MIN, T2);
557     RETURN();
558 }
559
560 void OPPROTO op_POWER_sle (void)
561 {
562     T1 &= 0x1FUL;
563     env->spr[SPR_MQ] = rotl32(T0, T1);
564     T0 = T0 << T1;
565     RETURN();
566 }
567
568 void OPPROTO op_POWER_sleq (void)
569 {
570     uint32_t tmp = env->spr[SPR_MQ];
571
572     T1 &= 0x1FUL;
573     env->spr[SPR_MQ] = rotl32(T0, T1);
574     T0 = T0 << T1;
575     T0 |= tmp >> (32 - T1);
576     RETURN();
577 }
578
579 void OPPROTO op_POWER_sllq (void)
580 {
581     uint32_t msk = UINT32_MAX;
582
583     msk = msk << (T1 & 0x1FUL);
584     if (T1 & 0x20UL)
585         msk = ~msk;
586     T1 &= 0x1FUL;
587     T0 = (T0 << T1) & msk;
588     T0 |= env->spr[SPR_MQ] & ~msk;
589     RETURN();
590 }
591
592 void OPPROTO op_POWER_slq (void)
593 {
594     uint32_t msk = UINT32_MAX, tmp;
595
596     msk = msk << (T1 & 0x1FUL);
597     if (T1 & 0x20UL)
598         msk = ~msk;
599     T1 &= 0x1FUL;
600     tmp = rotl32(T0, T1);
601     T0 = tmp & msk;
602     env->spr[SPR_MQ] = tmp;
603     RETURN();
604 }
605
606 void OPPROTO op_POWER_sraq (void)
607 {
608     env->spr[SPR_MQ] = rotl32(T0, 32 - (T1 & 0x1FUL));
609     if (T1 & 0x20UL)
610         T0 = UINT32_MAX;
611     else
612         T0 = (int32_t)T0 >> T1;
613     RETURN();
614 }
615
616 void OPPROTO op_POWER_sre (void)
617 {
618     T1 &= 0x1FUL;
619     env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
620     T0 = (int32_t)T0 >> T1;
621     RETURN();
622 }
623
624 void OPPROTO op_POWER_srea (void)
625 {
626     T1 &= 0x1FUL;
627     env->spr[SPR_MQ] = T0 >> T1;
628     T0 = (int32_t)T0 >> T1;
629     RETURN();
630 }
631
632 void OPPROTO op_POWER_sreq (void)
633 {
634     uint32_t tmp;
635     int32_t msk;
636
637     T1 &= 0x1FUL;
638     msk = INT32_MIN >> T1;
639     tmp = env->spr[SPR_MQ];
640     env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
641     T0 = T0 >> T1;
642     T0 |= tmp & msk;
643     RETURN();
644 }
645
646 void OPPROTO op_POWER_srlq (void)
647 {
648     uint32_t tmp;
649     int32_t msk;
650
651     msk = INT32_MIN >> (T1 & 0x1FUL);
652     if (T1 & 0x20UL)
653         msk = ~msk;
654     T1 &= 0x1FUL;
655     tmp = env->spr[SPR_MQ];
656     env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
657     T0 = T0 >> T1;
658     T0 &= msk;
659     T0 |= tmp & ~msk;
660     RETURN();
661 }
662
663 void OPPROTO op_POWER_srq (void)
664 {
665     T1 &= 0x1FUL;
666     env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
667     T0 = T0 >> T1;
668     RETURN();
669 }
670
671 /* POWER instructions not implemented in PowerPC 601 */
672 #if !defined(CONFIG_USER_ONLY)
673 void OPPROTO op_POWER_mfsri (void)
674 {
675     T1 = T0 >> 28;
676     T0 = env->sr[T1];
677     RETURN();
678 }
679
680 void OPPROTO op_POWER_rac (void)
681 {
682     do_POWER_rac();
683     RETURN();
684 }
685
686 void OPPROTO op_POWER_rfsvc (void)
687 {
688     do_POWER_rfsvc();
689     RETURN();
690 }
691 #endif
692
693 /* PowerPC 602 specific instruction */
694 #if !defined(CONFIG_USER_ONLY)
695 void OPPROTO op_602_mfrom (void)
696 {
697     do_op_602_mfrom();
698     RETURN();
699 }
700 #endif
701
702 /* PowerPC 4xx specific micro-ops */
703 void OPPROTO op_load_dcr (void)
704 {
705     do_load_dcr();
706     RETURN();
707 }
708
709 void OPPROTO op_store_dcr (void)
710 {
711     do_store_dcr();
712     RETURN();
713 }
714
715 #if !defined(CONFIG_USER_ONLY)
716 /* Return from critical interrupt :
717  * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
718  */
719 void OPPROTO op_40x_rfci (void)
720 {
721     do_40x_rfci();
722     RETURN();
723 }
724
725 void OPPROTO op_rfci (void)
726 {
727     do_rfci();
728     RETURN();
729 }
730
731 void OPPROTO op_rfdi (void)
732 {
733     do_rfdi();
734     RETURN();
735 }
736
737 void OPPROTO op_rfmci (void)
738 {
739     do_rfmci();
740     RETURN();
741 }
742
743 void OPPROTO op_wrte (void)
744 {
745     /* We don't call do_store_msr here as we won't trigger
746      * any special case nor change hflags
747      */
748     T0 &= 1 << MSR_EE;
749     env->msr &= ~(1 << MSR_EE);
750     env->msr |= T0;
751     RETURN();
752 }
753
754 void OPPROTO op_440_tlbre (void)
755 {
756     do_440_tlbre(PARAM1);
757     RETURN();
758 }
759
760 void OPPROTO op_440_tlbsx (void)
761 {
762     T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
763     RETURN();
764 }
765
766 void OPPROTO op_4xx_tlbsx_check (void)
767 {
768     int tmp;
769
770     tmp = xer_so;
771     if ((int)T0 != -1)
772         tmp |= 0x02;
773     env->crf[0] = tmp;
774     RETURN();
775 }
776
777 void OPPROTO op_440_tlbwe (void)
778 {
779     do_440_tlbwe(PARAM1);
780     RETURN();
781 }
782
783 void OPPROTO op_4xx_tlbre_lo (void)
784 {
785     do_4xx_tlbre_lo();
786     RETURN();
787 }
788
789 void OPPROTO op_4xx_tlbre_hi (void)
790 {
791     do_4xx_tlbre_hi();
792     RETURN();
793 }
794
795 void OPPROTO op_4xx_tlbsx (void)
796 {
797     T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
798     RETURN();
799 }
800
801 void OPPROTO op_4xx_tlbwe_lo (void)
802 {
803     do_4xx_tlbwe_lo();
804     RETURN();
805 }
806
807 void OPPROTO op_4xx_tlbwe_hi (void)
808 {
809     do_4xx_tlbwe_hi();
810     RETURN();
811 }
812 #endif
813
814 /* SPR micro-ops */
815 /* 440 specific */
816 void OPPROTO op_440_dlmzb (void)
817 {
818     do_440_dlmzb();
819     RETURN();
820 }
821
822 void OPPROTO op_440_dlmzb_update_Rc (void)
823 {
824     if (T0 == 8)
825         T0 = 0x2;
826     else if (T0 < 4)
827         T0 = 0x4;
828     else
829         T0 = 0x8;
830     RETURN();
831 }
832
833 #if !defined(CONFIG_USER_ONLY)
834 void OPPROTO op_store_pir (void)
835 {
836     env->spr[SPR_PIR] = T0 & 0x0000000FUL;
837     RETURN();
838 }
839
840 void OPPROTO op_load_403_pb (void)
841 {
842     do_load_403_pb(PARAM1);
843     RETURN();
844 }
845
846 void OPPROTO op_store_403_pb (void)
847 {
848     do_store_403_pb(PARAM1);
849     RETURN();
850 }
851
852 void OPPROTO op_load_40x_pit (void)
853 {
854     T0 = load_40x_pit(env);
855     RETURN();
856 }
857
858 void OPPROTO op_store_40x_pit (void)
859 {
860     store_40x_pit(env, T0);
861     RETURN();
862 }
863
864 void OPPROTO op_store_40x_dbcr0 (void)
865 {
866     store_40x_dbcr0(env, T0);
867     RETURN();
868 }
869
870 void OPPROTO op_store_40x_sler (void)
871 {
872     store_40x_sler(env, T0);
873     RETURN();
874 }
875
876 void OPPROTO op_store_booke_tcr (void)
877 {
878     store_booke_tcr(env, T0);
879     RETURN();
880 }
881
882 void OPPROTO op_store_booke_tsr (void)
883 {
884     store_booke_tsr(env, T0);
885     RETURN();
886 }
887 #endif /* !defined(CONFIG_USER_ONLY) */
888
This page took 0.069502 seconds and 4 git commands to generate.