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