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