Do not allow PowerPC CPU restart after entering checkstop mode.
[qemu] / target-alpha / op.c
1 /*
2  *  Alpha emulation cpu micro-operations for qemu.
3  *
4  *  Copyright (c) 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
26 #include "op_helper.h"
27
28 #define REG 0
29 #include "op_template.h"
30
31 #define REG 1
32 #include "op_template.h"
33
34 #define REG 2
35 #include "op_template.h"
36
37 #define REG 3
38 #include "op_template.h"
39
40 #define REG 4
41 #include "op_template.h"
42
43 #define REG 5
44 #include "op_template.h"
45
46 #define REG 6
47 #include "op_template.h"
48
49 #define REG 7
50 #include "op_template.h"
51
52 #define REG 8
53 #include "op_template.h"
54
55 #define REG 9
56 #include "op_template.h"
57
58 #define REG 10
59 #include "op_template.h"
60
61 #define REG 11
62 #include "op_template.h"
63
64 #define REG 12
65 #include "op_template.h"
66
67 #define REG 13
68 #include "op_template.h"
69
70 #define REG 14
71 #include "op_template.h"
72
73 #define REG 15
74 #include "op_template.h"
75
76 #define REG 16
77 #include "op_template.h"
78
79 #define REG 17
80 #include "op_template.h"
81
82 #define REG 18
83 #include "op_template.h"
84
85 #define REG 19
86 #include "op_template.h"
87
88 #define REG 20
89 #include "op_template.h"
90
91 #define REG 21
92 #include "op_template.h"
93
94 #define REG 22
95 #include "op_template.h"
96
97 #define REG 23
98 #include "op_template.h"
99
100 #define REG 24
101 #include "op_template.h"
102
103 #define REG 25
104 #include "op_template.h"
105
106 #define REG 26
107 #include "op_template.h"
108
109 #define REG 27
110 #include "op_template.h"
111
112 #define REG 28
113 #include "op_template.h"
114
115 #define REG 29
116 #include "op_template.h"
117
118 #define REG 30
119 #include "op_template.h"
120
121 #define REG 31
122 #include "op_template.h"
123
124 /* Debug stuff */
125 void OPPROTO op_no_op (void)
126 {
127 #if !defined (DEBUG_OP)
128     __asm__ __volatile__("nop" : : : "memory");
129 #endif
130     RETURN();
131 }
132
133 void OPPROTO op_tb_flush (void)
134 {
135     helper_tb_flush();
136     RETURN();
137 }
138
139 /* Load and stores */
140 #define MEMSUFFIX _raw
141 #include "op_mem.h"
142 #if !defined(CONFIG_USER_ONLY)
143 #define MEMSUFFIX _kernel
144 #include "op_mem.h"
145 #define MEMSUFFIX _executive
146 #include "op_mem.h"
147 #define MEMSUFFIX _supervisor
148 #include "op_mem.h"
149 #define MEMSUFFIX _user
150 #include "op_mem.h"
151 /* This is used for pal modes */
152 #define MEMSUFFIX _data
153 #include "op_mem.h"
154 #endif
155
156 /* Special operation for load and store */
157 void OPPROTO op_n7 (void)
158 {
159     T0 &= ~(uint64_t)0x7;
160     RETURN();
161 }
162
163 /* Misc */
164 void OPPROTO op_excp (void)
165 {
166     helper_excp(PARAM(1), PARAM(2));
167     RETURN();
168 }
169
170 void OPPROTO op_load_amask (void)
171 {
172     helper_amask();
173     RETURN();
174 }
175
176 void OPPROTO op_load_pcc (void)
177 {
178     helper_load_pcc();
179     RETURN();
180 }
181
182 void OPPROTO op_load_implver (void)
183 {
184     helper_load_implver();
185     RETURN();
186 }
187
188 void OPPROTO op_load_fpcr (void)
189 {
190     helper_load_fpcr();
191     RETURN();
192 }
193
194 void OPPROTO op_store_fpcr (void)
195 {
196     helper_store_fpcr();
197     RETURN();
198 }
199
200 void OPPROTO op_load_irf (void)
201 {
202     helper_load_irf();
203     RETURN();
204 }
205
206 void OPPROTO op_set_irf (void)
207 {
208     helper_set_irf();
209     RETURN();
210 }
211
212 void OPPROTO op_clear_irf (void)
213 {
214     helper_clear_irf();
215     RETURN();
216 }
217
218 void OPPROTO op_exit_tb (void)
219 {
220     EXIT_TB();
221 }
222
223 /* Arithmetic */
224 void OPPROTO op_addq (void)
225 {
226     T0 += T1;
227     RETURN();
228 }
229
230 void OPPROTO op_addqv (void)
231 {
232     helper_addqv();
233     RETURN();
234 }
235
236 void OPPROTO op_addl (void)
237 {
238     T0 = (int64_t)((int32_t)(T0 + T1));
239     RETURN();
240 }
241
242 void OPPROTO op_addlv (void)
243 {
244     helper_addlv();
245     RETURN();
246 }
247
248 void OPPROTO op_subq (void)
249 {
250     T0 -= T1;
251     RETURN();
252 }
253
254 void OPPROTO op_subqv (void)
255 {
256     helper_subqv();
257     RETURN();
258 }
259
260 void OPPROTO op_subl (void)
261 {
262     T0 = (int64_t)((int32_t)(T0 - T1));
263     RETURN();
264 }
265
266 void OPPROTO op_sublv (void)
267 {
268     helper_sublv();
269     RETURN();
270 }
271
272 void OPPROTO op_s4 (void)
273 {
274     T0 <<= 2;
275     RETURN();
276 }
277
278 void OPPROTO op_s8 (void)
279 {
280     T0 <<= 3;
281     RETURN();
282 }
283
284 void OPPROTO op_mull (void)
285 {
286     T0 = (int64_t)((int32_t)T0 * (int32_t)T1);
287     RETURN();
288 }
289
290 void OPPROTO op_mullv (void)
291 {
292     helper_mullv();
293     RETURN();
294 }
295
296 void OPPROTO op_mulq (void)
297 {
298     T0 *= T1;
299     RETURN();
300 }
301
302 void OPPROTO op_mulqv (void)
303 {
304     helper_mulqv();
305     RETURN();
306 }
307
308 void OPPROTO op_umulh (void)
309 {
310     helper_umulh();
311     RETURN();
312 }
313
314 /* Logical */
315 void OPPROTO op_and (void)
316 {
317     T0 &= T1;
318     RETURN();
319 }
320
321 void OPPROTO op_bic (void)
322 {
323     T0 &= ~T1;
324     RETURN();
325 }
326
327 void OPPROTO op_bis (void)
328 {
329     T0 |= T1;
330     RETURN();
331 }
332
333 void OPPROTO op_eqv (void)
334 {
335     T0 ^= ~T1;
336     RETURN();
337 }
338
339 void OPPROTO op_ornot (void)
340 {
341     T0 |= ~T1;
342     RETURN();
343 }
344
345 void OPPROTO op_xor (void)
346 {
347     T0 ^= T1;
348     RETURN();
349 }
350
351 void OPPROTO op_sll (void)
352 {
353     T0 <<= T1;
354     RETURN();
355 }
356
357 void OPPROTO op_srl (void)
358 {
359     T0 >>= T1;
360     RETURN();
361 }
362
363 void OPPROTO op_sra (void)
364 {
365     T0 = (int64_t)T0 >> T1;
366     RETURN();
367 }
368
369 void OPPROTO op_sextb (void)
370 {
371     T0 = (int64_t)((int8_t)T0);
372     RETURN();
373 }
374
375 void OPPROTO op_sextw (void)
376 {
377     T0 = (int64_t)((int16_t)T0);
378     RETURN();
379
380 }
381
382 void OPPROTO op_ctpop (void)
383 {
384     helper_ctpop();
385     RETURN();
386 }
387
388 void OPPROTO op_ctlz (void)
389 {
390     helper_ctlz();
391     RETURN();
392 }
393
394 void OPPROTO op_cttz (void)
395 {
396     helper_cttz();
397     RETURN();
398 }
399
400 void OPPROTO op_mskbl (void)
401 {
402     helper_mskbl();
403     RETURN();
404 }
405
406 void OPPROTO op_extbl (void)
407 {
408     helper_extbl();
409     RETURN();
410 }
411
412 void OPPROTO op_insbl (void)
413 {
414     helper_insbl();
415     RETURN();
416 }
417
418 void OPPROTO op_mskwl (void)
419 {
420     helper_mskwl();
421     RETURN();
422 }
423
424 void OPPROTO op_extwl (void)
425 {
426     helper_extwl();
427     RETURN();
428 }
429
430 void OPPROTO op_inswl (void)
431 {
432     helper_inswl();
433     RETURN();
434 }
435
436 void OPPROTO op_mskll (void)
437 {
438     helper_mskll();
439     RETURN();
440 }
441
442 void OPPROTO op_extll (void)
443 {
444     helper_extll();
445     RETURN();
446 }
447
448 void OPPROTO op_insll (void)
449 {
450     helper_insll();
451     RETURN();
452 }
453
454 void OPPROTO op_zap (void)
455 {
456     helper_zap();
457     RETURN();
458 }
459
460 void OPPROTO op_zapnot (void)
461 {
462     helper_zapnot();
463     RETURN();
464 }
465
466 void OPPROTO op_mskql (void)
467 {
468     helper_mskql();
469     RETURN();
470 }
471
472 void OPPROTO op_extql (void)
473 {
474     helper_extql();
475     RETURN();
476 }
477
478 void OPPROTO op_insql (void)
479 {
480     helper_insql();
481     RETURN();
482 }
483
484 void OPPROTO op_mskwh (void)
485 {
486     helper_mskwh();
487     RETURN();
488 }
489
490 void OPPROTO op_inswh (void)
491 {
492     helper_inswh();
493     RETURN();
494 }
495
496 void OPPROTO op_extwh (void)
497 {
498     helper_extwh();
499     RETURN();
500 }
501
502 void OPPROTO op_msklh (void)
503 {
504     helper_msklh();
505     RETURN();
506 }
507
508 void OPPROTO op_inslh (void)
509 {
510     helper_inslh();
511     RETURN();
512 }
513
514 void OPPROTO op_extlh (void)
515 {
516     helper_extlh();
517     RETURN();
518 }
519
520 void OPPROTO op_mskqh (void)
521 {
522     helper_mskqh();
523     RETURN();
524 }
525
526 void OPPROTO op_insqh (void)
527 {
528     helper_insqh();
529     RETURN();
530 }
531
532 void OPPROTO op_extqh (void)
533 {
534     helper_extqh();
535     RETURN();
536 }
537
538 /* Tests */
539 void OPPROTO op_cmpult (void)
540 {
541     if (T0 < T1)
542         T0 = 1;
543     else
544         T0 = 0;
545     RETURN();
546 }
547
548 void OPPROTO op_cmpule (void)
549 {
550     if (T0 <= T1)
551         T0 = 1;
552     else
553         T0 = 0;
554     RETURN();
555 }
556
557 void OPPROTO op_cmpeq (void)
558 {
559     if (T0 == T1)
560         T0 = 1;
561     else
562         T0 = 0;
563     RETURN();
564 }
565
566 void OPPROTO op_cmplt (void)
567 {
568     if ((int64_t)T0 < (int64_t)T1)
569         T0 = 1;
570     else
571         T0 = 0;
572     RETURN();
573 }
574
575 void OPPROTO op_cmple (void)
576 {
577     if ((int64_t)T0 <= (int64_t)T1)
578         T0 = 1;
579     else
580         T0 = 0;
581     RETURN();
582 }
583
584 void OPPROTO op_cmpbge (void)
585 {
586     helper_cmpbge();
587     RETURN();
588 }
589
590 void OPPROTO op_cmpeqz (void)
591 {
592     if (T0 == 0)
593         T0 = 1;
594     else
595         T0 = 0;
596     RETURN();
597 }
598
599 void OPPROTO op_cmpnez (void)
600 {
601     if (T0 != 0)
602         T0 = 1;
603     else
604         T0 = 0;
605     RETURN();
606 }
607
608 void OPPROTO op_cmpltz (void)
609 {
610     if ((int64_t)T0 < 0)
611         T0 = 1;
612     else
613         T0 = 0;
614     RETURN();
615 }
616
617 void OPPROTO op_cmplez (void)
618 {
619     if ((int64_t)T0 <= 0)
620         T0 = 1;
621     else
622         T0 = 0;
623     RETURN();
624 }
625
626 void OPPROTO op_cmpgtz (void)
627 {
628     if ((int64_t)T0 > 0)
629         T0 = 1;
630     else
631         T0 = 0;
632     RETURN();
633 }
634
635 void OPPROTO op_cmpgez (void)
636 {
637     if ((int64_t)T0 >= 0)
638         T0 = 1;
639     else
640         T0 = 0;
641     RETURN();
642 }
643
644 void OPPROTO op_cmplbs (void)
645 {
646     T0 &= 1;
647     RETURN();
648 }
649
650 void OPPROTO op_cmplbc (void)
651 {
652     T0 = (~T0) & 1;
653     RETURN();
654 }
655
656 /* Branches */
657 void OPPROTO op_branch (void)
658 {
659     env->pc = T0 & ~3;
660     RETURN();
661 }
662
663 void OPPROTO op_addq1 (void)
664 {
665     T1 += T0;
666     RETURN();
667 }
668
669 #if 0 // Qemu does not know how to do this...
670 void OPPROTO op_bcond (void)
671 {
672     if (T0)
673         env->pc = T1 & ~3;
674     else
675         env->pc = PARAM(1);
676     RETURN();
677 }
678 #else
679 void OPPROTO op_bcond (void)
680 {
681     if (T0)
682         env->pc = T1 & ~3;
683     else
684         env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2);
685     RETURN();
686 }
687 #endif
688
689 #if 0 // Qemu does not know how to do this...
690 void OPPROTO op_update_pc (void)
691 {
692     env->pc = PARAM(1);
693     RETURN();
694 }
695 #else
696 void OPPROTO op_update_pc (void)
697 {
698     env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2);
699     RETURN();
700 }
701 #endif
702
703 /* Optimization for 32 bits hosts architectures */
704 void OPPROTO op_update_pc32 (void)
705 {
706     env->pc = (uint64_t)PARAM(1);
707     RETURN();
708 }
709
710 /* IEEE floating point arithmetic */
711 /* S floating (single) */
712 void OPPROTO op_adds (void)
713 {
714     FT0 = float32_add(FT0, FT1, &FP_STATUS);
715     RETURN();
716 }
717
718 void OPPROTO op_subs (void)
719 {
720     FT0 = float32_sub(FT0, FT1, &FP_STATUS);
721     RETURN();
722 }
723
724 void OPPROTO op_muls (void)
725 {
726     FT0 = float32_mul(FT0, FT1, &FP_STATUS);
727     RETURN();
728 }
729
730 void OPPROTO op_divs (void)
731 {
732     FT0 = float32_div(FT0, FT1, &FP_STATUS);
733     RETURN();
734 }
735
736 void OPPROTO op_sqrts (void)
737 {
738     helper_sqrts();
739     RETURN();
740 }
741
742 void OPPROTO op_cpys (void)
743 {
744     helper_cpys();
745     RETURN();
746 }
747
748 void OPPROTO op_cpysn (void)
749 {
750     helper_cpysn();
751     RETURN();
752 }
753
754 void OPPROTO op_cpyse (void)
755 {
756     helper_cpyse();
757     RETURN();
758 }
759
760 void OPPROTO op_itofs (void)
761 {
762     helper_itofs();
763     RETURN();
764 }
765
766 void OPPROTO op_ftois (void)
767 {
768     helper_ftois();
769     RETURN();
770 }
771
772 /* T floating (double) */
773 void OPPROTO op_addt (void)
774 {
775     FT0 = float64_add(FT0, FT1, &FP_STATUS);
776     RETURN();
777 }
778
779 void OPPROTO op_subt (void)
780 {
781     FT0 = float64_sub(FT0, FT1, &FP_STATUS);
782     RETURN();
783 }
784
785 void OPPROTO op_mult (void)
786 {
787     FT0 = float64_mul(FT0, FT1, &FP_STATUS);
788     RETURN();
789 }
790
791 void OPPROTO op_divt (void)
792 {
793     FT0 = float64_div(FT0, FT1, &FP_STATUS);
794     RETURN();
795 }
796
797 void OPPROTO op_sqrtt (void)
798 {
799     helper_sqrtt();
800     RETURN();
801 }
802
803 void OPPROTO op_cmptun (void)
804 {
805     helper_cmptun();
806     RETURN();
807 }
808
809 void OPPROTO op_cmpteq (void)
810 {
811     helper_cmpteq();
812     RETURN();
813 }
814
815 void OPPROTO op_cmptle (void)
816 {
817     helper_cmptle();
818     RETURN();
819 }
820
821 void OPPROTO op_cmptlt (void)
822 {
823     helper_cmptlt();
824     RETURN();
825 }
826
827 void OPPROTO op_itoft (void)
828 {
829     helper_itoft();
830     RETURN();
831 }
832
833 void OPPROTO op_ftoit (void)
834 {
835     helper_ftoit();
836     RETURN();
837 }
838
839 /* VAX floating point arithmetic */
840 /* F floating */
841 void OPPROTO op_addf (void)
842 {
843     helper_addf();
844     RETURN();
845 }
846
847 void OPPROTO op_subf (void)
848 {
849     helper_subf();
850     RETURN();
851 }
852
853 void OPPROTO op_mulf (void)
854 {
855     helper_mulf();
856     RETURN();
857 }
858
859 void OPPROTO op_divf (void)
860 {
861     helper_divf();
862     RETURN();
863 }
864
865 void OPPROTO op_sqrtf (void)
866 {
867     helper_sqrtf();
868     RETURN();
869 }
870
871 void OPPROTO op_cmpfeq (void)
872 {
873     helper_cmpfeq();
874     RETURN();
875 }
876
877 void OPPROTO op_cmpfne (void)
878 {
879     helper_cmpfne();
880     RETURN();
881 }
882
883 void OPPROTO op_cmpflt (void)
884 {
885     helper_cmpflt();
886     RETURN();
887 }
888
889 void OPPROTO op_cmpfle (void)
890 {
891     helper_cmpfle();
892     RETURN();
893 }
894
895 void OPPROTO op_cmpfgt (void)
896 {
897     helper_cmpfgt();
898     RETURN();
899 }
900
901 void OPPROTO op_cmpfge (void)
902 {
903     helper_cmpfge();
904     RETURN();
905 }
906
907 void OPPROTO op_itoff (void)
908 {
909     helper_itoff();
910     RETURN();
911 }
912
913 /* G floating */
914 void OPPROTO op_addg (void)
915 {
916     helper_addg();
917     RETURN();
918 }
919
920 void OPPROTO op_subg (void)
921 {
922     helper_subg();
923     RETURN();
924 }
925
926 void OPPROTO op_mulg (void)
927 {
928     helper_mulg();
929     RETURN();
930 }
931
932 void OPPROTO op_divg (void)
933 {
934     helper_divg();
935     RETURN();
936 }
937
938 void OPPROTO op_sqrtg (void)
939 {
940     helper_sqrtg();
941     RETURN();
942 }
943
944 void OPPROTO op_cmpgeq (void)
945 {
946     helper_cmpgeq();
947     RETURN();
948 }
949
950 void OPPROTO op_cmpglt (void)
951 {
952     helper_cmpglt();
953     RETURN();
954 }
955
956 void OPPROTO op_cmpgle (void)
957 {
958     helper_cmpgle();
959     RETURN();
960 }
961
962 /* Floating point format conversion */
963 void OPPROTO op_cvtst (void)
964 {
965     FT0 = (float)FT0;
966     RETURN();
967 }
968
969 void OPPROTO op_cvtqs (void)
970 {
971     helper_cvtqs();
972     RETURN();
973 }
974
975 void OPPROTO op_cvtts (void)
976 {
977     FT0 = (float)FT0;
978     RETURN();
979 }
980
981 void OPPROTO op_cvttq (void)
982 {
983     helper_cvttq();
984     RETURN();
985 }
986
987 void OPPROTO op_cvtqt (void)
988 {
989     helper_cvtqt();
990     RETURN();
991 }
992
993 void OPPROTO op_cvtqf (void)
994 {
995     helper_cvtqf();
996     RETURN();
997 }
998
999 void OPPROTO op_cvtgf (void)
1000 {
1001     helper_cvtgf();
1002     RETURN();
1003 }
1004
1005 void OPPROTO op_cvtgd (void)
1006 {
1007     helper_cvtgd();
1008     RETURN();
1009 }
1010
1011 void OPPROTO op_cvtgq (void)
1012 {
1013     helper_cvtgq();
1014     RETURN();
1015 }
1016
1017 void OPPROTO op_cvtqg (void)
1018 {
1019     helper_cvtqg();
1020     RETURN();
1021 }
1022
1023 void OPPROTO op_cvtdg (void)
1024 {
1025     helper_cvtdg();
1026     RETURN();
1027 }
1028
1029 void OPPROTO op_cvtlq (void)
1030 {
1031     helper_cvtlq();
1032     RETURN();
1033 }
1034
1035 void OPPROTO op_cvtql (void)
1036 {
1037     helper_cvtql();
1038     RETURN();
1039 }
1040
1041 void OPPROTO op_cvtqlv (void)
1042 {
1043     helper_cvtqlv();
1044     RETURN();
1045 }
1046
1047 void OPPROTO op_cvtqlsv (void)
1048 {
1049     helper_cvtqlsv();
1050     RETURN();
1051 }
1052
1053 /* PALcode support special instructions */
1054 #if !defined (CONFIG_USER_ONLY)
1055 void OPPROTO op_hw_rei (void)
1056 {
1057     env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
1058     env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
1059     /* XXX: re-enable interrupts and memory mapping */
1060     RETURN();
1061 }
1062
1063 void OPPROTO op_hw_ret (void)
1064 {
1065     env->pc = T0 & ~3;
1066     env->ipr[IPR_EXC_ADDR] = T0 & 1;
1067     /* XXX: re-enable interrupts and memory mapping */
1068     RETURN();
1069 }
1070
1071 void OPPROTO op_mfpr (void)
1072 {
1073     helper_mfpr(PARAM(1));
1074     RETURN();
1075 }
1076
1077 void OPPROTO op_mtpr (void)
1078 {
1079     helper_mtpr(PARAM(1));
1080     RETURN();
1081 }
1082
1083 void OPPROTO op_set_alt_mode (void)
1084 {
1085     env->saved_mode = env->ps & 0xC;
1086     env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
1087     RETURN();
1088 }
1089
1090 void OPPROTO op_restore_mode (void)
1091 {
1092     env->ps = (env->ps & ~0xC) | env->saved_mode;
1093     RETURN();
1094 }
1095
1096 void OPPROTO op_ld_phys_to_virt (void)
1097 {
1098     helper_ld_phys_to_virt();
1099     RETURN();
1100 }
1101
1102 void OPPROTO op_st_phys_to_virt (void)
1103 {
1104     helper_st_phys_to_virt();
1105     RETURN();
1106 }
1107 #endif /* !defined (CONFIG_USER_ONLY) */