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