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