Commit 7a387fffce508fedae82e3e81b90d1f20c02c783
1 parent
8c0fdd85
Add MIPS32R2 instructions, and generally straighten out the instruction
decoding. This is also the first percent towards MIPS64 support. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2224 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
2235 additions
and
591 deletions
target-mips/cpu.h
... | ... | @@ -99,14 +99,16 @@ struct CPUMIPSState { |
99 | 99 | #endif |
100 | 100 | uint32_t CP0_index; |
101 | 101 | uint32_t CP0_random; |
102 | - uint32_t CP0_EntryLo0; | |
103 | - uint32_t CP0_EntryLo1; | |
104 | - uint32_t CP0_Context; | |
102 | + uint64_t CP0_EntryLo0; | |
103 | + uint64_t CP0_EntryLo1; | |
104 | + uint64_t CP0_Context; | |
105 | 105 | uint32_t CP0_PageMask; |
106 | + uint32_t CP0_PageGrain; | |
106 | 107 | uint32_t CP0_Wired; |
108 | + uint32_t CP0_HWREna; | |
107 | 109 | uint32_t CP0_BadVAddr; |
108 | 110 | uint32_t CP0_Count; |
109 | - uint32_t CP0_EntryHi; | |
111 | + uint64_t CP0_EntryHi; | |
110 | 112 | uint32_t CP0_Compare; |
111 | 113 | uint32_t CP0_Status; |
112 | 114 | #define CP0St_CU3 31 |
... | ... | @@ -116,19 +118,36 @@ struct CPUMIPSState { |
116 | 118 | #define CP0St_RP 27 |
117 | 119 | #define CP0St_FR 26 |
118 | 120 | #define CP0St_RE 25 |
121 | +#define CP0St_MX 24 | |
122 | +#define CP0St_PX 23 | |
119 | 123 | #define CP0St_BEV 22 |
120 | 124 | #define CP0St_TS 21 |
121 | 125 | #define CP0St_SR 20 |
122 | 126 | #define CP0St_NMI 19 |
123 | 127 | #define CP0St_IM 8 |
128 | +#define CP0St_KX 7 | |
129 | +#define CP0St_SX 6 | |
130 | +#define CP0St_UX 5 | |
124 | 131 | #define CP0St_UM 4 |
132 | +#define CP0St_R0 3 | |
125 | 133 | #define CP0St_ERL 2 |
126 | 134 | #define CP0St_EXL 1 |
127 | 135 | #define CP0St_IE 0 |
136 | + uint32_t CP0_IntCtl; | |
137 | + uint32_t CP0_SRSCtl; | |
128 | 138 | uint32_t CP0_Cause; |
139 | +#define CP0Ca_BD 31 | |
140 | +#define CP0Ca_TI 30 | |
141 | +#define CP0Ca_CE 28 | |
142 | +#define CP0Ca_DC 27 | |
143 | +#define CP0Ca_PCI 26 | |
129 | 144 | #define CP0Ca_IV 23 |
145 | +#define CP0Ca_WP 22 | |
146 | +#define CP0Ca_IP 8 | |
147 | +#define CP0Ca_EC 2 | |
130 | 148 | uint32_t CP0_EPC; |
131 | 149 | uint32_t CP0_PRid; |
150 | + uint32_t CP0_EBase; | |
132 | 151 | uint32_t CP0_Config0; |
133 | 152 | #define CP0C0_M 31 |
134 | 153 | #define CP0C0_K23 28 |
... | ... | @@ -140,8 +159,10 @@ struct CPUMIPSState { |
140 | 159 | #define CP0C0_AT 13 |
141 | 160 | #define CP0C0_AR 10 |
142 | 161 | #define CP0C0_MT 7 |
162 | +#define CP0C0_VI 3 | |
143 | 163 | #define CP0C0_K0 0 |
144 | 164 | uint32_t CP0_Config1; |
165 | +#define CP0C1_M 31 | |
145 | 166 | #define CP0C1_MMU 25 |
146 | 167 | #define CP0C1_IS 22 |
147 | 168 | #define CP0C1_IL 19 |
... | ... | @@ -149,14 +170,38 @@ struct CPUMIPSState { |
149 | 170 | #define CP0C1_DS 13 |
150 | 171 | #define CP0C1_DL 10 |
151 | 172 | #define CP0C1_DA 7 |
173 | +#define CP0C1_C2 6 | |
174 | +#define CP0C1_MD 5 | |
152 | 175 | #define CP0C1_PC 4 |
153 | 176 | #define CP0C1_WR 3 |
154 | 177 | #define CP0C1_CA 2 |
155 | 178 | #define CP0C1_EP 1 |
156 | 179 | #define CP0C1_FP 0 |
180 | + uint32_t CP0_Config2; | |
181 | +#define CP0C2_M 31 | |
182 | +#define CP0C2_TU 28 | |
183 | +#define CP0C2_TS 24 | |
184 | +#define CP0C2_TL 20 | |
185 | +#define CP0C2_TA 16 | |
186 | +#define CP0C2_SU 12 | |
187 | +#define CP0C2_SS 8 | |
188 | +#define CP0C2_SL 4 | |
189 | +#define CP0C2_SA 0 | |
190 | + uint32_t CP0_Config3; | |
191 | +#define CP0C3_M 31 | |
192 | +#define CP0C3_DSPP 10 | |
193 | +#define CP0C3_LPA 7 | |
194 | +#define CP0C3_VEIC 6 | |
195 | +#define CP0C3_VInt 5 | |
196 | +#define CP0C3_SP 4 | |
197 | +#define CP0C3_MT 2 | |
198 | +#define CP0C3_SM 1 | |
199 | +#define CP0C3_TL 0 | |
157 | 200 | uint32_t CP0_LLAddr; |
158 | 201 | uint32_t CP0_WatchLo; |
159 | 202 | uint32_t CP0_WatchHi; |
203 | + uint32_t CP0_XContext; | |
204 | + uint32_t CP0_Framemask; | |
160 | 205 | uint32_t CP0_Debug; |
161 | 206 | #define CPDB_DBD 31 |
162 | 207 | #define CP0DB_DM 30 |
... | ... | @@ -177,8 +222,11 @@ struct CPUMIPSState { |
177 | 222 | #define CP0DB_DBp 1 |
178 | 223 | #define CP0DB_DSS 0 |
179 | 224 | uint32_t CP0_DEPC; |
225 | + uint32_t CP0_Performance0; | |
180 | 226 | uint32_t CP0_TagLo; |
181 | 227 | uint32_t CP0_DataLo; |
228 | + uint32_t CP0_TagHi; | |
229 | + uint32_t CP0_DataHi; | |
182 | 230 | uint32_t CP0_ErrorEPC; |
183 | 231 | uint32_t CP0_DESAVE; |
184 | 232 | /* Qemu */ |
... | ... | @@ -211,6 +259,9 @@ struct CPUMIPSState { |
211 | 259 | |
212 | 260 | int halted; /* TRUE if the CPU is in suspend state */ |
213 | 261 | |
262 | + int SYNCI_Step; /* Address step size for SYNCI */ | |
263 | + int CCRes; /* Cycle count resolution/divisor */ | |
264 | + | |
214 | 265 | CPU_COMMON |
215 | 266 | |
216 | 267 | int ram_size; | ... | ... |
target-mips/exec.h
... | ... | @@ -68,6 +68,7 @@ void do_msubu (void); |
68 | 68 | #endif |
69 | 69 | void do_mfc0_random(void); |
70 | 70 | void do_mfc0_count(void); |
71 | +void do_mtc0_entryhi(uint32_t in); | |
71 | 72 | void do_mtc0_status_debug(uint32_t old, uint32_t val); |
72 | 73 | void do_mtc0_status_irqraise_debug(void); |
73 | 74 | void do_tlbwi (void); | ... | ... |
target-mips/helper.c
... | ... | @@ -302,15 +302,9 @@ void do_interrupt (CPUState *env) |
302 | 302 | #endif |
303 | 303 | env->CP0_Wired = 0; |
304 | 304 | env->CP0_Config0 = MIPS_CONFIG0; |
305 | -#if defined (MIPS_CONFIG1) | |
306 | 305 | env->CP0_Config1 = MIPS_CONFIG1; |
307 | -#endif | |
308 | -#if defined (MIPS_CONFIG2) | |
309 | 306 | env->CP0_Config2 = MIPS_CONFIG2; |
310 | -#endif | |
311 | -#if defined (MIPS_CONFIG3) | |
312 | 307 | env->CP0_Config3 = MIPS_CONFIG3; |
313 | -#endif | |
314 | 308 | env->CP0_WatchLo = 0; |
315 | 309 | env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); |
316 | 310 | goto set_error_EPC; | ... | ... |
target-mips/mips-defs.h
... | ... | @@ -29,26 +29,44 @@ |
29 | 29 | * Define a major version 1, minor version 0. |
30 | 30 | */ |
31 | 31 | #define MIPS_FCR0 ((0 << 16) | (1 << 8) | (1 << 4) | 0) |
32 | -/* Have config1, uses TLB */ | |
33 | -#define MIPS_CONFIG0_1 \ | |
34 | -((1 << CP0C0_M) | (0 << CP0C0_K23) | (0 << CP0C0_KU) | \ | |
35 | - (1 << CP0C0_MT) | (2 << CP0C0_K0)) | |
32 | + /* Have config1, is MIPS32R1, uses TLB, no virtual icache, | |
33 | + uncached coherency */ | |
34 | +#define MIPS_CONFIG0_1 \ | |
35 | + ((1 << CP0C0_M) | (0x0 << CP0C0_K23) | (0x0 << CP0C0_KU) | \ | |
36 | + (0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) | \ | |
37 | + (0x2 << CP0C0_K0)) | |
36 | 38 | #ifdef TARGET_WORDS_BIGENDIAN |
37 | 39 | #define MIPS_CONFIG0 (MIPS_CONFIG0_1 | (1 << CP0C0_BE)) |
38 | 40 | #else |
39 | 41 | #define MIPS_CONFIG0 MIPS_CONFIG0_1 |
40 | 42 | #endif |
41 | -/* 16 TLBs, 64 sets Icache, 16 bytes Icache line, 2-way Icache, | |
42 | - * 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, | |
43 | - * no performance counters, watch registers present, no code compression, | |
44 | - * EJTAG present, FPU enable bit depending on MIPS_USES_FPU | |
45 | - */ | |
46 | -#define MIPS_CONFIG1 \ | |
47 | -((15 << CP0C1_MMU) | \ | |
48 | - (0x000 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x01 << CP0C1_IA) | \ | |
49 | - (0x000 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x01 << CP0C1_DA) | \ | |
50 | - (0 << CP0C1_PC) | (1 << CP0C1_WR) | (0 << CP0C1_CA) | \ | |
51 | - (1 << CP0C1_EP) | (MIPS_USES_FPU << CP0C1_FP)) | |
43 | +/* Have config2, 16 TLB entries, 64 sets Icache, 16 bytes Icache line, | |
44 | + 2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, | |
45 | + no coprocessor2 attached, no MDMX support attached, | |
46 | + no performance counters, watch registers present, | |
47 | + no code compression, EJTAG present, FPU enable bit depending on | |
48 | + MIPS_USES_FPU */ | |
49 | +#define MIPS_CONFIG1_1 \ | |
50 | +((1 << CP0C1_M) | ((MIPS_TLB_NB - 1) << CP0C1_MMU) | \ | |
51 | + (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) | \ | |
52 | + (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) | \ | |
53 | + (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ | |
54 | + (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP)) | |
55 | +#ifdef MIPS_USES_FPU | |
56 | +#define MIPS_CONFIG1 (MIPS_CONFIG1_1 | (1 << CP0C1_FP)) | |
57 | +#else | |
58 | +#define MIPS_CONFIG1 (MIPS_CONFIG1_1 | (0 << CP0C1_FP)) | |
59 | +#endif | |
60 | +/* Have config3, no tertiary/secondary caches implemented */ | |
61 | +#define MIPS_CONFIG2 \ | |
62 | +((1 << CP0C2_M)) | |
63 | +/* No config4, no DSP ASE, no large physaddr, | |
64 | + no external interrupt controller, no vectored interupts, | |
65 | + no 1kb pages, no MT ASE, no SmartMIPS ASE, no trace logic */ | |
66 | +#define MIPS_CONFIG3 \ | |
67 | +((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \ | |
68 | + (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ | |
69 | + (0 << CP0C3_MT) | (0 << CP0C3_SM) | (0 << CP0C3_TL)) | |
52 | 70 | #elif (MIPS_CPU == MIPS_R4Kp) |
53 | 71 | /* 32 bits target */ |
54 | 72 | #define TARGET_LONG_BITS 32 |
... | ... | @@ -60,7 +78,7 @@ |
60 | 78 | #define MIPS_USES_R4K_FPM |
61 | 79 | #else |
62 | 80 | #error "MIPS CPU not defined" |
63 | -/* Remainder for other flags */ | |
81 | +/* Reminder for other flags */ | |
64 | 82 | //#define TARGET_MIPS64 |
65 | 83 | //#define MIPS_USES_FPU |
66 | 84 | #endif | ... | ... |
target-mips/op.c
... | ... | @@ -437,6 +437,18 @@ void op_srl (void) |
437 | 437 | RETURN(); |
438 | 438 | } |
439 | 439 | |
440 | +void op_rotr (void) | |
441 | +{ | |
442 | + target_ulong tmp; | |
443 | + | |
444 | + if (T1) { | |
445 | + tmp = T0 << (0x20 - T1); | |
446 | + T0 = (T0 >> T1) | tmp; | |
447 | + } else | |
448 | + T0 = T1; | |
449 | + RETURN(); | |
450 | +} | |
451 | + | |
440 | 452 | void op_sllv (void) |
441 | 453 | { |
442 | 454 | T0 = T1 << (T0 & 0x1F); |
... | ... | @@ -455,6 +467,19 @@ void op_srlv (void) |
455 | 467 | RETURN(); |
456 | 468 | } |
457 | 469 | |
470 | +void op_rotrv (void) | |
471 | +{ | |
472 | + target_ulong tmp; | |
473 | + | |
474 | + T0 &= 0x1F; | |
475 | + if (T0) { | |
476 | + tmp = T1 << (0x20 - T0); | |
477 | + T0 = (T1 >> T0) | tmp; | |
478 | + } else | |
479 | + T0 = T1; | |
480 | + RETURN(); | |
481 | +} | |
482 | + | |
458 | 483 | void op_clo (void) |
459 | 484 | { |
460 | 485 | int n; |
... | ... | @@ -602,6 +627,20 @@ void op_movz (void) |
602 | 627 | RETURN(); |
603 | 628 | } |
604 | 629 | |
630 | +void op_movf (void) | |
631 | +{ | |
632 | + if (!(env->fcr31 & PARAM1)) | |
633 | + env->gpr[PARAM2] = env->gpr[PARAM3]; | |
634 | + RETURN(); | |
635 | +} | |
636 | + | |
637 | +void op_movt (void) | |
638 | +{ | |
639 | + if (env->fcr31 & PARAM1) | |
640 | + env->gpr[PARAM2] = env->gpr[PARAM3]; | |
641 | + RETURN(); | |
642 | +} | |
643 | + | |
605 | 644 | /* Tests */ |
606 | 645 | #define OP_COND(name, cond) \ |
607 | 646 | void glue(op_, name) (void) \ |
... | ... | @@ -625,28 +664,32 @@ OP_COND(gtz, (int32_t)T0 > 0); |
625 | 664 | OP_COND(lez, (int32_t)T0 <= 0); |
626 | 665 | OP_COND(ltz, (int32_t)T0 < 0); |
627 | 666 | |
628 | -/* Branchs */ | |
667 | +/* Branches */ | |
629 | 668 | //#undef USE_DIRECT_JUMP |
630 | 669 | |
631 | 670 | void OPPROTO op_goto_tb0(void) |
632 | 671 | { |
633 | 672 | GOTO_TB(op_goto_tb0, PARAM1, 0); |
673 | + RETURN(); | |
634 | 674 | } |
635 | 675 | |
636 | 676 | void OPPROTO op_goto_tb1(void) |
637 | 677 | { |
638 | 678 | GOTO_TB(op_goto_tb1, PARAM1, 1); |
679 | + RETURN(); | |
639 | 680 | } |
640 | 681 | |
641 | 682 | /* Branch to register */ |
642 | 683 | void op_save_breg_target (void) |
643 | 684 | { |
644 | 685 | env->btarget = T2; |
686 | + RETURN(); | |
645 | 687 | } |
646 | 688 | |
647 | 689 | void op_restore_breg_target (void) |
648 | 690 | { |
649 | 691 | T2 = env->btarget; |
692 | + RETURN(); | |
650 | 693 | } |
651 | 694 | |
652 | 695 | void op_breg (void) |
... | ... | @@ -724,12 +767,24 @@ void op_mfc0_pagemask (void) |
724 | 767 | RETURN(); |
725 | 768 | } |
726 | 769 | |
770 | +void op_mfc0_pagegrain (void) | |
771 | +{ | |
772 | + T0 = env->CP0_PageGrain; | |
773 | + RETURN(); | |
774 | +} | |
775 | + | |
727 | 776 | void op_mfc0_wired (void) |
728 | 777 | { |
729 | 778 | T0 = env->CP0_Wired; |
730 | 779 | RETURN(); |
731 | 780 | } |
732 | 781 | |
782 | +void op_mfc0_hwrena (void) | |
783 | +{ | |
784 | + T0 = env->CP0_HWREna; | |
785 | + RETURN(); | |
786 | +} | |
787 | + | |
733 | 788 | void op_mfc0_badvaddr (void) |
734 | 789 | { |
735 | 790 | T0 = env->CP0_BadVAddr; |
... | ... | @@ -766,6 +821,18 @@ void op_mfc0_status (void) |
766 | 821 | RETURN(); |
767 | 822 | } |
768 | 823 | |
824 | +void op_mfc0_intctl (void) | |
825 | +{ | |
826 | + T0 = env->CP0_IntCtl; | |
827 | + RETURN(); | |
828 | +} | |
829 | + | |
830 | +void op_mfc0_srsctl (void) | |
831 | +{ | |
832 | + T0 = env->CP0_SRSCtl; | |
833 | + RETURN(); | |
834 | +} | |
835 | + | |
769 | 836 | void op_mfc0_cause (void) |
770 | 837 | { |
771 | 838 | T0 = env->CP0_Cause; |
... | ... | @@ -784,6 +851,12 @@ void op_mfc0_prid (void) |
784 | 851 | RETURN(); |
785 | 852 | } |
786 | 853 | |
854 | +void op_mfc0_ebase (void) | |
855 | +{ | |
856 | + T0 = env->CP0_EBase; | |
857 | + RETURN(); | |
858 | +} | |
859 | + | |
787 | 860 | void op_mfc0_config0 (void) |
788 | 861 | { |
789 | 862 | T0 = env->CP0_Config0; |
... | ... | @@ -796,24 +869,48 @@ void op_mfc0_config1 (void) |
796 | 869 | RETURN(); |
797 | 870 | } |
798 | 871 | |
872 | +void op_mfc0_config2 (void) | |
873 | +{ | |
874 | + T0 = env->CP0_Config2; | |
875 | + RETURN(); | |
876 | +} | |
877 | + | |
878 | +void op_mfc0_config3 (void) | |
879 | +{ | |
880 | + T0 = env->CP0_Config3; | |
881 | + RETURN(); | |
882 | +} | |
883 | + | |
799 | 884 | void op_mfc0_lladdr (void) |
800 | 885 | { |
801 | 886 | T0 = env->CP0_LLAddr >> 4; |
802 | 887 | RETURN(); |
803 | 888 | } |
804 | 889 | |
805 | -void op_mfc0_watchlo (void) | |
890 | +void op_mfc0_watchlo0 (void) | |
806 | 891 | { |
807 | 892 | T0 = env->CP0_WatchLo; |
808 | 893 | RETURN(); |
809 | 894 | } |
810 | 895 | |
811 | -void op_mfc0_watchhi (void) | |
896 | +void op_mfc0_watchhi0 (void) | |
812 | 897 | { |
813 | 898 | T0 = env->CP0_WatchHi; |
814 | 899 | RETURN(); |
815 | 900 | } |
816 | 901 | |
902 | +void op_mfc0_xcontext (void) | |
903 | +{ | |
904 | + T0 = env->CP0_XContext; | |
905 | + RETURN(); | |
906 | +} | |
907 | + | |
908 | +void op_mfc0_framemask (void) | |
909 | +{ | |
910 | + T0 = env->CP0_Framemask; | |
911 | + RETURN(); | |
912 | +} | |
913 | + | |
817 | 914 | void op_mfc0_debug (void) |
818 | 915 | { |
819 | 916 | T0 = env->CP0_Debug; |
... | ... | @@ -828,6 +925,12 @@ void op_mfc0_depc (void) |
828 | 925 | RETURN(); |
829 | 926 | } |
830 | 927 | |
928 | +void op_mfc0_performance0 (void) | |
929 | +{ | |
930 | + T0 = env->CP0_Performance0; | |
931 | + RETURN(); | |
932 | +} | |
933 | + | |
831 | 934 | void op_mfc0_taglo (void) |
832 | 935 | { |
833 | 936 | T0 = env->CP0_TagLo; |
... | ... | @@ -840,6 +943,18 @@ void op_mfc0_datalo (void) |
840 | 943 | RETURN(); |
841 | 944 | } |
842 | 945 | |
946 | +void op_mfc0_taghi (void) | |
947 | +{ | |
948 | + T0 = env->CP0_TagHi; | |
949 | + RETURN(); | |
950 | +} | |
951 | + | |
952 | +void op_mfc0_datahi (void) | |
953 | +{ | |
954 | + T0 = env->CP0_DataHi; | |
955 | + RETURN(); | |
956 | +} | |
957 | + | |
843 | 958 | void op_mfc0_errorepc (void) |
844 | 959 | { |
845 | 960 | T0 = env->CP0_ErrorEPC; |
... | ... | @@ -854,37 +969,57 @@ void op_mfc0_desave (void) |
854 | 969 | |
855 | 970 | void op_mtc0_index (void) |
856 | 971 | { |
857 | - env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); | |
972 | + env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1)); | |
858 | 973 | RETURN(); |
859 | 974 | } |
860 | 975 | |
861 | 976 | void op_mtc0_entrylo0 (void) |
862 | 977 | { |
863 | - env->CP0_EntryLo0 = T0 & 0x3FFFFFFF; | |
978 | + /* Large physaddr not implemented */ | |
979 | + /* 1k pages not implemented */ | |
980 | + env->CP0_EntryLo0 = T0 & 0x3FFFFFFFUL; | |
864 | 981 | RETURN(); |
865 | 982 | } |
866 | 983 | |
867 | 984 | void op_mtc0_entrylo1 (void) |
868 | 985 | { |
869 | - env->CP0_EntryLo1 = T0 & 0x3FFFFFFF; | |
986 | + /* Large physaddr not implemented */ | |
987 | + /* 1k pages not implemented */ | |
988 | + env->CP0_EntryLo1 = T0 & 0x3FFFFFFFUL; | |
870 | 989 | RETURN(); |
871 | 990 | } |
872 | 991 | |
873 | 992 | void op_mtc0_context (void) |
874 | 993 | { |
875 | - env->CP0_Context = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0); | |
994 | + env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0); | |
876 | 995 | RETURN(); |
877 | 996 | } |
878 | 997 | |
879 | 998 | void op_mtc0_pagemask (void) |
880 | 999 | { |
881 | - env->CP0_PageMask = T0 & 0x01FFE000; | |
1000 | + /* 1k pages not implemented */ | |
1001 | + env->CP0_PageMask = T0 & 0x1FFFE000; | |
1002 | + RETURN(); | |
1003 | +} | |
1004 | + | |
1005 | +void op_mtc0_pagegrain (void) | |
1006 | +{ | |
1007 | + /* SmartMIPS not implemented */ | |
1008 | + /* Large physaddr not implemented */ | |
1009 | + /* 1k pages not implemented */ | |
1010 | + env->CP0_PageGrain = 0; | |
882 | 1011 | RETURN(); |
883 | 1012 | } |
884 | 1013 | |
885 | 1014 | void op_mtc0_wired (void) |
886 | 1015 | { |
887 | - env->CP0_Wired = T0 & 0x0000000F; | |
1016 | + env->CP0_Wired = T0 & (MIPS_TLB_NB - 1); | |
1017 | + RETURN(); | |
1018 | +} | |
1019 | + | |
1020 | +void op_mtc0_hwrena (void) | |
1021 | +{ | |
1022 | + env->CP0_HWREna = T0 & 0x0000000F; | |
888 | 1023 | RETURN(); |
889 | 1024 | } |
890 | 1025 | |
... | ... | @@ -898,6 +1033,8 @@ void op_mtc0_entryhi (void) |
898 | 1033 | { |
899 | 1034 | uint32_t old, val; |
900 | 1035 | |
1036 | + /* 1k pages not implemented */ | |
1037 | + /* Ignore MIPS64 TLB for now */ | |
901 | 1038 | val = T0 & 0xFFFFE0FF; |
902 | 1039 | old = env->CP0_EntryHi; |
903 | 1040 | env->CP0_EntryHi = val; |
... | ... | @@ -950,6 +1087,20 @@ void op_mtc0_status (void) |
950 | 1087 | RETURN(); |
951 | 1088 | } |
952 | 1089 | |
1090 | +void op_mtc0_intctl (void) | |
1091 | +{ | |
1092 | + /* vectored interrupts not implemented */ | |
1093 | + env->CP0_IntCtl = 0; | |
1094 | + RETURN(); | |
1095 | +} | |
1096 | + | |
1097 | +void op_mtc0_srsctl (void) | |
1098 | +{ | |
1099 | + /* shadow registers not implemented */ | |
1100 | + env->CP0_SRSCtl = 0; | |
1101 | + RETURN(); | |
1102 | +} | |
1103 | + | |
953 | 1104 | void op_mtc0_cause (void) |
954 | 1105 | { |
955 | 1106 | uint32_t val, old; |
... | ... | @@ -960,7 +1111,6 @@ void op_mtc0_cause (void) |
960 | 1111 | #if 0 |
961 | 1112 | { |
962 | 1113 | int i, mask; |
963 | - | |
964 | 1114 | /* Check if we ever asserted a software IRQ */ |
965 | 1115 | for (i = 0; i < 2; i++) { |
966 | 1116 | mask = 0x100 << i; |
... | ... | @@ -978,28 +1128,56 @@ void op_mtc0_epc (void) |
978 | 1128 | RETURN(); |
979 | 1129 | } |
980 | 1130 | |
1131 | +void op_mtc0_ebase (void) | |
1132 | +{ | |
1133 | + /* vectored interrupts not implemented */ | |
1134 | + /* Multi-CPU not implemented */ | |
1135 | + env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000); | |
1136 | + RETURN(); | |
1137 | +} | |
1138 | + | |
981 | 1139 | void op_mtc0_config0 (void) |
982 | 1140 | { |
983 | 1141 | #if defined(MIPS_USES_R4K_TLB) |
984 | - env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); | |
1142 | + /* Fixed mapping MMU not implemented */ | |
1143 | + env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001); | |
985 | 1144 | #else |
986 | - env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); | |
1145 | + env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001); | |
987 | 1146 | #endif |
988 | 1147 | RETURN(); |
989 | 1148 | } |
990 | 1149 | |
991 | -void op_mtc0_watchlo (void) | |
1150 | +void op_mtc0_config2 (void) | |
1151 | +{ | |
1152 | + /* tertiary/secondary caches not implemented */ | |
1153 | + env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF); | |
1154 | + RETURN(); | |
1155 | +} | |
1156 | + | |
1157 | +void op_mtc0_watchlo0 (void) | |
992 | 1158 | { |
993 | 1159 | env->CP0_WatchLo = T0; |
994 | 1160 | RETURN(); |
995 | 1161 | } |
996 | 1162 | |
997 | -void op_mtc0_watchhi (void) | |
1163 | +void op_mtc0_watchhi0 (void) | |
998 | 1164 | { |
999 | 1165 | env->CP0_WatchHi = T0 & 0x40FF0FF8; |
1000 | 1166 | RETURN(); |
1001 | 1167 | } |
1002 | 1168 | |
1169 | +void op_mtc0_xcontext (void) | |
1170 | +{ | |
1171 | + env->CP0_XContext = T0; /* XXX */ | |
1172 | + RETURN(); | |
1173 | +} | |
1174 | + | |
1175 | +void op_mtc0_framemask (void) | |
1176 | +{ | |
1177 | + env->CP0_Framemask = T0; /* XXX */ | |
1178 | + RETURN(); | |
1179 | +} | |
1180 | + | |
1003 | 1181 | void op_mtc0_debug (void) |
1004 | 1182 | { |
1005 | 1183 | env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); |
... | ... | @@ -1016,12 +1194,36 @@ void op_mtc0_depc (void) |
1016 | 1194 | RETURN(); |
1017 | 1195 | } |
1018 | 1196 | |
1197 | +void op_mtc0_performance0 (void) | |
1198 | +{ | |
1199 | + env->CP0_Performance0 = T0; /* XXX */ | |
1200 | + RETURN(); | |
1201 | +} | |
1202 | + | |
1019 | 1203 | void op_mtc0_taglo (void) |
1020 | 1204 | { |
1021 | 1205 | env->CP0_TagLo = T0 & 0xFFFFFCF6; |
1022 | 1206 | RETURN(); |
1023 | 1207 | } |
1024 | 1208 | |
1209 | +void op_mtc0_datalo (void) | |
1210 | +{ | |
1211 | + env->CP0_DataLo = T0; /* XXX */ | |
1212 | + RETURN(); | |
1213 | +} | |
1214 | + | |
1215 | +void op_mtc0_taghi (void) | |
1216 | +{ | |
1217 | + env->CP0_TagHi = T0; /* XXX */ | |
1218 | + RETURN(); | |
1219 | +} | |
1220 | + | |
1221 | +void op_mtc0_datahi (void) | |
1222 | +{ | |
1223 | + env->CP0_DataHi = T0; /* XXX */ | |
1224 | + RETURN(); | |
1225 | +} | |
1226 | + | |
1025 | 1227 | void op_mtc0_errorepc (void) |
1026 | 1228 | { |
1027 | 1229 | env->CP0_ErrorEPC = T0; |
... | ... | @@ -1422,6 +1624,42 @@ void op_tlbr (void) |
1422 | 1624 | void op_pmon (void) |
1423 | 1625 | { |
1424 | 1626 | CALL_FROM_TB1(do_pmon, PARAM1); |
1627 | + RETURN(); | |
1628 | +} | |
1629 | + | |
1630 | +void op_di (void) | |
1631 | +{ | |
1632 | + uint32_t val; | |
1633 | + | |
1634 | + T0 = env->CP0_Status; | |
1635 | + val = T0 & ~(1 << CP0St_IE); | |
1636 | + if (val != T0) { | |
1637 | + env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
1638 | + env->CP0_Status = val; | |
1639 | + } | |
1640 | + RETURN(); | |
1641 | +} | |
1642 | + | |
1643 | +void op_ei (void) | |
1644 | +{ | |
1645 | + uint32_t val; | |
1646 | + | |
1647 | + T0 = env->CP0_Status; | |
1648 | + val = T0 | (1 << CP0St_IE); | |
1649 | + if (val != T0) { | |
1650 | + const uint32_t mask = 0x0000FF00; | |
1651 | + | |
1652 | + env->CP0_Status = val; | |
1653 | + if (!(env->hflags & MIPS_HFLAG_EXL) && | |
1654 | + !(env->hflags & MIPS_HFLAG_ERL) && | |
1655 | + !(env->hflags & MIPS_HFLAG_DM) && | |
1656 | + (env->CP0_Status & env->CP0_Cause & mask)) { | |
1657 | + env->interrupt_request |= CPU_INTERRUPT_HARD; | |
1658 | + if (logfile) | |
1659 | + CALL_FROM_TB0(do_mtc0_status_irqraise_debug); | |
1660 | + } | |
1661 | + } | |
1662 | + RETURN(); | |
1425 | 1663 | } |
1426 | 1664 | |
1427 | 1665 | void op_trap (void) |
... | ... | @@ -1434,12 +1672,14 @@ void op_trap (void) |
1434 | 1672 | |
1435 | 1673 | void op_debug (void) |
1436 | 1674 | { |
1437 | - CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG); | |
1675 | + CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG); | |
1676 | + RETURN(); | |
1438 | 1677 | } |
1439 | 1678 | |
1440 | 1679 | void op_set_lladdr (void) |
1441 | 1680 | { |
1442 | 1681 | env->CP0_LLAddr = T2; |
1682 | + RETURN(); | |
1443 | 1683 | } |
1444 | 1684 | |
1445 | 1685 | void debug_eret (void); |
... | ... | @@ -1456,12 +1696,50 @@ void op_eret (void) |
1456 | 1696 | env->CP0_Status &= ~(1 << CP0St_EXL); |
1457 | 1697 | } |
1458 | 1698 | env->CP0_LLAddr = 1; |
1699 | + RETURN(); | |
1459 | 1700 | } |
1460 | 1701 | |
1461 | 1702 | void op_deret (void) |
1462 | 1703 | { |
1463 | 1704 | CALL_FROM_TB0(debug_eret); |
1464 | 1705 | env->PC = env->CP0_DEPC; |
1706 | + RETURN(); | |
1707 | +} | |
1708 | + | |
1709 | +void op_rdhwr_cpunum(void) | |
1710 | +{ | |
1711 | + if (env->CP0_HWREna & (1 << 0)) | |
1712 | + T0 = env->CP0_EBase & 0x2ff; | |
1713 | + else | |
1714 | + CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); | |
1715 | + RETURN(); | |
1716 | +} | |
1717 | + | |
1718 | +void op_rdhwr_synci_step(void) | |
1719 | +{ | |
1720 | + if (env->CP0_HWREna & (1 << 1)) | |
1721 | + T0 = env->SYNCI_Step; | |
1722 | + else | |
1723 | + CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); | |
1724 | + RETURN(); | |
1725 | +} | |
1726 | + | |
1727 | +void op_rdhwr_cc(void) | |
1728 | +{ | |
1729 | + if (env->CP0_HWREna & (1 << 2)) | |
1730 | + T0 = env->CP0_Count; | |
1731 | + else | |
1732 | + CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); | |
1733 | + RETURN(); | |
1734 | +} | |
1735 | + | |
1736 | +void op_rdhwr_ccres(void) | |
1737 | +{ | |
1738 | + if (env->CP0_HWREna & (1 << 3)) | |
1739 | + T0 = env->CCRes; | |
1740 | + else | |
1741 | + CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); | |
1742 | + RETURN(); | |
1465 | 1743 | } |
1466 | 1744 | |
1467 | 1745 | void op_save_state (void) |
... | ... | @@ -1491,10 +1769,62 @@ void op_raise_exception_err (void) |
1491 | 1769 | void op_exit_tb (void) |
1492 | 1770 | { |
1493 | 1771 | EXIT_TB(); |
1772 | + RETURN(); | |
1494 | 1773 | } |
1495 | 1774 | |
1496 | 1775 | void op_wait (void) |
1497 | 1776 | { |
1498 | 1777 | env->halted = 1; |
1499 | 1778 | CALL_FROM_TB1(do_raise_exception, EXCP_HLT); |
1779 | + RETURN(); | |
1780 | +} | |
1781 | + | |
1782 | +/* Bitfield operations. */ | |
1783 | +void op_ext(void) | |
1784 | +{ | |
1785 | + unsigned int pos = PARAM1; | |
1786 | + unsigned int size = PARAM2; | |
1787 | + | |
1788 | + T0 = (T1 >> pos) & ((1 << size) - 1); | |
1789 | + RETURN(); | |
1790 | +} | |
1791 | + | |
1792 | +void op_ins(void) | |
1793 | +{ | |
1794 | + unsigned int pos = PARAM1; | |
1795 | + unsigned int size = PARAM2; | |
1796 | + target_ulong mask = ((1 << size) - 1) << pos; | |
1797 | + | |
1798 | + T0 = (T2 & ~mask) | ((T1 << pos) & mask); | |
1799 | + RETURN(); | |
1800 | +} | |
1801 | + | |
1802 | +void op_wsbh(void) | |
1803 | +{ | |
1804 | + T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF); | |
1805 | + RETURN(); | |
1806 | +} | |
1807 | + | |
1808 | +void op_dsbh(void) | |
1809 | +{ | |
1810 | + T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL); | |
1811 | + RETURN(); | |
1812 | +} | |
1813 | + | |
1814 | +void op_dshd(void) | |
1815 | +{ | |
1816 | + T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL); | |
1817 | + RETURN(); | |
1818 | +} | |
1819 | + | |
1820 | +void op_seb(void) | |
1821 | +{ | |
1822 | + T0 = ((T1 & 0xFF) ^ 0x80) - 0x80; | |
1823 | + RETURN(); | |
1824 | +} | |
1825 | + | |
1826 | +void op_seh(void) | |
1827 | +{ | |
1828 | + T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000; | |
1829 | + RETURN(); | |
1500 | 1830 | } | ... | ... |
target-mips/op_helper.c
... | ... | @@ -153,12 +153,12 @@ void cpu_mips_store_compare(CPUState *env, uint32_t value) |
153 | 153 | |
154 | 154 | void do_mtc0_status_debug(uint32_t old, uint32_t val) |
155 | 155 | { |
156 | - cpu_abort(env, "mtc0 status\n"); | |
156 | + cpu_abort(env, "mtc0 status debug\n"); | |
157 | 157 | } |
158 | 158 | |
159 | -void do_mtc0_status_irqraise_debug(void) | |
159 | +void do_mtc0_status_irqraise_debug (void) | |
160 | 160 | { |
161 | - cpu_abort(env, "mtc0 status\n"); | |
161 | + cpu_abort(env, "mtc0 status irqraise debug\n"); | |
162 | 162 | } |
163 | 163 | |
164 | 164 | void do_tlbwi (void) | ... | ... |
target-mips/translate.c
... | ... | @@ -50,184 +50,313 @@ static uint32_t *gen_opparam_ptr; |
50 | 50 | |
51 | 51 | #include "gen-op.h" |
52 | 52 | |
53 | -/* MIPS opcodes */ | |
54 | -#define EXT_SPECIAL 0x100 | |
55 | -#define EXT_SPECIAL2 0x200 | |
56 | -#define EXT_REGIMM 0x300 | |
57 | -#define EXT_CP0 0x400 | |
58 | -#define EXT_CP1 0x500 | |
59 | -#define EXT_CP2 0x600 | |
60 | -#define EXT_CP3 0x700 | |
53 | +/* MIPS major opcodes */ | |
54 | +#define MASK_OP_MAJOR(op) (op & (0x3F << 26)) | |
61 | 55 | |
62 | 56 | enum { |
63 | 57 | /* indirect opcode tables */ |
64 | - OPC_SPECIAL = 0x00, | |
65 | - OPC_BREGIMM = 0x01, | |
66 | - OPC_CP0 = 0x10, | |
67 | - OPC_CP1 = 0x11, | |
68 | - OPC_CP2 = 0x12, | |
69 | - OPC_CP3 = 0x13, | |
70 | - OPC_SPECIAL2 = 0x1C, | |
58 | + OPC_SPECIAL = (0x00 << 26), | |
59 | + OPC_REGIMM = (0x01 << 26), | |
60 | + OPC_CP0 = (0x10 << 26), | |
61 | + OPC_CP1 = (0x11 << 26), | |
62 | + OPC_CP2 = (0x12 << 26), | |
63 | + OPC_CP3 = (0x13 << 26), | |
64 | + OPC_SPECIAL2 = (0x1C << 26), | |
65 | + OPC_SPECIAL3 = (0x1F << 26), | |
71 | 66 | /* arithmetic with immediate */ |
72 | - OPC_ADDI = 0x08, | |
73 | - OPC_ADDIU = 0x09, | |
74 | - OPC_SLTI = 0x0A, | |
75 | - OPC_SLTIU = 0x0B, | |
76 | - OPC_ANDI = 0x0C, | |
77 | - OPC_ORI = 0x0D, | |
78 | - OPC_XORI = 0x0E, | |
79 | - OPC_LUI = 0x0F, | |
67 | + OPC_ADDI = (0x08 << 26), | |
68 | + OPC_ADDIU = (0x09 << 26), | |
69 | + OPC_SLTI = (0x0A << 26), | |
70 | + OPC_SLTIU = (0x0B << 26), | |
71 | + OPC_ANDI = (0x0C << 26), | |
72 | + OPC_ORI = (0x0D << 26), | |
73 | + OPC_XORI = (0x0E << 26), | |
74 | + OPC_LUI = (0x0F << 26), | |
75 | + OPC_DADDI = (0x18 << 26), | |
76 | + OPC_DADDIU = (0x19 << 26), | |
80 | 77 | /* Jump and branches */ |
81 | - OPC_J = 0x02, | |
82 | - OPC_JAL = 0x03, | |
83 | - OPC_BEQ = 0x04, /* Unconditional if rs = rt = 0 (B) */ | |
84 | - OPC_BEQL = 0x14, | |
85 | - OPC_BNE = 0x05, | |
86 | - OPC_BNEL = 0x15, | |
87 | - OPC_BLEZ = 0x06, | |
88 | - OPC_BLEZL = 0x16, | |
89 | - OPC_BGTZ = 0x07, | |
90 | - OPC_BGTZL = 0x17, | |
91 | - OPC_JALX = 0x1D, /* MIPS 16 only */ | |
78 | + OPC_J = (0x02 << 26), | |
79 | + OPC_JAL = (0x03 << 26), | |
80 | + OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */ | |
81 | + OPC_BEQL = (0x14 << 26), | |
82 | + OPC_BNE = (0x05 << 26), | |
83 | + OPC_BNEL = (0x15 << 26), | |
84 | + OPC_BLEZ = (0x06 << 26), | |
85 | + OPC_BLEZL = (0x16 << 26), | |
86 | + OPC_BGTZ = (0x07 << 26), | |
87 | + OPC_BGTZL = (0x17 << 26), | |
88 | + OPC_JALX = (0x1D << 26), /* MIPS 16 only */ | |
92 | 89 | /* Load and stores */ |
93 | - OPC_LB = 0x20, | |
94 | - OPC_LH = 0x21, | |
95 | - OPC_LWL = 0x22, | |
96 | - OPC_LW = 0x23, | |
97 | - OPC_LBU = 0x24, | |
98 | - OPC_LHU = 0x25, | |
99 | - OPC_LWR = 0x26, | |
100 | - OPC_LWU = 0x27, | |
101 | - OPC_SB = 0x28, | |
102 | - OPC_SH = 0x29, | |
103 | - OPC_SWL = 0x2A, | |
104 | - OPC_SW = 0x2B, | |
105 | - OPC_SWR = 0x2E, | |
106 | - OPC_LL = 0x30, | |
107 | - OPC_SC = 0x38, | |
90 | + OPC_LDL = (0x1A << 26), | |
91 | + OPC_LDR = (0x1B << 26), | |
92 | + OPC_LB = (0x20 << 26), | |
93 | + OPC_LH = (0x21 << 26), | |
94 | + OPC_LWL = (0x22 << 26), | |
95 | + OPC_LW = (0x23 << 26), | |
96 | + OPC_LBU = (0x24 << 26), | |
97 | + OPC_LHU = (0x25 << 26), | |
98 | + OPC_LWR = (0x26 << 26), | |
99 | + OPC_LWU = (0x27 << 26), | |
100 | + OPC_SB = (0x28 << 26), | |
101 | + OPC_SH = (0x29 << 26), | |
102 | + OPC_SWL = (0x2A << 26), | |
103 | + OPC_SW = (0x2B << 26), | |
104 | + OPC_SDL = (0x2C << 26), | |
105 | + OPC_SDR = (0x2D << 26), | |
106 | + OPC_SWR = (0x2E << 26), | |
107 | + OPC_LL = (0x30 << 26), | |
108 | + OPC_LLD = (0x34 << 26), | |
109 | + OPC_LD = (0x37 << 26), | |
110 | + OPC_SC = (0x38 << 26), | |
111 | + OPC_SCD = (0x3C << 26), | |
112 | + OPC_SD = (0x3F << 26), | |
108 | 113 | /* Floating point load/store */ |
109 | - OPC_LWC1 = 0x31, | |
110 | - OPC_LWC2 = 0x32, | |
111 | - OPC_LDC1 = 0x35, | |
112 | - OPC_LDC2 = 0x36, | |
113 | - OPC_SWC1 = 0x39, | |
114 | - OPC_SWC2 = 0x3A, | |
115 | - OPC_SDC1 = 0x3D, | |
116 | - OPC_SDC2 = 0x3E, | |
114 | + OPC_LWC1 = (0x31 << 26), | |
115 | + OPC_LWC2 = (0x32 << 26), | |
116 | + OPC_LDC1 = (0x35 << 26), | |
117 | + OPC_LDC2 = (0x36 << 26), | |
118 | + OPC_SWC1 = (0x39 << 26), | |
119 | + OPC_SWC2 = (0x3A << 26), | |
120 | + OPC_SDC1 = (0x3D << 26), | |
121 | + OPC_SDC2 = (0x3E << 26), | |
122 | + /* MDMX ASE specific */ | |
123 | + OPC_MDMX = (0x1E << 26), | |
117 | 124 | /* Cache and prefetch */ |
118 | - OPC_CACHE = 0x2F, | |
119 | - OPC_PREF = 0x33, | |
125 | + OPC_CACHE = (0x2F << 26), | |
126 | + OPC_PREF = (0x33 << 26), | |
127 | + /* Reserved major opcode */ | |
128 | + OPC_MAJOR3B_RESERVED = (0x3B << 26), | |
120 | 129 | }; |
121 | 130 | |
122 | 131 | /* MIPS special opcodes */ |
132 | +#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F) | |
133 | + | |
123 | 134 | enum { |
124 | 135 | /* Shifts */ |
125 | - OPC_SLL = 0x00 | EXT_SPECIAL, | |
136 | + OPC_SLL = 0x00 | OPC_SPECIAL, | |
126 | 137 | /* NOP is SLL r0, r0, 0 */ |
127 | 138 | /* SSNOP is SLL r0, r0, 1 */ |
128 | - OPC_SRL = 0x02 | EXT_SPECIAL, | |
129 | - OPC_SRA = 0x03 | EXT_SPECIAL, | |
130 | - OPC_SLLV = 0x04 | EXT_SPECIAL, | |
131 | - OPC_SRLV = 0x06 | EXT_SPECIAL, | |
132 | - OPC_SRAV = 0x07 | EXT_SPECIAL, | |
139 | + /* EHB is SLL r0, r0, 3 */ | |
140 | + OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */ | |
141 | + OPC_SRA = 0x03 | OPC_SPECIAL, | |
142 | + OPC_SLLV = 0x04 | OPC_SPECIAL, | |
143 | + OPC_SRLV = 0x06 | OPC_SPECIAL, | |
144 | + OPC_SRAV = 0x07 | OPC_SPECIAL, | |
145 | + OPC_DSLLV = 0x14 | OPC_SPECIAL, | |
146 | + OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */ | |
147 | + OPC_DSRAV = 0x17 | OPC_SPECIAL, | |
148 | + OPC_DSLL = 0x38 | OPC_SPECIAL, | |
149 | + OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */ | |
150 | + OPC_DSRA = 0x3B | OPC_SPECIAL, | |
151 | + OPC_DSLL32 = 0x3C | OPC_SPECIAL, | |
152 | + OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */ | |
153 | + OPC_DSRA32 = 0x3F | OPC_SPECIAL, | |
133 | 154 | /* Multiplication / division */ |
134 | - OPC_MULT = 0x18 | EXT_SPECIAL, | |
135 | - OPC_MULTU = 0x19 | EXT_SPECIAL, | |
136 | - OPC_DIV = 0x1A | EXT_SPECIAL, | |
137 | - OPC_DIVU = 0x1B | EXT_SPECIAL, | |
155 | + OPC_MULT = 0x18 | OPC_SPECIAL, | |
156 | + OPC_MULTU = 0x19 | OPC_SPECIAL, | |
157 | + OPC_DIV = 0x1A | OPC_SPECIAL, | |
158 | + OPC_DIVU = 0x1B | OPC_SPECIAL, | |
159 | + OPC_DMULT = 0x1C | OPC_SPECIAL, | |
160 | + OPC_DMULTU = 0x1D | OPC_SPECIAL, | |
161 | + OPC_DDIV = 0x1E | OPC_SPECIAL, | |
162 | + OPC_DDIVU = 0x1F | OPC_SPECIAL, | |
138 | 163 | /* 2 registers arithmetic / logic */ |
139 | - OPC_ADD = 0x20 | EXT_SPECIAL, | |
140 | - OPC_ADDU = 0x21 | EXT_SPECIAL, | |
141 | - OPC_SUB = 0x22 | EXT_SPECIAL, | |
142 | - OPC_SUBU = 0x23 | EXT_SPECIAL, | |
143 | - OPC_AND = 0x24 | EXT_SPECIAL, | |
144 | - OPC_OR = 0x25 | EXT_SPECIAL, | |
145 | - OPC_XOR = 0x26 | EXT_SPECIAL, | |
146 | - OPC_NOR = 0x27 | EXT_SPECIAL, | |
147 | - OPC_SLT = 0x2A | EXT_SPECIAL, | |
148 | - OPC_SLTU = 0x2B | EXT_SPECIAL, | |
164 | + OPC_ADD = 0x20 | OPC_SPECIAL, | |
165 | + OPC_ADDU = 0x21 | OPC_SPECIAL, | |
166 | + OPC_SUB = 0x22 | OPC_SPECIAL, | |
167 | + OPC_SUBU = 0x23 | OPC_SPECIAL, | |
168 | + OPC_AND = 0x24 | OPC_SPECIAL, | |
169 | + OPC_OR = 0x25 | OPC_SPECIAL, | |
170 | + OPC_XOR = 0x26 | OPC_SPECIAL, | |
171 | + OPC_NOR = 0x27 | OPC_SPECIAL, | |
172 | + OPC_SLT = 0x2A | OPC_SPECIAL, | |
173 | + OPC_SLTU = 0x2B | OPC_SPECIAL, | |
174 | + OPC_DADD = 0x2C | OPC_SPECIAL, | |
175 | + OPC_DADDU = 0x2D | OPC_SPECIAL, | |
176 | + OPC_DSUB = 0x2E | OPC_SPECIAL, | |
177 | + OPC_DSUBU = 0x2F | OPC_SPECIAL, | |
149 | 178 | /* Jumps */ |
150 | - OPC_JR = 0x08 | EXT_SPECIAL, | |
151 | - OPC_JALR = 0x09 | EXT_SPECIAL, | |
179 | + OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */ | |
180 | + OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */ | |
152 | 181 | /* Traps */ |
153 | - OPC_TGE = 0x30 | EXT_SPECIAL, | |
154 | - OPC_TGEU = 0x31 | EXT_SPECIAL, | |
155 | - OPC_TLT = 0x32 | EXT_SPECIAL, | |
156 | - OPC_TLTU = 0x33 | EXT_SPECIAL, | |
157 | - OPC_TEQ = 0x34 | EXT_SPECIAL, | |
158 | - OPC_TNE = 0x36 | EXT_SPECIAL, | |
182 | + OPC_TGE = 0x30 | OPC_SPECIAL, | |
183 | + OPC_TGEU = 0x31 | OPC_SPECIAL, | |
184 | + OPC_TLT = 0x32 | OPC_SPECIAL, | |
185 | + OPC_TLTU = 0x33 | OPC_SPECIAL, | |
186 | + OPC_TEQ = 0x34 | OPC_SPECIAL, | |
187 | + OPC_TNE = 0x36 | OPC_SPECIAL, | |
159 | 188 | /* HI / LO registers load & stores */ |
160 | - OPC_MFHI = 0x10 | EXT_SPECIAL, | |
161 | - OPC_MTHI = 0x11 | EXT_SPECIAL, | |
162 | - OPC_MFLO = 0x12 | EXT_SPECIAL, | |
163 | - OPC_MTLO = 0x13 | EXT_SPECIAL, | |
189 | + OPC_MFHI = 0x10 | OPC_SPECIAL, | |
190 | + OPC_MTHI = 0x11 | OPC_SPECIAL, | |
191 | + OPC_MFLO = 0x12 | OPC_SPECIAL, | |
192 | + OPC_MTLO = 0x13 | OPC_SPECIAL, | |
164 | 193 | /* Conditional moves */ |
165 | - OPC_MOVZ = 0x0A | EXT_SPECIAL, | |
166 | - OPC_MOVN = 0x0B | EXT_SPECIAL, | |
194 | + OPC_MOVZ = 0x0A | OPC_SPECIAL, | |
195 | + OPC_MOVN = 0x0B | OPC_SPECIAL, | |
167 | 196 | |
168 | - OPC_MOVCI = 0x01 | EXT_SPECIAL, | |
197 | + OPC_MOVCI = 0x01 | OPC_SPECIAL, | |
169 | 198 | |
170 | 199 | /* Special */ |
171 | - OPC_PMON = 0x05 | EXT_SPECIAL, | |
172 | - OPC_SYSCALL = 0x0C | EXT_SPECIAL, | |
173 | - OPC_BREAK = 0x0D | EXT_SPECIAL, | |
174 | - OPC_SYNC = 0x0F | EXT_SPECIAL, | |
200 | + OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */ | |
201 | + OPC_SYSCALL = 0x0C | OPC_SPECIAL, | |
202 | + OPC_BREAK = 0x0D | OPC_SPECIAL, | |
203 | + OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */ | |
204 | + OPC_SYNC = 0x0F | OPC_SPECIAL, | |
205 | + | |
206 | + OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL, | |
207 | + OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL, | |
208 | + OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL, | |
209 | + OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL, | |
210 | + OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL, | |
211 | + OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL, | |
212 | + OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL, | |
213 | +}; | |
214 | + | |
215 | +/* REGIMM (rt field) opcodes */ | |
216 | +#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16)) | |
217 | + | |
218 | +enum { | |
219 | + OPC_BLTZ = (0x00 << 16) | OPC_REGIMM, | |
220 | + OPC_BLTZL = (0x02 << 16) | OPC_REGIMM, | |
221 | + OPC_BGEZ = (0x01 << 16) | OPC_REGIMM, | |
222 | + OPC_BGEZL = (0x03 << 16) | OPC_REGIMM, | |
223 | + OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM, | |
224 | + OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM, | |
225 | + OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM, | |
226 | + OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM, | |
227 | + OPC_TGEI = (0x08 << 16) | OPC_REGIMM, | |
228 | + OPC_TGEIU = (0x09 << 16) | OPC_REGIMM, | |
229 | + OPC_TLTI = (0x0A << 16) | OPC_REGIMM, | |
230 | + OPC_TLTIU = (0x0B << 16) | OPC_REGIMM, | |
231 | + OPC_TEQI = (0x0C << 16) | OPC_REGIMM, | |
232 | + OPC_TNEI = (0x0E << 16) | OPC_REGIMM, | |
233 | + OPC_SYNCI = (0x1F << 16) | OPC_REGIMM, | |
175 | 234 | }; |
176 | 235 | |
236 | +/* Special2 opcodes */ | |
237 | +#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F) | |
238 | + | |
177 | 239 | enum { |
178 | - /* Mutiply & xxx operations */ | |
179 | - OPC_MADD = 0x00 | EXT_SPECIAL2, | |
180 | - OPC_MADDU = 0x01 | EXT_SPECIAL2, | |
181 | - OPC_MUL = 0x02 | EXT_SPECIAL2, | |
182 | - OPC_MSUB = 0x04 | EXT_SPECIAL2, | |
183 | - OPC_MSUBU = 0x05 | EXT_SPECIAL2, | |
240 | + /* Multiply & xxx operations */ | |
241 | + OPC_MADD = 0x00 | OPC_SPECIAL2, | |
242 | + OPC_MADDU = 0x01 | OPC_SPECIAL2, | |
243 | + OPC_MUL = 0x02 | OPC_SPECIAL2, | |
244 | + OPC_MSUB = 0x04 | OPC_SPECIAL2, | |
245 | + OPC_MSUBU = 0x05 | OPC_SPECIAL2, | |
184 | 246 | /* Misc */ |
185 | - OPC_CLZ = 0x20 | EXT_SPECIAL2, | |
186 | - OPC_CLO = 0x21 | EXT_SPECIAL2, | |
247 | + OPC_CLZ = 0x20 | OPC_SPECIAL2, | |
248 | + OPC_CLO = 0x21 | OPC_SPECIAL2, | |
249 | + OPC_DCLZ = 0x24 | OPC_SPECIAL2, | |
250 | + OPC_DCLO = 0x25 | OPC_SPECIAL2, | |
187 | 251 | /* Special */ |
188 | - OPC_SDBBP = 0x3F | EXT_SPECIAL2, | |
252 | + OPC_SDBBP = 0x3F | OPC_SPECIAL2, | |
253 | +}; | |
254 | + | |
255 | +/* Special3 opcodes */ | |
256 | +#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F) | |
257 | + | |
258 | +enum { | |
259 | + OPC_EXT = 0x00 | OPC_SPECIAL3, | |
260 | + OPC_DEXTM = 0x01 | OPC_SPECIAL3, | |
261 | + OPC_DEXTU = 0x02 | OPC_SPECIAL3, | |
262 | + OPC_DEXT = 0x03 | OPC_SPECIAL3, | |
263 | + OPC_INS = 0x04 | OPC_SPECIAL3, | |
264 | + OPC_DINSM = 0x05 | OPC_SPECIAL3, | |
265 | + OPC_DINSU = 0x06 | OPC_SPECIAL3, | |
266 | + OPC_DINS = 0x07 | OPC_SPECIAL3, | |
267 | + OPC_BSHFL = 0x20 | OPC_SPECIAL3, | |
268 | + OPC_DBSHFL = 0x24 | OPC_SPECIAL3, | |
269 | + OPC_RDHWR = 0x3B | OPC_SPECIAL3, | |
189 | 270 | }; |
190 | 271 | |
191 | -/* Branch REGIMM */ | |
272 | +/* BSHFL opcodes */ | |
273 | +#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) | |
274 | + | |
192 | 275 | enum { |
193 | - OPC_BLTZ = 0x00 | EXT_REGIMM, | |
194 | - OPC_BLTZL = 0x02 | EXT_REGIMM, | |
195 | - OPC_BGEZ = 0x01 | EXT_REGIMM, | |
196 | - OPC_BGEZL = 0x03 | EXT_REGIMM, | |
197 | - OPC_BLTZAL = 0x10 | EXT_REGIMM, | |
198 | - OPC_BLTZALL = 0x12 | EXT_REGIMM, | |
199 | - OPC_BGEZAL = 0x11 | EXT_REGIMM, | |
200 | - OPC_BGEZALL = 0x13 | EXT_REGIMM, | |
201 | - OPC_TGEI = 0x08 | EXT_REGIMM, | |
202 | - OPC_TGEIU = 0x09 | EXT_REGIMM, | |
203 | - OPC_TLTI = 0x0A | EXT_REGIMM, | |
204 | - OPC_TLTIU = 0x0B | EXT_REGIMM, | |
205 | - OPC_TEQI = 0x0C | EXT_REGIMM, | |
206 | - OPC_TNEI = 0x0E | EXT_REGIMM, | |
276 | + OPC_WSBH = (0x02 << 6) | OPC_BSHFL, | |
277 | + OPC_SEB = (0x10 << 6) | OPC_BSHFL, | |
278 | + OPC_SEH = (0x18 << 6) | OPC_BSHFL, | |
207 | 279 | }; |
208 | 280 | |
281 | +/* DBSHFL opcodes */ | |
282 | +#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) | |
283 | + | |
209 | 284 | enum { |
210 | - /* Coprocessor 0 (MMU) */ | |
211 | - OPC_MFC0 = 0x00 | EXT_CP0, | |
212 | - OPC_MTC0 = 0x04 | EXT_CP0, | |
213 | - OPC_TLBR = 0x01 | EXT_CP0, | |
214 | - OPC_TLBWI = 0x02 | EXT_CP0, | |
215 | - OPC_TLBWR = 0x06 | EXT_CP0, | |
216 | - OPC_TLBP = 0x08 | EXT_CP0, | |
217 | - OPC_ERET = 0x18 | EXT_CP0, | |
218 | - OPC_DERET = 0x1F | EXT_CP0, | |
219 | - OPC_WAIT = 0x20 | EXT_CP0, | |
285 | + OPC_DSBH = (0x02 << 6) | OPC_DBSHFL, | |
286 | + OPC_DSHD = (0x05 << 6) | OPC_DBSHFL, | |
220 | 287 | }; |
221 | 288 | |
222 | -#ifdef MIPS_USES_FPU | |
289 | +/* Coprocessor 0 (rs field) */ | |
290 | +#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | |
291 | + | |
223 | 292 | enum { |
224 | - /* Coprocessor 1 (FPU) */ | |
225 | - OPC_MFC1 = 0x00 | EXT_CP1, | |
226 | - OPC_MTC1 = 0x04 | EXT_CP1, | |
227 | - OPC_CFC1 = 0x02 | EXT_CP1, | |
228 | - OPC_CTC1 = 0x06 | EXT_CP1, | |
293 | + OPC_MFC0 = (0x00 << 21) | OPC_CP0, | |
294 | + OPC_DMFC0 = (0x01 << 21) | OPC_CP0, | |
295 | + OPC_MTC0 = (0x04 << 21) | OPC_CP0, | |
296 | + OPC_DMTC0 = (0x05 << 21) | OPC_CP0, | |
297 | + OPC_RDPGPR = (0x0A << 21) | OPC_CP0, | |
298 | + OPC_MFMC0 = (0x0B << 21) | OPC_CP0, | |
299 | + OPC_WRPGPR = (0x0E << 21) | OPC_CP0, | |
300 | + OPC_C0 = (0x10 << 21) | OPC_CP0, | |
301 | + OPC_C0_FIRST = (0x10 << 21) | OPC_CP0, | |
302 | + OPC_C0_LAST = (0x1F << 21) | OPC_CP0, | |
229 | 303 | }; |
230 | -#endif | |
304 | + | |
305 | +/* MFMC0 opcodes */ | |
306 | +#define MASK_MFMC0(op) MASK_CP0(op) | (op & ((0x0C << 11) | (1 << 5))) | |
307 | + | |
308 | +enum { | |
309 | + OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0, | |
310 | + OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0, | |
311 | +}; | |
312 | + | |
313 | +/* Coprocessor 0 (with rs == C0) */ | |
314 | +#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F) | |
315 | + | |
316 | +enum { | |
317 | + OPC_TLBR = 0x01 | OPC_C0, | |
318 | + OPC_TLBWI = 0x02 | OPC_C0, | |
319 | + OPC_TLBWR = 0x06 | OPC_C0, | |
320 | + OPC_TLBP = 0x08 | OPC_C0, | |
321 | + OPC_RFE = 0x10 | OPC_C0, | |
322 | + OPC_ERET = 0x18 | OPC_C0, | |
323 | + OPC_DERET = 0x1F | OPC_C0, | |
324 | + OPC_WAIT = 0x20 | OPC_C0, | |
325 | +}; | |
326 | + | |
327 | +/* Coprocessor 1 (rs field) */ | |
328 | +#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | |
329 | + | |
330 | +enum { | |
331 | + OPC_MFC1 = (0x00 << 21) | OPC_CP1, | |
332 | + OPC_DMFC1 = (0x01 << 21) | OPC_CP1, | |
333 | + OPC_CFC1 = (0x02 << 21) | OPC_CP1, | |
334 | + OPC_MFHCI = (0x03 << 21) | OPC_CP1, | |
335 | + OPC_MTC1 = (0x04 << 21) | OPC_CP1, | |
336 | + OPC_DMTC1 = (0x05 << 21) | OPC_CP1, | |
337 | + OPC_CTC1 = (0x06 << 21) | OPC_CP1, | |
338 | + OPC_MTHCI = (0x07 << 21) | OPC_CP1, | |
339 | + OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ | |
340 | + OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */ | |
341 | + OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */ | |
342 | + OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */ | |
343 | + OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */ | |
344 | + OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */ | |
345 | + OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */ | |
346 | +}; | |
347 | + | |
348 | +enum { | |
349 | + OPC_BC1F = (0x00 << 16) | OPC_BC1, | |
350 | + OPC_BC1T = (0x01 << 16) | OPC_BC1, | |
351 | + OPC_BC1FL = (0x02 << 16) | OPC_BC1, | |
352 | + OPC_BC1TL = (0x03 << 16) | OPC_BC1, | |
353 | +}; | |
354 | + | |
355 | +#define MASK_CP1_BCOND(op) MASK_CP1(op) | (op & ((0x1F << 21) | (0x3 << 16))) | |
356 | +#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & ((0x1F << 21) | 0x3F)) | |
357 | + | |
358 | +#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | |
359 | +#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | |
231 | 360 | |
232 | 361 | const unsigned char *regnames[] = |
233 | 362 | { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", |
... | ... | @@ -260,8 +389,7 @@ GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr); |
260 | 389 | GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr); |
261 | 390 | GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr); |
262 | 391 | |
263 | -#ifdef MIPS_USES_FPU | |
264 | -const unsigned char *fregnames[] = | |
392 | +static const char *fregnames[] = | |
265 | 393 | { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
266 | 394 | "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", |
267 | 395 | "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", |
... | ... | @@ -344,8 +472,6 @@ static inline void gen_cmp_ ## fmt(int n) \ |
344 | 472 | FOP_CONDS(d) |
345 | 473 | FOP_CONDS(s) |
346 | 474 | |
347 | -#endif | |
348 | - | |
349 | 475 | typedef struct DisasContext { |
350 | 476 | struct TranslationBlock *tb; |
351 | 477 | target_ulong pc, saved_pc; |
... | ... | @@ -410,9 +536,7 @@ do { \ |
410 | 536 | } \ |
411 | 537 | } while (0) |
412 | 538 | |
413 | -#ifdef MIPS_USES_FPU | |
414 | - | |
415 | -# define GEN_LOAD_FREG_FTN(FTn, Fn) \ | |
539 | +#define GEN_LOAD_FREG_FTN(FTn, Fn) \ | |
416 | 540 | do { \ |
417 | 541 | glue(gen_op_load_fpr_, FTn)(Fn); \ |
418 | 542 | } while (0) |
... | ... | @@ -422,8 +546,6 @@ do { \ |
422 | 546 | glue(gen_op_store_fpr_, FTn)(Fn); \ |
423 | 547 | } while (0) |
424 | 548 | |
425 | -#endif | |
426 | - | |
427 | 549 | static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) |
428 | 550 | { |
429 | 551 | #if defined MIPS_DEBUG_DISAS |
... | ... | @@ -487,7 +609,7 @@ static GenOpFunc *gen_op_s##width[] = { \ |
487 | 609 | } |
488 | 610 | #endif |
489 | 611 | |
490 | -#ifdef TARGET_MIPS64 | |
612 | +#ifdef MIPS_HAS_MIPS64 | |
491 | 613 | OP_LD_TABLE(d); |
492 | 614 | OP_LD_TABLE(dl); |
493 | 615 | OP_LD_TABLE(dr); |
... | ... | @@ -510,18 +632,16 @@ OP_LD_TABLE(bu); |
510 | 632 | OP_ST_TABLE(b); |
511 | 633 | OP_LD_TABLE(l); |
512 | 634 | OP_ST_TABLE(c); |
513 | -#ifdef MIPS_USES_FPU | |
514 | 635 | OP_LD_TABLE(wc1); |
515 | 636 | OP_ST_TABLE(wc1); |
516 | 637 | OP_LD_TABLE(dc1); |
517 | 638 | OP_ST_TABLE(dc1); |
518 | -#endif | |
519 | 639 | |
520 | 640 | /* Load and store */ |
521 | -static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | |
641 | +static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, | |
522 | 642 | int base, int16_t offset) |
523 | 643 | { |
524 | - const unsigned char *opn = "unk"; | |
644 | + const char *opn = "unk"; | |
525 | 645 | |
526 | 646 | if (base == 0) { |
527 | 647 | GEN_LOAD_IMM_TN(T0, offset); |
... | ... | @@ -536,23 +656,27 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, |
536 | 656 | * memory access |
537 | 657 | */ |
538 | 658 | switch (opc) { |
539 | -#if defined(TARGET_MIPS64) | |
659 | +#ifdef MIPS_HAS_MIPS64 | |
540 | 660 | case OPC_LD: |
541 | -#if defined (MIPS_HAS_UNALIGNED_LS) | |
542 | - case OPC_ULD: | |
543 | -#endif | |
544 | 661 | op_ldst(ld); |
545 | 662 | GEN_STORE_TN_REG(rt, T0); |
546 | 663 | opn = "ld"; |
547 | 664 | break; |
665 | + case OPC_LLD: | |
666 | + op_ldst(lld); | |
667 | + GEN_STORE_TN_REG(rt, T0); | |
668 | + opn = "lld"; | |
669 | + break; | |
548 | 670 | case OPC_SD: |
549 | -#if defined (MIPS_HAS_UNALIGNED_LS) | |
550 | - case OPC_USD: | |
551 | -#endif | |
552 | 671 | GEN_LOAD_REG_TN(T1, rt); |
553 | 672 | op_ldst(sd); |
554 | 673 | opn = "sd"; |
555 | 674 | break; |
675 | + case OPC_SCD: | |
676 | + GEN_LOAD_REG_TN(T1, rt); | |
677 | + op_ldst(scd); | |
678 | + opn = "scd"; | |
679 | + break; | |
556 | 680 | case OPC_LDL: |
557 | 681 | op_ldst(ldl); |
558 | 682 | GEN_STORE_TN_REG(rt, T0); |
... | ... | @@ -575,9 +699,6 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, |
575 | 699 | break; |
576 | 700 | #endif |
577 | 701 | case OPC_LW: |
578 | -#if defined (MIPS_HAS_UNALIGNED_LS) | |
579 | - case OPC_ULW: | |
580 | -#endif | |
581 | 702 | op_ldst(lw); |
582 | 703 | GEN_STORE_TN_REG(rt, T0); |
583 | 704 | opn = "lw"; |
... | ... | @@ -588,33 +709,21 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, |
588 | 709 | opn = "lwu"; |
589 | 710 | break; |
590 | 711 | case OPC_SW: |
591 | -#if defined (MIPS_HAS_UNALIGNED_LS) | |
592 | - case OPC_USW: | |
593 | -#endif | |
594 | 712 | GEN_LOAD_REG_TN(T1, rt); |
595 | 713 | op_ldst(sw); |
596 | 714 | opn = "sw"; |
597 | 715 | break; |
598 | 716 | case OPC_LH: |
599 | -#if defined (MIPS_HAS_UNALIGNED_LS) | |
600 | - case OPC_ULH: | |
601 | -#endif | |
602 | 717 | op_ldst(lh); |
603 | 718 | GEN_STORE_TN_REG(rt, T0); |
604 | 719 | opn = "lh"; |
605 | 720 | break; |
606 | 721 | case OPC_SH: |
607 | -#if defined (MIPS_HAS_UNALIGNED_LS) | |
608 | - case OPC_USH: | |
609 | -#endif | |
610 | 722 | GEN_LOAD_REG_TN(T1, rt); |
611 | 723 | op_ldst(sh); |
612 | 724 | opn = "sh"; |
613 | 725 | break; |
614 | 726 | case OPC_LHU: |
615 | -#if defined (MIPS_HAS_UNALIGNED_LS) | |
616 | - case OPC_ULHU: | |
617 | -#endif | |
618 | 727 | op_ldst(lhu); |
619 | 728 | GEN_STORE_TN_REG(rt, T0); |
620 | 729 | opn = "lhu"; |
... | ... | @@ -675,13 +784,11 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, |
675 | 784 | MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); |
676 | 785 | } |
677 | 786 | |
678 | -#ifdef MIPS_USES_FPU | |
679 | - | |
680 | 787 | /* Load and store */ |
681 | -static void gen_flt_ldst (DisasContext *ctx, uint16_t opc, int ft, | |
788 | +static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, | |
682 | 789 | int base, int16_t offset) |
683 | 790 | { |
684 | - const unsigned char *opn = "unk"; | |
791 | + const char *opn = "unk"; | |
685 | 792 | |
686 | 793 | if (base == 0) { |
687 | 794 | GEN_LOAD_IMM_TN(T0, offset); |
... | ... | @@ -718,21 +825,20 @@ static void gen_flt_ldst (DisasContext *ctx, uint16_t opc, int ft, |
718 | 825 | break; |
719 | 826 | default: |
720 | 827 | MIPS_INVAL("float load/store"); |
721 | - generate_exception(ctx, EXCP_CpU); | |
828 | + generate_exception_err(ctx, EXCP_CpU, 1); | |
722 | 829 | return; |
723 | 830 | } |
724 | 831 | MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]); |
725 | 832 | } |
726 | -#endif | |
727 | 833 | |
728 | 834 | /* Arithmetic with immediate operand */ |
729 | -static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | |
835 | +static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, | |
730 | 836 | int rs, int16_t imm) |
731 | 837 | { |
732 | 838 | uint32_t uimm; |
733 | - const unsigned char *opn = "unk"; | |
839 | + const char *opn = "unk"; | |
734 | 840 | |
735 | - if (rt == 0 && opc != OPC_ADDI) { | |
841 | + if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { | |
736 | 842 | /* if no destination, treat it as a NOP |
737 | 843 | * For addi, we must generate the overflow exception when needed. |
738 | 844 | */ |
... | ... | @@ -740,8 +846,9 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, |
740 | 846 | return; |
741 | 847 | } |
742 | 848 | if (opc == OPC_ADDI || opc == OPC_ADDIU || |
849 | + opc == OPC_DADDI || opc == OPC_DADDIU || | |
743 | 850 | opc == OPC_SLTI || opc == OPC_SLTIU) |
744 | - uimm = (int32_t)imm; /* Sign extent to 32 bits */ | |
851 | + uimm = (int32_t)imm; /* Sign extend to 32 bits */ | |
745 | 852 | else |
746 | 853 | uimm = (uint16_t)imm; |
747 | 854 | if (opc != OPC_LUI) { |
... | ... | @@ -761,6 +868,17 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, |
761 | 868 | gen_op_add(); |
762 | 869 | opn = "addiu"; |
763 | 870 | break; |
871 | +#ifdef MIPS_HAS_MIPS64 | |
872 | + case OPC_DADDI: | |
873 | + save_cpu_state(ctx, 1); | |
874 | + gen_op_daddo(); | |
875 | + opn = "daddi"; | |
876 | + break; | |
877 | + case OPC_DADDIU: | |
878 | + gen_op_dadd(); | |
879 | + opn = "daddiu"; | |
880 | + break; | |
881 | +#endif | |
764 | 882 | case OPC_SLTI: |
765 | 883 | gen_op_lt(); |
766 | 884 | opn = "slti"; |
... | ... | @@ -793,9 +911,50 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, |
793 | 911 | opn = "sra"; |
794 | 912 | break; |
795 | 913 | case OPC_SRL: |
796 | - gen_op_srl(); | |
797 | - opn = "srl"; | |
914 | + if ((ctx->opcode >> 21) & 1) { | |
915 | + gen_op_rotr(); | |
916 | + opn = "rotr"; | |
917 | + } else { | |
918 | + gen_op_srl(); | |
919 | + opn = "srl"; | |
920 | + } | |
921 | + break; | |
922 | +#ifdef MIPS_HAS_MIPS64 | |
923 | + case OPC_DSLL: | |
924 | + gen_op_dsll(); | |
925 | + opn = "dsll"; | |
926 | + break; | |
927 | + case OPC_DSRA: | |
928 | + gen_op_dsra(); | |
929 | + opn = "dsra"; | |
930 | + break; | |
931 | + case OPC_DSRL: | |
932 | + if ((ctx->opcode >> 21) & 1) { | |
933 | + gen_op_drotr(); | |
934 | + opn = "drotr"; | |
935 | + } else { | |
936 | + gen_op_dsrl(); | |
937 | + opn = "dsrl"; | |
938 | + } | |
939 | + break; | |
940 | + case OPC_DSLL32: | |
941 | + gen_op_dsll32(); | |
942 | + opn = "dsll32"; | |
943 | + break; | |
944 | + case OPC_DSRA32: | |
945 | + gen_op_dsra32(); | |
946 | + opn = "dsra32"; | |
947 | + break; | |
948 | + case OPC_DSRL32: | |
949 | + if ((ctx->opcode >> 21) & 1) { | |
950 | + gen_op_drotr32(); | |
951 | + opn = "drotr32"; | |
952 | + } else { | |
953 | + gen_op_dsrl32(); | |
954 | + opn = "dsrl32"; | |
955 | + } | |
798 | 956 | break; |
957 | +#endif | |
799 | 958 | default: |
800 | 959 | MIPS_INVAL("imm arith"); |
801 | 960 | generate_exception(ctx, EXCP_RI); |
... | ... | @@ -806,12 +965,13 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, |
806 | 965 | } |
807 | 966 | |
808 | 967 | /* Arithmetic */ |
809 | -static void gen_arith (DisasContext *ctx, uint16_t opc, | |
968 | +static void gen_arith (DisasContext *ctx, uint32_t opc, | |
810 | 969 | int rd, int rs, int rt) |
811 | 970 | { |
812 | - const unsigned char *opn = "unk"; | |
971 | + const char *opn = "unk"; | |
813 | 972 | |
814 | - if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB) { | |
973 | + if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB | |
974 | + && opc != OPC_DADD && opc != OPC_DSUB) { | |
815 | 975 | /* if no destination, treat it as a NOP |
816 | 976 | * For add & sub, we must generate the overflow exception when needed. |
817 | 977 | */ |
... | ... | @@ -839,6 +999,26 @@ static void gen_arith (DisasContext *ctx, uint16_t opc, |
839 | 999 | gen_op_sub(); |
840 | 1000 | opn = "subu"; |
841 | 1001 | break; |
1002 | +#ifdef MIPS_HAS_MIPS64 | |
1003 | + case OPC_DADD: | |
1004 | + save_cpu_state(ctx, 1); | |
1005 | + gen_op_daddo(); | |
1006 | + opn = "dadd"; | |
1007 | + break; | |
1008 | + case OPC_DADDU: | |
1009 | + gen_op_dadd(); | |
1010 | + opn = "daddu"; | |
1011 | + break; | |
1012 | + case OPC_DSUB: | |
1013 | + save_cpu_state(ctx, 1); | |
1014 | + gen_op_dsubo(); | |
1015 | + opn = "dsub"; | |
1016 | + break; | |
1017 | + case OPC_DSUBU: | |
1018 | + gen_op_dsub(); | |
1019 | + opn = "dsubu"; | |
1020 | + break; | |
1021 | +#endif | |
842 | 1022 | case OPC_SLT: |
843 | 1023 | gen_op_lt(); |
844 | 1024 | opn = "slt"; |
... | ... | @@ -884,9 +1064,33 @@ static void gen_arith (DisasContext *ctx, uint16_t opc, |
884 | 1064 | opn = "srav"; |
885 | 1065 | break; |
886 | 1066 | case OPC_SRLV: |
887 | - gen_op_srlv(); | |
888 | - opn = "srlv"; | |
1067 | + if ((ctx->opcode >> 6) & 1) { | |
1068 | + gen_op_rotrv(); | |
1069 | + opn = "rotrv"; | |
1070 | + } else { | |
1071 | + gen_op_srlv(); | |
1072 | + opn = "srlv"; | |
1073 | + } | |
1074 | + break; | |
1075 | +#ifdef MIPS_HAS_MIPS64 | |
1076 | + case OPC_DSLLV: | |
1077 | + gen_op_dsllv(); | |
1078 | + opn = "dsllv"; | |
1079 | + break; | |
1080 | + case OPC_DSRAV: | |
1081 | + gen_op_dsrav(); | |
1082 | + opn = "dsrav"; | |
1083 | + break; | |
1084 | + case OPC_DSRLV: | |
1085 | + if ((ctx->opcode >> 6) & 1) { | |
1086 | + gen_op_drotrv(); | |
1087 | + opn = "drotrv"; | |
1088 | + } else { | |
1089 | + gen_op_dsrlv(); | |
1090 | + opn = "dsrlv"; | |
1091 | + } | |
889 | 1092 | break; |
1093 | +#endif | |
890 | 1094 | default: |
891 | 1095 | MIPS_INVAL("arith"); |
892 | 1096 | generate_exception(ctx, EXCP_RI); |
... | ... | @@ -898,9 +1102,9 @@ static void gen_arith (DisasContext *ctx, uint16_t opc, |
898 | 1102 | } |
899 | 1103 | |
900 | 1104 | /* Arithmetic on HI/LO registers */ |
901 | -static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg) | |
1105 | +static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) | |
902 | 1106 | { |
903 | - const unsigned char *opn = "unk"; | |
1107 | + const char *opn = "unk"; | |
904 | 1108 | |
905 | 1109 | if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { |
906 | 1110 | /* Treat as a NOP */ |
... | ... | @@ -936,10 +1140,10 @@ static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg) |
936 | 1140 | MIPS_DEBUG("%s %s", opn, regnames[reg]); |
937 | 1141 | } |
938 | 1142 | |
939 | -static void gen_muldiv (DisasContext *ctx, uint16_t opc, | |
1143 | +static void gen_muldiv (DisasContext *ctx, uint32_t opc, | |
940 | 1144 | int rs, int rt) |
941 | 1145 | { |
942 | - const unsigned char *opn = "unk"; | |
1146 | + const char *opn = "unk"; | |
943 | 1147 | |
944 | 1148 | GEN_LOAD_REG_TN(T0, rs); |
945 | 1149 | GEN_LOAD_REG_TN(T1, rt); |
... | ... | @@ -960,6 +1164,24 @@ static void gen_muldiv (DisasContext *ctx, uint16_t opc, |
960 | 1164 | gen_op_multu(); |
961 | 1165 | opn = "multu"; |
962 | 1166 | break; |
1167 | +#ifdef MIPS_HAS_MIPS64 | |
1168 | + case OPC_DDIV: | |
1169 | + gen_op_ddiv(); | |
1170 | + opn = "ddiv"; | |
1171 | + break; | |
1172 | + case OPC_DDIVU: | |
1173 | + gen_op_ddivu(); | |
1174 | + opn = "ddivu"; | |
1175 | + break; | |
1176 | + case OPC_DMULT: | |
1177 | + gen_op_dmult(); | |
1178 | + opn = "dmult"; | |
1179 | + break; | |
1180 | + case OPC_DMULTU: | |
1181 | + gen_op_dmultu(); | |
1182 | + opn = "dmultu"; | |
1183 | + break; | |
1184 | +#endif | |
963 | 1185 | case OPC_MADD: |
964 | 1186 | gen_op_madd(); |
965 | 1187 | opn = "madd"; |
... | ... | @@ -984,10 +1206,10 @@ static void gen_muldiv (DisasContext *ctx, uint16_t opc, |
984 | 1206 | MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]); |
985 | 1207 | } |
986 | 1208 | |
987 | -static void gen_cl (DisasContext *ctx, uint16_t opc, | |
1209 | +static void gen_cl (DisasContext *ctx, uint32_t opc, | |
988 | 1210 | int rd, int rs) |
989 | 1211 | { |
990 | - const unsigned char *opn = "unk"; | |
1212 | + const char *opn = "unk"; | |
991 | 1213 | if (rd == 0) { |
992 | 1214 | /* Treat as a NOP */ |
993 | 1215 | MIPS_DEBUG("NOP"); |
... | ... | @@ -996,15 +1218,23 @@ static void gen_cl (DisasContext *ctx, uint16_t opc, |
996 | 1218 | GEN_LOAD_REG_TN(T0, rs); |
997 | 1219 | switch (opc) { |
998 | 1220 | case OPC_CLO: |
999 | - /* CLO */ | |
1000 | 1221 | gen_op_clo(); |
1001 | 1222 | opn = "clo"; |
1002 | 1223 | break; |
1003 | 1224 | case OPC_CLZ: |
1004 | - /* CLZ */ | |
1005 | 1225 | gen_op_clz(); |
1006 | 1226 | opn = "clz"; |
1007 | 1227 | break; |
1228 | +#ifdef MIPS_HAS_MIPS64 | |
1229 | + case OPC_DCLO: | |
1230 | + gen_op_dclo(); | |
1231 | + opn = "dclo"; | |
1232 | + break; | |
1233 | + case OPC_DCLZ: | |
1234 | + gen_op_dclz(); | |
1235 | + opn = "dclz"; | |
1236 | + break; | |
1237 | +#endif | |
1008 | 1238 | default: |
1009 | 1239 | MIPS_INVAL("CLx"); |
1010 | 1240 | generate_exception(ctx, EXCP_RI); |
... | ... | @@ -1015,7 +1245,7 @@ static void gen_cl (DisasContext *ctx, uint16_t opc, |
1015 | 1245 | } |
1016 | 1246 | |
1017 | 1247 | /* Traps */ |
1018 | -static void gen_trap (DisasContext *ctx, uint16_t opc, | |
1248 | +static void gen_trap (DisasContext *ctx, uint32_t opc, | |
1019 | 1249 | int rs, int rt, int16_t imm) |
1020 | 1250 | { |
1021 | 1251 | int cond; |
... | ... | @@ -1130,7 +1360,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) |
1130 | 1360 | } |
1131 | 1361 | |
1132 | 1362 | /* Branches (before delay slot) */ |
1133 | -static void gen_compute_branch (DisasContext *ctx, uint16_t opc, | |
1363 | +static void gen_compute_branch (DisasContext *ctx, uint32_t opc, | |
1134 | 1364 | int rs, int rt, int32_t offset) |
1135 | 1365 | { |
1136 | 1366 | target_ulong btarget; |
... | ... | @@ -1180,8 +1410,9 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, |
1180 | 1410 | case OPC_JR: |
1181 | 1411 | case OPC_JALR: |
1182 | 1412 | /* Jump to register */ |
1183 | - if (offset != 0) { | |
1184 | - /* Only hint = 0 is valid */ | |
1413 | + if (offset != 0 && offset != 16) { | |
1414 | + /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the | |
1415 | + others are reserved. */ | |
1185 | 1416 | generate_exception(ctx, EXCP_RI); |
1186 | 1417 | return; |
1187 | 1418 | } |
... | ... | @@ -1348,80 +1579,342 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, |
1348 | 1579 | return; |
1349 | 1580 | } |
1350 | 1581 | |
1582 | +/* special3 bitfield operations */ | |
1583 | +static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, | |
1584 | + int rs, int lsb, int msb) | |
1585 | +{ | |
1586 | + GEN_LOAD_REG_TN(T1, rs); | |
1587 | + switch (opc) { | |
1588 | + case OPC_EXT: | |
1589 | + if (lsb + msb > 31) | |
1590 | + goto fail; | |
1591 | + gen_op_ext(lsb, msb + 1); | |
1592 | + break; | |
1593 | + case OPC_DEXTM: | |
1594 | + if (lsb + msb > 63) | |
1595 | + goto fail; | |
1596 | + gen_op_ext(lsb, msb + 1 + 32); | |
1597 | + break; | |
1598 | + case OPC_DEXTU: | |
1599 | + if (lsb + msb > 63) | |
1600 | + goto fail; | |
1601 | + gen_op_ext(lsb + 32, msb + 1); | |
1602 | + break; | |
1603 | + case OPC_DEXT: | |
1604 | + gen_op_ext(lsb, msb + 1); | |
1605 | + break; | |
1606 | + case OPC_INS: | |
1607 | + if (lsb > msb) | |
1608 | + goto fail; | |
1609 | + GEN_LOAD_REG_TN(T2, rt); | |
1610 | + gen_op_ins(lsb, msb - lsb + 1); | |
1611 | + break; | |
1612 | + case OPC_DINSM: | |
1613 | + if (lsb > msb) | |
1614 | + goto fail; | |
1615 | + GEN_LOAD_REG_TN(T2, rt); | |
1616 | + gen_op_ins(lsb, msb - lsb + 1 + 32); | |
1617 | + break; | |
1618 | + case OPC_DINSU: | |
1619 | + if (lsb > msb) | |
1620 | + goto fail; | |
1621 | + GEN_LOAD_REG_TN(T2, rt); | |
1622 | + gen_op_ins(lsb + 32, msb - lsb + 1); | |
1623 | + break; | |
1624 | + case OPC_DINS: | |
1625 | + if (lsb > msb) | |
1626 | + goto fail; | |
1627 | + GEN_LOAD_REG_TN(T2, rt); | |
1628 | + gen_op_ins(lsb, msb - lsb + 1); | |
1629 | + break; | |
1630 | + default: | |
1631 | +fail: | |
1632 | + MIPS_INVAL("bitops"); | |
1633 | + generate_exception(ctx, EXCP_RI); | |
1634 | + return; | |
1635 | + } | |
1636 | + GEN_STORE_TN_REG(rt, T0); | |
1637 | +} | |
1638 | + | |
1351 | 1639 | /* CP0 (MMU and control) */ |
1352 | 1640 | static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
1353 | 1641 | { |
1354 | - const unsigned char *rn; | |
1642 | + const char *rn = "invalid"; | |
1355 | 1643 | |
1356 | - if (sel != 0 && reg != 16 && reg != 28) { | |
1357 | - rn = "invalid"; | |
1358 | - goto die; | |
1359 | - } | |
1360 | 1644 | switch (reg) { |
1361 | 1645 | case 0: |
1362 | - gen_op_mfc0_index(); | |
1363 | - rn = "Index"; | |
1646 | + switch (sel) { | |
1647 | + case 0: | |
1648 | + gen_op_mfc0_index(); | |
1649 | + rn = "Index"; | |
1650 | + break; | |
1651 | + case 1: | |
1652 | +// gen_op_mfc0_mvpcontrol(); /* MT ASE */ | |
1653 | + rn = "MVPControl"; | |
1654 | +// break; | |
1655 | + case 2: | |
1656 | +// gen_op_mfc0_mvpconf0(); /* MT ASE */ | |
1657 | + rn = "MVPConf0"; | |
1658 | +// break; | |
1659 | + case 3: | |
1660 | +// gen_op_mfc0_mvpconf1(); /* MT ASE */ | |
1661 | + rn = "MVPConf1"; | |
1662 | +// break; | |
1663 | + default: | |
1664 | + goto die; | |
1665 | + } | |
1364 | 1666 | break; |
1365 | 1667 | case 1: |
1366 | - gen_op_mfc0_random(); | |
1367 | - rn = "Random"; | |
1668 | + switch (sel) { | |
1669 | + case 0: | |
1670 | + gen_op_mfc0_random(); | |
1671 | + rn = "Random"; | |
1672 | + break; | |
1673 | + case 1: | |
1674 | +// gen_op_mfc0_vpecontrol(); /* MT ASE */ | |
1675 | + rn = "VPEControl"; | |
1676 | +// break; | |
1677 | + case 2: | |
1678 | +// gen_op_mfc0_vpeconf0(); /* MT ASE */ | |
1679 | + rn = "VPEConf0"; | |
1680 | +// break; | |
1681 | + case 3: | |
1682 | +// gen_op_mfc0_vpeconf1(); /* MT ASE */ | |
1683 | + rn = "VPEConf1"; | |
1684 | +// break; | |
1685 | + case 4: | |
1686 | +// gen_op_mfc0_YQMask(); /* MT ASE */ | |
1687 | + rn = "YQMask"; | |
1688 | +// break; | |
1689 | + case 5: | |
1690 | +// gen_op_mfc0_vpeschedule(); /* MT ASE */ | |
1691 | + rn = "VPESchedule"; | |
1692 | +// break; | |
1693 | + case 6: | |
1694 | +// gen_op_mfc0_vpeschefback(); /* MT ASE */ | |
1695 | + rn = "VPEScheFBack"; | |
1696 | +// break; | |
1697 | + case 7: | |
1698 | +// gen_op_mfc0_vpeopt(); /* MT ASE */ | |
1699 | + rn = "VPEOpt"; | |
1700 | +// break; | |
1701 | + default: | |
1702 | + goto die; | |
1703 | + } | |
1368 | 1704 | break; |
1369 | 1705 | case 2: |
1370 | - gen_op_mfc0_entrylo0(); | |
1371 | - rn = "EntryLo0"; | |
1706 | + switch (sel) { | |
1707 | + case 0: | |
1708 | + gen_op_mfc0_entrylo0(); | |
1709 | + rn = "EntryLo0"; | |
1710 | + break; | |
1711 | + case 1: | |
1712 | +// gen_op_mfc0_tcstatus(); /* MT ASE */ | |
1713 | + rn = "TCStatus"; | |
1714 | +// break; | |
1715 | + case 2: | |
1716 | +// gen_op_mfc0_tcbind(); /* MT ASE */ | |
1717 | + rn = "TCBind"; | |
1718 | +// break; | |
1719 | + case 3: | |
1720 | +// gen_op_mfc0_tcrestart(); /* MT ASE */ | |
1721 | + rn = "TCRestart"; | |
1722 | +// break; | |
1723 | + case 4: | |
1724 | +// gen_op_mfc0_tchalt(); /* MT ASE */ | |
1725 | + rn = "TCHalt"; | |
1726 | +// break; | |
1727 | + case 5: | |
1728 | +// gen_op_mfc0_tccontext(); /* MT ASE */ | |
1729 | + rn = "TCContext"; | |
1730 | +// break; | |
1731 | + case 6: | |
1732 | +// gen_op_mfc0_tcschedule(); /* MT ASE */ | |
1733 | + rn = "TCSchedule"; | |
1734 | +// break; | |
1735 | + case 7: | |
1736 | +// gen_op_mfc0_tcschefback(); /* MT ASE */ | |
1737 | + rn = "TCScheFBack"; | |
1738 | +// break; | |
1739 | + default: | |
1740 | + goto die; | |
1741 | + } | |
1372 | 1742 | break; |
1373 | 1743 | case 3: |
1374 | - /* also CONF */ | |
1375 | - gen_op_mfc0_entrylo1(); | |
1376 | - rn = "EntryLo1"; | |
1744 | + switch (sel) { | |
1745 | + case 0: | |
1746 | + gen_op_mfc0_entrylo1(); | |
1747 | + rn = "EntryLo1"; | |
1748 | + break; | |
1749 | + default: | |
1750 | + goto die; | |
1751 | + } | |
1377 | 1752 | break; |
1378 | 1753 | case 4: |
1379 | - gen_op_mfc0_context(); | |
1380 | - rn = "Context"; | |
1754 | + switch (sel) { | |
1755 | + case 0: | |
1756 | + gen_op_mfc0_context(); | |
1757 | + rn = "Context"; | |
1758 | + break; | |
1759 | + case 1: | |
1760 | +// gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */ | |
1761 | + rn = "ContextConfig"; | |
1762 | +// break; | |
1763 | + default: | |
1764 | + goto die; | |
1765 | + } | |
1381 | 1766 | break; |
1382 | 1767 | case 5: |
1383 | - gen_op_mfc0_pagemask(); | |
1384 | - rn = "PageMask"; | |
1768 | + switch (sel) { | |
1769 | + case 0: | |
1770 | + gen_op_mfc0_pagemask(); | |
1771 | + rn = "PageMask"; | |
1772 | + break; | |
1773 | + case 1: | |
1774 | + gen_op_mfc0_pagegrain(); | |
1775 | + rn = "PageGrain"; | |
1776 | + break; | |
1777 | + default: | |
1778 | + goto die; | |
1779 | + } | |
1385 | 1780 | break; |
1386 | 1781 | case 6: |
1387 | - gen_op_mfc0_wired(); | |
1388 | - rn = "Wired"; | |
1782 | + switch (sel) { | |
1783 | + case 0: | |
1784 | + gen_op_mfc0_wired(); | |
1785 | + rn = "Wired"; | |
1786 | + break; | |
1787 | + case 1: | |
1788 | +// gen_op_mfc0_srsconf0(); /* shadow registers */ | |
1789 | + rn = "SRSConf0"; | |
1790 | +// break; | |
1791 | + case 2: | |
1792 | +// gen_op_mfc0_srsconf1(); /* shadow registers */ | |
1793 | + rn = "SRSConf1"; | |
1794 | +// break; | |
1795 | + case 3: | |
1796 | +// gen_op_mfc0_srsconf2(); /* shadow registers */ | |
1797 | + rn = "SRSConf2"; | |
1798 | +// break; | |
1799 | + case 4: | |
1800 | +// gen_op_mfc0_srsconf3(); /* shadow registers */ | |
1801 | + rn = "SRSConf3"; | |
1802 | +// break; | |
1803 | + case 5: | |
1804 | +// gen_op_mfc0_srsconf4(); /* shadow registers */ | |
1805 | + rn = "SRSConf4"; | |
1806 | +// break; | |
1807 | + default: | |
1808 | + goto die; | |
1809 | + } | |
1389 | 1810 | break; |
1390 | 1811 | case 7: |
1391 | -// gen_op_mfc0_info(); | |
1392 | - rn = "Info"; | |
1812 | + switch (sel) { | |
1813 | + case 0: | |
1814 | + gen_op_mfc0_hwrena(); | |
1815 | + rn = "HWREna"; | |
1816 | + break; | |
1817 | + default: | |
1818 | + goto die; | |
1819 | + } | |
1393 | 1820 | break; |
1394 | 1821 | case 8: |
1395 | - gen_op_mfc0_badvaddr(); | |
1396 | - rn = "BadVaddr"; | |
1822 | + switch (sel) { | |
1823 | + case 0: | |
1824 | + gen_op_mfc0_badvaddr(); | |
1825 | + rn = "BadVaddr"; | |
1826 | + break; | |
1827 | + default: | |
1828 | + goto die; | |
1829 | + } | |
1397 | 1830 | break; |
1398 | 1831 | case 9: |
1399 | - gen_op_mfc0_count(); | |
1400 | - rn = "Count"; | |
1832 | + switch (sel) { | |
1833 | + case 0: | |
1834 | + gen_op_mfc0_count(); | |
1835 | + rn = "Count"; | |
1836 | + break; | |
1837 | + /* 6,7 are implementation dependent */ | |
1838 | + default: | |
1839 | + goto die; | |
1840 | + } | |
1401 | 1841 | break; |
1402 | 1842 | case 10: |
1403 | - gen_op_mfc0_entryhi(); | |
1404 | - rn = "EntryHi"; | |
1843 | + switch (sel) { | |
1844 | + case 0: | |
1845 | + gen_op_mfc0_entryhi(); | |
1846 | + rn = "EntryHi"; | |
1847 | + break; | |
1848 | + default: | |
1849 | + goto die; | |
1850 | + } | |
1405 | 1851 | break; |
1406 | 1852 | case 11: |
1407 | - gen_op_mfc0_compare(); | |
1408 | - rn = "Compare"; | |
1853 | + switch (sel) { | |
1854 | + case 0: | |
1855 | + gen_op_mfc0_compare(); | |
1856 | + rn = "Compare"; | |
1857 | + break; | |
1858 | + /* 6,7 are implementation dependent */ | |
1859 | + default: | |
1860 | + goto die; | |
1861 | + } | |
1409 | 1862 | break; |
1410 | 1863 | case 12: |
1411 | - gen_op_mfc0_status(); | |
1412 | - rn = "Status"; | |
1864 | + switch (sel) { | |
1865 | + case 0: | |
1866 | + gen_op_mfc0_status(); | |
1867 | + rn = "Status"; | |
1868 | + break; | |
1869 | + case 1: | |
1870 | + gen_op_mfc0_intctl(); | |
1871 | + rn = "IntCtl"; | |
1872 | + break; | |
1873 | + case 2: | |
1874 | + gen_op_mfc0_srsctl(); | |
1875 | + rn = "SRSCtl"; | |
1876 | + break; | |
1877 | + case 3: | |
1878 | +// gen_op_mfc0_srsmap(); /* shadow registers */ | |
1879 | + rn = "SRSMap"; | |
1880 | +// break; | |
1881 | + default: | |
1882 | + goto die; | |
1883 | + } | |
1413 | 1884 | break; |
1414 | 1885 | case 13: |
1415 | - gen_op_mfc0_cause(); | |
1416 | - rn = "Cause"; | |
1886 | + switch (sel) { | |
1887 | + case 0: | |
1888 | + gen_op_mfc0_cause(); | |
1889 | + rn = "Cause"; | |
1890 | + break; | |
1891 | + default: | |
1892 | + goto die; | |
1893 | + } | |
1417 | 1894 | break; |
1418 | 1895 | case 14: |
1419 | - gen_op_mfc0_epc(); | |
1420 | - rn = "EPC"; | |
1896 | + switch (sel) { | |
1897 | + case 0: | |
1898 | + gen_op_mfc0_epc(); | |
1899 | + rn = "EPC"; | |
1900 | + break; | |
1901 | + default: | |
1902 | + goto die; | |
1903 | + } | |
1421 | 1904 | break; |
1422 | 1905 | case 15: |
1423 | - gen_op_mfc0_prid(); | |
1424 | - rn = "PRid"; | |
1906 | + switch (sel) { | |
1907 | + case 0: | |
1908 | + gen_op_mfc0_prid(); | |
1909 | + rn = "PRid"; | |
1910 | + break; | |
1911 | + case 1: | |
1912 | + gen_op_mfc0_ebase(); | |
1913 | + rn = "EBase"; | |
1914 | + break; | |
1915 | + default: | |
1916 | + goto die; | |
1917 | + } | |
1425 | 1918 | break; |
1426 | 1919 | case 16: |
1427 | 1920 | switch (sel) { |
... | ... | @@ -1433,91 +1926,285 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
1433 | 1926 | gen_op_mfc0_config1(); |
1434 | 1927 | rn = "Config1"; |
1435 | 1928 | break; |
1929 | + case 2: | |
1930 | + gen_op_mfc0_config2(); | |
1931 | + rn = "Config2"; | |
1932 | + break; | |
1933 | + case 3: | |
1934 | + gen_op_mfc0_config3(); | |
1935 | + rn = "Config3"; | |
1936 | + break; | |
1937 | + /* 6,7 are implementation dependent */ | |
1436 | 1938 | default: |
1437 | - rn = "Unknown config register"; | |
1438 | 1939 | goto die; |
1439 | 1940 | } |
1440 | 1941 | break; |
1441 | 1942 | case 17: |
1442 | - gen_op_mfc0_lladdr(); | |
1443 | - rn = "LLAddr"; | |
1943 | + switch (sel) { | |
1944 | + case 0: | |
1945 | + gen_op_mfc0_lladdr(); | |
1946 | + rn = "LLAddr"; | |
1947 | + break; | |
1948 | + default: | |
1949 | + goto die; | |
1950 | + } | |
1444 | 1951 | break; |
1445 | 1952 | case 18: |
1446 | - gen_op_mfc0_watchlo(); | |
1447 | - rn = "WatchLo"; | |
1953 | + switch (sel) { | |
1954 | + case 0: | |
1955 | + gen_op_mfc0_watchlo0(); | |
1956 | + rn = "WatchLo"; | |
1957 | + break; | |
1958 | + case 1: | |
1959 | +// gen_op_mfc0_watchlo1(); | |
1960 | + rn = "WatchLo1"; | |
1961 | +// break; | |
1962 | + case 2: | |
1963 | +// gen_op_mfc0_watchlo2(); | |
1964 | + rn = "WatchLo2"; | |
1965 | +// break; | |
1966 | + case 3: | |
1967 | +// gen_op_mfc0_watchlo3(); | |
1968 | + rn = "WatchLo3"; | |
1969 | +// break; | |
1970 | + case 4: | |
1971 | +// gen_op_mfc0_watchlo4(); | |
1972 | + rn = "WatchLo4"; | |
1973 | +// break; | |
1974 | + case 5: | |
1975 | +// gen_op_mfc0_watchlo5(); | |
1976 | + rn = "WatchLo5"; | |
1977 | +// break; | |
1978 | + case 6: | |
1979 | +// gen_op_mfc0_watchlo6(); | |
1980 | + rn = "WatchLo6"; | |
1981 | +// break; | |
1982 | + case 7: | |
1983 | +// gen_op_mfc0_watchlo7(); | |
1984 | + rn = "WatchLo7"; | |
1985 | +// break; | |
1986 | + default: | |
1987 | + goto die; | |
1988 | + } | |
1448 | 1989 | break; |
1449 | 1990 | case 19: |
1450 | - gen_op_mfc0_watchhi(); | |
1451 | - rn = "WatchHi"; | |
1991 | + switch (sel) { | |
1992 | + case 0: | |
1993 | + gen_op_mfc0_watchhi0(); | |
1994 | + rn = "WatchHi"; | |
1995 | + break; | |
1996 | + case 1: | |
1997 | +// gen_op_mfc0_watchhi1(); | |
1998 | + rn = "WatchHi1"; | |
1999 | +// break; | |
2000 | + case 2: | |
2001 | +// gen_op_mfc0_watchhi2(); | |
2002 | + rn = "WatchHi2"; | |
2003 | +// break; | |
2004 | + case 3: | |
2005 | +// gen_op_mfc0_watchhi3(); | |
2006 | + rn = "WatchHi3"; | |
2007 | +// break; | |
2008 | + case 4: | |
2009 | +// gen_op_mfc0_watchhi4(); | |
2010 | + rn = "WatchHi4"; | |
2011 | +// break; | |
2012 | + case 5: | |
2013 | +// gen_op_mfc0_watchhi5(); | |
2014 | + rn = "WatchHi5"; | |
2015 | +// break; | |
2016 | + case 6: | |
2017 | +// gen_op_mfc0_watchhi6(); | |
2018 | + rn = "WatchHi6"; | |
2019 | +// break; | |
2020 | + case 7: | |
2021 | +// gen_op_mfc0_watchhi7(); | |
2022 | + rn = "WatchHi7"; | |
2023 | +// break; | |
2024 | + default: | |
2025 | + goto die; | |
2026 | + } | |
1452 | 2027 | break; |
1453 | 2028 | case 20: |
1454 | - /* 64 bit only */ | |
1455 | -// gen_op_mfc0_xcontext(); | |
1456 | - rn = "XContext"; | |
2029 | + switch (sel) { | |
2030 | + case 0: | |
2031 | + /* 64 bit MMU only */ | |
2032 | + gen_op_mfc0_xcontext(); | |
2033 | + rn = "XContext"; | |
2034 | + break; | |
2035 | + default: | |
2036 | + goto die; | |
2037 | + } | |
1457 | 2038 | break; |
1458 | 2039 | case 21: |
1459 | -// gen_op_mfc0_framemask(); | |
1460 | - rn = "Framemask"; | |
2040 | + /* Officially reserved, but sel 0 is used for R1x000 framemask */ | |
2041 | + switch (sel) { | |
2042 | + case 0: | |
2043 | + gen_op_mfc0_framemask(); | |
2044 | + rn = "Framemask"; | |
2045 | + break; | |
2046 | + default: | |
2047 | + goto die; | |
2048 | + } | |
1461 | 2049 | break; |
1462 | 2050 | case 22: |
1463 | -// gen_op_mfc0_diagnostic(); | |
1464 | - rn = "'Diagnostic"; | |
1465 | - break; | |
2051 | + /* ignored */ | |
2052 | + rn = "'Diagnostic"; /* implementation dependent */ | |
2053 | + break; | |
1466 | 2054 | case 23: |
1467 | - gen_op_mfc0_debug(); | |
1468 | - rn = "Debug"; | |
2055 | + switch (sel) { | |
2056 | + case 0: | |
2057 | + gen_op_mfc0_debug(); /* EJTAG support */ | |
2058 | + rn = "Debug"; | |
2059 | + break; | |
2060 | + case 1: | |
2061 | +// gen_op_mfc0_tracecontrol(); /* PDtrace support */ | |
2062 | + rn = "TraceControl"; | |
2063 | +// break; | |
2064 | + case 2: | |
2065 | +// gen_op_mfc0_tracecontrol2(); /* PDtrace support */ | |
2066 | + rn = "TraceControl2"; | |
2067 | +// break; | |
2068 | + case 3: | |
2069 | +// gen_op_mfc0_usertracedata(); /* PDtrace support */ | |
2070 | + rn = "UserTraceData"; | |
2071 | +// break; | |
2072 | + case 4: | |
2073 | +// gen_op_mfc0_debug(); /* PDtrace support */ | |
2074 | + rn = "TraceBPC"; | |
2075 | +// break; | |
2076 | + default: | |
2077 | + goto die; | |
2078 | + } | |
1469 | 2079 | break; |
1470 | 2080 | case 24: |
1471 | - gen_op_mfc0_depc(); | |
1472 | - rn = "DEPC"; | |
2081 | + switch (sel) { | |
2082 | + case 0: | |
2083 | + gen_op_mfc0_depc(); /* EJTAG support */ | |
2084 | + rn = "DEPC"; | |
2085 | + break; | |
2086 | + default: | |
2087 | + goto die; | |
2088 | + } | |
1473 | 2089 | break; |
1474 | 2090 | case 25: |
1475 | -// gen_op_mfc0_performance(); | |
1476 | - rn = "Performance"; | |
2091 | + switch (sel) { | |
2092 | + case 0: | |
2093 | + gen_op_mfc0_performance0(); | |
2094 | + rn = "Performance0"; | |
2095 | + break; | |
2096 | + case 1: | |
2097 | +// gen_op_mfc0_performance1(); | |
2098 | + rn = "Performance1"; | |
2099 | +// break; | |
2100 | + case 2: | |
2101 | +// gen_op_mfc0_performance2(); | |
2102 | + rn = "Performance2"; | |
2103 | +// break; | |
2104 | + case 3: | |
2105 | +// gen_op_mfc0_performance3(); | |
2106 | + rn = "Performance3"; | |
2107 | +// break; | |
2108 | + case 4: | |
2109 | +// gen_op_mfc0_performance4(); | |
2110 | + rn = "Performance4"; | |
2111 | +// break; | |
2112 | + case 5: | |
2113 | +// gen_op_mfc0_performance5(); | |
2114 | + rn = "Performance5"; | |
2115 | +// break; | |
2116 | + case 6: | |
2117 | +// gen_op_mfc0_performance6(); | |
2118 | + rn = "Performance6"; | |
2119 | +// break; | |
2120 | + case 7: | |
2121 | +// gen_op_mfc0_performance7(); | |
2122 | + rn = "Performance7"; | |
2123 | +// break; | |
2124 | + default: | |
2125 | + goto die; | |
2126 | + } | |
1477 | 2127 | break; |
1478 | 2128 | case 26: |
1479 | -// gen_op_mfc0_ecc(); | |
1480 | - rn = "ECC"; | |
1481 | - break; | |
2129 | + rn = "ECC"; | |
2130 | + break; | |
1482 | 2131 | case 27: |
1483 | -// gen_op_mfc0_cacheerr(); | |
1484 | - rn = "CacheErr"; | |
2132 | + switch (sel) { | |
2133 | + /* ignored */ | |
2134 | + case 0 ... 3: | |
2135 | + rn = "CacheErr"; | |
2136 | + break; | |
2137 | + default: | |
2138 | + goto die; | |
2139 | + } | |
1485 | 2140 | break; |
1486 | 2141 | case 28: |
1487 | 2142 | switch (sel) { |
1488 | 2143 | case 0: |
2144 | + case 2: | |
2145 | + case 4: | |
2146 | + case 6: | |
1489 | 2147 | gen_op_mfc0_taglo(); |
1490 | 2148 | rn = "TagLo"; |
1491 | 2149 | break; |
1492 | 2150 | case 1: |
2151 | + case 3: | |
2152 | + case 5: | |
2153 | + case 7: | |
1493 | 2154 | gen_op_mfc0_datalo(); |
1494 | 2155 | rn = "DataLo"; |
1495 | 2156 | break; |
1496 | 2157 | default: |
1497 | - rn = "unknown sel"; | |
1498 | 2158 | goto die; |
1499 | 2159 | } |
1500 | 2160 | break; |
1501 | 2161 | case 29: |
1502 | -// gen_op_mfc0_taghi(); | |
1503 | - rn = "TagHi"; | |
2162 | + switch (sel) { | |
2163 | + case 0: | |
2164 | + case 2: | |
2165 | + case 4: | |
2166 | + case 6: | |
2167 | + gen_op_mfc0_taghi(); | |
2168 | + rn = "TagHi"; | |
2169 | + break; | |
2170 | + case 1: | |
2171 | + case 3: | |
2172 | + case 5: | |
2173 | + case 7: | |
2174 | + gen_op_mfc0_datahi(); | |
2175 | + rn = "DataHi"; | |
2176 | + break; | |
2177 | + default: | |
2178 | + goto die; | |
2179 | + } | |
1504 | 2180 | break; |
1505 | 2181 | case 30: |
1506 | - gen_op_mfc0_errorepc(); | |
1507 | - rn = "ErrorEPC"; | |
2182 | + switch (sel) { | |
2183 | + case 0: | |
2184 | + gen_op_mfc0_errorepc(); | |
2185 | + rn = "ErrorEPC"; | |
2186 | + break; | |
2187 | + default: | |
2188 | + goto die; | |
2189 | + } | |
1508 | 2190 | break; |
1509 | 2191 | case 31: |
1510 | - gen_op_mfc0_desave(); | |
1511 | - rn = "DESAVE"; | |
2192 | + switch (sel) { | |
2193 | + case 0: | |
2194 | + gen_op_mfc0_desave(); /* EJTAG support */ | |
2195 | + rn = "DESAVE"; | |
2196 | + break; | |
2197 | + default: | |
2198 | + goto die; | |
2199 | + } | |
1512 | 2200 | break; |
1513 | 2201 | default: |
1514 | - rn = "unknown"; | |
1515 | 2202 | goto die; |
1516 | 2203 | } |
1517 | 2204 | #if defined MIPS_DEBUG_DISAS |
1518 | 2205 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1519 | - fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n", | |
1520 | - env->PC, rn, T0, reg, sel); | |
2206 | + fprintf(logfile, "mfc0 %s (reg %d sel %d)\n", | |
2207 | + rn, reg, sel); | |
1521 | 2208 | } |
1522 | 2209 | #endif |
1523 | 2210 | return; |
... | ... | @@ -1525,8 +2212,8 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
1525 | 2212 | die: |
1526 | 2213 | #if defined MIPS_DEBUG_DISAS |
1527 | 2214 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1528 | - fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n", | |
1529 | - env->PC, rn, T0, reg, sel); | |
2215 | + fprintf(logfile, "mfc0 %s (reg %d sel %d)\n", | |
2216 | + rn, reg, sel); | |
1530 | 2217 | } |
1531 | 2218 | #endif |
1532 | 2219 | generate_exception(ctx, EXCP_RI); |
... | ... | @@ -1534,167 +2221,583 @@ die: |
1534 | 2221 | |
1535 | 2222 | static void gen_mtc0 (DisasContext *ctx, int reg, int sel) |
1536 | 2223 | { |
1537 | - const unsigned char *rn; | |
1538 | - uint32_t val, old; | |
1539 | - | |
1540 | - if (sel != 0 && reg != 16 && reg != 28) { | |
1541 | - val = -1; | |
1542 | - old = -1; | |
1543 | - rn = "invalid"; | |
1544 | - goto die; | |
1545 | - } | |
2224 | + const char *rn = "invalid"; | |
2225 | + | |
1546 | 2226 | switch (reg) { |
1547 | 2227 | case 0: |
1548 | - gen_op_mtc0_index(); | |
1549 | - rn = "Index"; | |
2228 | + switch (sel) { | |
2229 | + case 0: | |
2230 | + gen_op_mtc0_index(); | |
2231 | + rn = "Index"; | |
2232 | + break; | |
2233 | + case 1: | |
2234 | +// gen_op_mtc0_mvpcontrol(); /* MT ASE */ | |
2235 | + rn = "MVPControl"; | |
2236 | +// break; | |
2237 | + case 2: | |
2238 | +// gen_op_mtc0_mvpconf0(); /* MT ASE */ | |
2239 | + rn = "MVPConf0"; | |
2240 | +// break; | |
2241 | + case 3: | |
2242 | +// gen_op_mtc0_mvpconf1(); /* MT ASE */ | |
2243 | + rn = "MVPConf1"; | |
2244 | +// break; | |
2245 | + default: | |
2246 | + goto die; | |
2247 | + } | |
1550 | 2248 | break; |
1551 | 2249 | case 1: |
1552 | -// ignore or except? | |
1553 | - rn = "Random"; | |
2250 | + switch (sel) { | |
2251 | + case 0: | |
2252 | + /* ignored */ | |
2253 | + rn = "Random"; | |
2254 | + break; | |
2255 | + case 1: | |
2256 | +// gen_op_mtc0_vpecontrol(); /* MT ASE */ | |
2257 | + rn = "VPEControl"; | |
2258 | +// break; | |
2259 | + case 2: | |
2260 | +// gen_op_mtc0_vpeconf0(); /* MT ASE */ | |
2261 | + rn = "VPEConf0"; | |
2262 | +// break; | |
2263 | + case 3: | |
2264 | +// gen_op_mtc0_vpeconf1(); /* MT ASE */ | |
2265 | + rn = "VPEConf1"; | |
2266 | +// break; | |
2267 | + case 4: | |
2268 | +// gen_op_mtc0_YQMask(); /* MT ASE */ | |
2269 | + rn = "YQMask"; | |
2270 | +// break; | |
2271 | + case 5: | |
2272 | +// gen_op_mtc0_vpeschedule(); /* MT ASE */ | |
2273 | + rn = "VPESchedule"; | |
2274 | +// break; | |
2275 | + case 6: | |
2276 | +// gen_op_mtc0_vpeschefback(); /* MT ASE */ | |
2277 | + rn = "VPEScheFBack"; | |
2278 | +// break; | |
2279 | + case 7: | |
2280 | +// gen_op_mtc0_vpeopt(); /* MT ASE */ | |
2281 | + rn = "VPEOpt"; | |
2282 | +// break; | |
2283 | + default: | |
2284 | + goto die; | |
2285 | + } | |
1554 | 2286 | break; |
1555 | 2287 | case 2: |
1556 | - gen_op_mtc0_entrylo0(); | |
1557 | - rn = "EntryLo0"; | |
2288 | + switch (sel) { | |
2289 | + case 0: | |
2290 | + gen_op_mtc0_entrylo0(); | |
2291 | + rn = "EntryLo0"; | |
2292 | + break; | |
2293 | + case 1: | |
2294 | +// gen_op_mtc0_tcstatus(); /* MT ASE */ | |
2295 | + rn = "TCStatus"; | |
2296 | +// break; | |
2297 | + case 2: | |
2298 | +// gen_op_mtc0_tcbind(); /* MT ASE */ | |
2299 | + rn = "TCBind"; | |
2300 | +// break; | |
2301 | + case 3: | |
2302 | +// gen_op_mtc0_tcrestart(); /* MT ASE */ | |
2303 | + rn = "TCRestart"; | |
2304 | +// break; | |
2305 | + case 4: | |
2306 | +// gen_op_mtc0_tchalt(); /* MT ASE */ | |
2307 | + rn = "TCHalt"; | |
2308 | +// break; | |
2309 | + case 5: | |
2310 | +// gen_op_mtc0_tccontext(); /* MT ASE */ | |
2311 | + rn = "TCContext"; | |
2312 | +// break; | |
2313 | + case 6: | |
2314 | +// gen_op_mtc0_tcschedule(); /* MT ASE */ | |
2315 | + rn = "TCSchedule"; | |
2316 | +// break; | |
2317 | + case 7: | |
2318 | +// gen_op_mtc0_tcschefback(); /* MT ASE */ | |
2319 | + rn = "TCScheFBack"; | |
2320 | +// break; | |
2321 | + default: | |
2322 | + goto die; | |
2323 | + } | |
1558 | 2324 | break; |
1559 | 2325 | case 3: |
1560 | - gen_op_mtc0_entrylo1(); | |
1561 | - rn = "EntryLo1"; | |
2326 | + switch (sel) { | |
2327 | + case 0: | |
2328 | + gen_op_mtc0_entrylo1(); | |
2329 | + rn = "EntryLo1"; | |
2330 | + break; | |
2331 | + default: | |
2332 | + goto die; | |
2333 | + } | |
1562 | 2334 | break; |
1563 | 2335 | case 4: |
1564 | - gen_op_mtc0_context(); | |
1565 | - rn = "Context"; | |
2336 | + switch (sel) { | |
2337 | + case 0: | |
2338 | + gen_op_mtc0_context(); | |
2339 | + rn = "Context"; | |
2340 | + break; | |
2341 | + case 1: | |
2342 | +// gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */ | |
2343 | + rn = "ContextConfig"; | |
2344 | +// break; | |
2345 | + default: | |
2346 | + goto die; | |
2347 | + } | |
1566 | 2348 | break; |
1567 | 2349 | case 5: |
1568 | - gen_op_mtc0_pagemask(); | |
1569 | - rn = "PageMask"; | |
2350 | + switch (sel) { | |
2351 | + case 0: | |
2352 | + gen_op_mtc0_pagemask(); | |
2353 | + rn = "PageMask"; | |
2354 | + break; | |
2355 | + case 1: | |
2356 | + gen_op_mtc0_pagegrain(); | |
2357 | + rn = "PageGrain"; | |
2358 | + break; | |
2359 | + default: | |
2360 | + goto die; | |
2361 | + } | |
1570 | 2362 | break; |
1571 | 2363 | case 6: |
1572 | - gen_op_mtc0_wired(); | |
1573 | - rn = "Wired"; | |
2364 | + switch (sel) { | |
2365 | + case 0: | |
2366 | + gen_op_mtc0_wired(); | |
2367 | + rn = "Wired"; | |
2368 | + break; | |
2369 | + case 1: | |
2370 | +// gen_op_mtc0_srsconf0(); /* shadow registers */ | |
2371 | + rn = "SRSConf0"; | |
2372 | +// break; | |
2373 | + case 2: | |
2374 | +// gen_op_mtc0_srsconf1(); /* shadow registers */ | |
2375 | + rn = "SRSConf1"; | |
2376 | +// break; | |
2377 | + case 3: | |
2378 | +// gen_op_mtc0_srsconf2(); /* shadow registers */ | |
2379 | + rn = "SRSConf2"; | |
2380 | +// break; | |
2381 | + case 4: | |
2382 | +// gen_op_mtc0_srsconf3(); /* shadow registers */ | |
2383 | + rn = "SRSConf3"; | |
2384 | +// break; | |
2385 | + case 5: | |
2386 | +// gen_op_mtc0_srsconf4(); /* shadow registers */ | |
2387 | + rn = "SRSConf4"; | |
2388 | +// break; | |
2389 | + default: | |
2390 | + goto die; | |
2391 | + } | |
1574 | 2392 | break; |
1575 | 2393 | case 7: |
1576 | -// ignore or except? | |
1577 | - rn = "Info"; | |
2394 | + switch (sel) { | |
2395 | + case 0: | |
2396 | + gen_op_mtc0_hwrena(); | |
2397 | + rn = "HWREna"; | |
2398 | + break; | |
2399 | + default: | |
2400 | + goto die; | |
2401 | + } | |
1578 | 2402 | break; |
1579 | 2403 | case 8: |
1580 | -// ignore or except? | |
2404 | + /* ignored */ | |
1581 | 2405 | rn = "BadVaddr"; |
1582 | 2406 | break; |
1583 | 2407 | case 9: |
1584 | - gen_op_mtc0_count(); | |
1585 | - rn = "Count"; | |
2408 | + switch (sel) { | |
2409 | + case 0: | |
2410 | + gen_op_mtc0_count(); | |
2411 | + rn = "Count"; | |
2412 | + break; | |
2413 | + /* 6,7 are implementation dependent */ | |
2414 | + default: | |
2415 | + goto die; | |
2416 | + } | |
2417 | + /* Stop translation as we may have switched the execution mode */ | |
2418 | + ctx->bstate = BS_STOP; | |
1586 | 2419 | break; |
1587 | 2420 | case 10: |
1588 | - gen_op_mtc0_entryhi(); | |
1589 | - rn = "EntryHi"; | |
2421 | + switch (sel) { | |
2422 | + case 0: | |
2423 | + gen_op_mtc0_entryhi(); | |
2424 | + rn = "EntryHi"; | |
2425 | + break; | |
2426 | + default: | |
2427 | + goto die; | |
2428 | + } | |
1590 | 2429 | break; |
1591 | 2430 | case 11: |
1592 | - gen_op_mtc0_compare(); | |
1593 | - rn = "Compare"; | |
2431 | + switch (sel) { | |
2432 | + case 0: | |
2433 | + gen_op_mtc0_compare(); | |
2434 | + rn = "Compare"; | |
2435 | + break; | |
2436 | + /* 6,7 are implementation dependent */ | |
2437 | + default: | |
2438 | + goto die; | |
2439 | + } | |
2440 | + /* Stop translation as we may have switched the execution mode */ | |
2441 | + ctx->bstate = BS_STOP; | |
1594 | 2442 | break; |
1595 | 2443 | case 12: |
1596 | - gen_op_mtc0_status(); | |
1597 | - rn = "Status"; | |
2444 | + switch (sel) { | |
2445 | + case 0: | |
2446 | + gen_op_mtc0_status(); | |
2447 | + rn = "Status"; | |
2448 | + break; | |
2449 | + case 1: | |
2450 | + gen_op_mtc0_intctl(); | |
2451 | + rn = "IntCtl"; | |
2452 | + break; | |
2453 | + case 2: | |
2454 | + gen_op_mtc0_srsctl(); | |
2455 | + rn = "SRSCtl"; | |
2456 | + break; | |
2457 | + case 3: | |
2458 | +// gen_op_mtc0_srsmap(); /* shadow registers */ | |
2459 | + rn = "SRSMap"; | |
2460 | +// break; | |
2461 | + default: | |
2462 | + goto die; | |
2463 | + } | |
2464 | + /* Stop translation as we may have switched the execution mode */ | |
2465 | + ctx->bstate = BS_STOP; | |
1598 | 2466 | break; |
1599 | 2467 | case 13: |
1600 | - gen_op_mtc0_cause(); | |
1601 | - rn = "Cause"; | |
2468 | + switch (sel) { | |
2469 | + case 0: | |
2470 | + gen_op_mtc0_cause(); | |
2471 | + rn = "Cause"; | |
2472 | + break; | |
2473 | + default: | |
2474 | + goto die; | |
2475 | + } | |
2476 | + /* Stop translation as we may have switched the execution mode */ | |
2477 | + ctx->bstate = BS_STOP; | |
1602 | 2478 | break; |
1603 | 2479 | case 14: |
1604 | - gen_op_mtc0_epc(); | |
1605 | - rn = "EPC"; | |
2480 | + switch (sel) { | |
2481 | + case 0: | |
2482 | + gen_op_mtc0_epc(); | |
2483 | + rn = "EPC"; | |
2484 | + break; | |
2485 | + default: | |
2486 | + goto die; | |
2487 | + } | |
1606 | 2488 | break; |
1607 | 2489 | case 15: |
1608 | -// ignore or except? | |
1609 | - rn = "PRid"; | |
2490 | + switch (sel) { | |
2491 | + case 0: | |
2492 | + /* ignored */ | |
2493 | + rn = "PRid"; | |
2494 | + break; | |
2495 | + case 1: | |
2496 | + gen_op_mtc0_ebase(); | |
2497 | + rn = "EBase"; | |
2498 | + break; | |
2499 | + default: | |
2500 | + goto die; | |
2501 | + } | |
1610 | 2502 | break; |
1611 | 2503 | case 16: |
1612 | 2504 | switch (sel) { |
1613 | 2505 | case 0: |
1614 | 2506 | gen_op_mtc0_config0(); |
1615 | - rn = "Config0"; | |
2507 | + rn = "Config"; | |
2508 | + break; | |
2509 | + case 1: | |
2510 | + /* ignored */ | |
2511 | + rn = "Config1"; | |
2512 | + break; | |
2513 | + case 2: | |
2514 | + gen_op_mtc0_config2(); | |
2515 | + rn = "Config2"; | |
1616 | 2516 | break; |
2517 | + case 3: | |
2518 | + /* ignored */ | |
2519 | + rn = "Config3"; | |
2520 | + break; | |
2521 | + /* 6,7 are implementation dependent */ | |
1617 | 2522 | default: |
1618 | 2523 | rn = "Invalid config selector"; |
1619 | 2524 | goto die; |
1620 | 2525 | } |
2526 | + /* Stop translation as we may have switched the execution mode */ | |
2527 | + ctx->bstate = BS_STOP; | |
1621 | 2528 | break; |
1622 | 2529 | case 17: |
1623 | -// ignore or except? | |
1624 | - rn = "LLaddr"; | |
2530 | + switch (sel) { | |
2531 | + case 0: | |
2532 | + /* ignored */ | |
2533 | + rn = "LLAddr"; | |
2534 | + break; | |
2535 | + default: | |
2536 | + goto die; | |
2537 | + } | |
1625 | 2538 | break; |
1626 | 2539 | case 18: |
1627 | - gen_op_mtc0_watchlo(); | |
1628 | - rn = "WatchLo"; | |
2540 | + switch (sel) { | |
2541 | + case 0: | |
2542 | + gen_op_mtc0_watchlo0(); | |
2543 | + rn = "WatchLo"; | |
2544 | + break; | |
2545 | + case 1: | |
2546 | +// gen_op_mtc0_watchlo1(); | |
2547 | + rn = "WatchLo1"; | |
2548 | +// break; | |
2549 | + case 2: | |
2550 | +// gen_op_mtc0_watchlo2(); | |
2551 | + rn = "WatchLo2"; | |
2552 | +// break; | |
2553 | + case 3: | |
2554 | +// gen_op_mtc0_watchlo3(); | |
2555 | + rn = "WatchLo3"; | |
2556 | +// break; | |
2557 | + case 4: | |
2558 | +// gen_op_mtc0_watchlo4(); | |
2559 | + rn = "WatchLo4"; | |
2560 | +// break; | |
2561 | + case 5: | |
2562 | +// gen_op_mtc0_watchlo5(); | |
2563 | + rn = "WatchLo5"; | |
2564 | +// break; | |
2565 | + case 6: | |
2566 | +// gen_op_mtc0_watchlo6(); | |
2567 | + rn = "WatchLo6"; | |
2568 | +// break; | |
2569 | + case 7: | |
2570 | +// gen_op_mtc0_watchlo7(); | |
2571 | + rn = "WatchLo7"; | |
2572 | +// break; | |
2573 | + default: | |
2574 | + goto die; | |
2575 | + } | |
1629 | 2576 | break; |
1630 | 2577 | case 19: |
1631 | - gen_op_mtc0_watchhi(); | |
1632 | - rn = "WatchHi"; | |
2578 | + switch (sel) { | |
2579 | + case 0: | |
2580 | + gen_op_mtc0_watchhi0(); | |
2581 | + rn = "WatchHi"; | |
2582 | + break; | |
2583 | + case 1: | |
2584 | +// gen_op_mtc0_watchhi1(); | |
2585 | + rn = "WatchHi1"; | |
2586 | +// break; | |
2587 | + case 2: | |
2588 | +// gen_op_mtc0_watchhi2(); | |
2589 | + rn = "WatchHi2"; | |
2590 | +// break; | |
2591 | + case 3: | |
2592 | +// gen_op_mtc0_watchhi3(); | |
2593 | + rn = "WatchHi3"; | |
2594 | +// break; | |
2595 | + case 4: | |
2596 | +// gen_op_mtc0_watchhi4(); | |
2597 | + rn = "WatchHi4"; | |
2598 | +// break; | |
2599 | + case 5: | |
2600 | +// gen_op_mtc0_watchhi5(); | |
2601 | + rn = "WatchHi5"; | |
2602 | +// break; | |
2603 | + case 6: | |
2604 | +// gen_op_mtc0_watchhi6(); | |
2605 | + rn = "WatchHi6"; | |
2606 | +// break; | |
2607 | + case 7: | |
2608 | +// gen_op_mtc0_watchhi7(); | |
2609 | + rn = "WatchHi7"; | |
2610 | +// break; | |
2611 | + default: | |
2612 | + goto die; | |
2613 | + } | |
1633 | 2614 | break; |
1634 | 2615 | case 20: |
1635 | - /* 64 bit only */ | |
1636 | -// gen_op_mtc0_xcontext(); | |
1637 | - rn = "XContext"; | |
2616 | + switch (sel) { | |
2617 | + case 0: | |
2618 | + /* 64 bit MMU only */ | |
2619 | + gen_op_mtc0_xcontext(); | |
2620 | + rn = "XContext"; | |
2621 | + break; | |
2622 | + default: | |
2623 | + goto die; | |
2624 | + } | |
1638 | 2625 | break; |
1639 | 2626 | case 21: |
1640 | -// gen_op_mtc0_framemask(); | |
1641 | - rn = "Framemask"; | |
1642 | - break; | |
2627 | + /* Officially reserved, but sel 0 is used for R1x000 framemask */ | |
2628 | + switch (sel) { | |
2629 | + case 0: | |
2630 | + gen_op_mtc0_framemask(); | |
2631 | + rn = "Framemask"; | |
2632 | + break; | |
2633 | + default: | |
2634 | + goto die; | |
2635 | + } | |
2636 | + break; | |
1643 | 2637 | case 22: |
1644 | -// ignore or except? | |
1645 | - rn = "Diagnostic"; | |
2638 | + /* ignored */ | |
2639 | + rn = "Diagnostic"; /* implementation dependent */ | |
1646 | 2640 | break; |
1647 | 2641 | case 23: |
1648 | - gen_op_mtc0_debug(); | |
1649 | - rn = "Debug"; | |
2642 | + switch (sel) { | |
2643 | + case 0: | |
2644 | + gen_op_mtc0_debug(); /* EJTAG support */ | |
2645 | + rn = "Debug"; | |
2646 | + break; | |
2647 | + case 1: | |
2648 | +// gen_op_mtc0_tracecontrol(); /* PDtrace support */ | |
2649 | + rn = "TraceControl"; | |
2650 | +// break; | |
2651 | + case 2: | |
2652 | +// gen_op_mtc0_tracecontrol2(); /* PDtrace support */ | |
2653 | + rn = "TraceControl2"; | |
2654 | +// break; | |
2655 | + case 3: | |
2656 | +// gen_op_mtc0_usertracedata(); /* PDtrace support */ | |
2657 | + rn = "UserTraceData"; | |
2658 | +// break; | |
2659 | + case 4: | |
2660 | +// gen_op_mtc0_debug(); /* PDtrace support */ | |
2661 | + rn = "TraceBPC"; | |
2662 | +// break; | |
2663 | + default: | |
2664 | + goto die; | |
2665 | + } | |
2666 | + /* Stop translation as we may have switched the execution mode */ | |
2667 | + ctx->bstate = BS_STOP; | |
1650 | 2668 | break; |
1651 | 2669 | case 24: |
1652 | - gen_op_mtc0_depc(); | |
1653 | - rn = "DEPC"; | |
2670 | + switch (sel) { | |
2671 | + case 0: | |
2672 | + gen_op_mtc0_depc(); /* EJTAG support */ | |
2673 | + rn = "DEPC"; | |
2674 | + break; | |
2675 | + default: | |
2676 | + goto die; | |
2677 | + } | |
1654 | 2678 | break; |
1655 | 2679 | case 25: |
1656 | -// ignore or except? | |
1657 | - rn = "Performance"; | |
2680 | + switch (sel) { | |
2681 | + case 0: | |
2682 | + gen_op_mtc0_performance0(); | |
2683 | + rn = "Performance0"; | |
2684 | + break; | |
2685 | + case 1: | |
2686 | +// gen_op_mtc0_performance1(); | |
2687 | + rn = "Performance1"; | |
2688 | +// break; | |
2689 | + case 2: | |
2690 | +// gen_op_mtc0_performance2(); | |
2691 | + rn = "Performance2"; | |
2692 | +// break; | |
2693 | + case 3: | |
2694 | +// gen_op_mtc0_performance3(); | |
2695 | + rn = "Performance3"; | |
2696 | +// break; | |
2697 | + case 4: | |
2698 | +// gen_op_mtc0_performance4(); | |
2699 | + rn = "Performance4"; | |
2700 | +// break; | |
2701 | + case 5: | |
2702 | +// gen_op_mtc0_performance5(); | |
2703 | + rn = "Performance5"; | |
2704 | +// break; | |
2705 | + case 6: | |
2706 | +// gen_op_mtc0_performance6(); | |
2707 | + rn = "Performance6"; | |
2708 | +// break; | |
2709 | + case 7: | |
2710 | +// gen_op_mtc0_performance7(); | |
2711 | + rn = "Performance7"; | |
2712 | +// break; | |
2713 | + default: | |
2714 | + goto die; | |
2715 | + } | |
1658 | 2716 | break; |
1659 | 2717 | case 26: |
1660 | -// ignore or except? | |
2718 | + /* ignored */ | |
1661 | 2719 | rn = "ECC"; |
1662 | 2720 | break; |
1663 | 2721 | case 27: |
1664 | -// ignore or except? | |
1665 | - rn = "CacheErr"; | |
2722 | + switch (sel) { | |
2723 | + case 0 ... 3: | |
2724 | + /* ignored */ | |
2725 | + rn = "CacheErr"; | |
2726 | + break; | |
2727 | + default: | |
2728 | + goto die; | |
2729 | + } | |
1666 | 2730 | break; |
1667 | 2731 | case 28: |
1668 | 2732 | switch (sel) { |
1669 | 2733 | case 0: |
2734 | + case 2: | |
2735 | + case 4: | |
2736 | + case 6: | |
1670 | 2737 | gen_op_mtc0_taglo(); |
1671 | 2738 | rn = "TagLo"; |
1672 | 2739 | break; |
2740 | + case 1: | |
2741 | + case 3: | |
2742 | + case 5: | |
2743 | + case 7: | |
2744 | + gen_op_mtc0_datalo(); | |
2745 | + rn = "DataLo"; | |
2746 | + break; | |
1673 | 2747 | default: |
1674 | - rn = "invalid sel"; | |
1675 | 2748 | goto die; |
1676 | 2749 | } |
1677 | 2750 | break; |
1678 | 2751 | case 29: |
1679 | -// gen_op_mtc0_taghi(); | |
1680 | - rn = "TagHi"; | |
2752 | + switch (sel) { | |
2753 | + case 0: | |
2754 | + case 2: | |
2755 | + case 4: | |
2756 | + case 6: | |
2757 | + gen_op_mtc0_taghi(); | |
2758 | + rn = "TagHi"; | |
2759 | + break; | |
2760 | + case 1: | |
2761 | + case 3: | |
2762 | + case 5: | |
2763 | + case 7: | |
2764 | + gen_op_mtc0_datahi(); | |
2765 | + rn = "DataHi"; | |
2766 | + break; | |
2767 | + default: | |
2768 | + rn = "invalid sel"; | |
2769 | + goto die; | |
2770 | + } | |
1681 | 2771 | break; |
1682 | 2772 | case 30: |
1683 | - gen_op_mtc0_errorepc(); | |
1684 | - rn = "ErrorEPC"; | |
2773 | + switch (sel) { | |
2774 | + case 0: | |
2775 | + gen_op_mtc0_errorepc(); | |
2776 | + rn = "ErrorEPC"; | |
2777 | + break; | |
2778 | + default: | |
2779 | + goto die; | |
2780 | + } | |
1685 | 2781 | break; |
1686 | 2782 | case 31: |
1687 | - gen_op_mtc0_desave(); | |
1688 | - rn = "DESAVE"; | |
2783 | + switch (sel) { | |
2784 | + case 0: | |
2785 | + gen_op_mtc0_desave(); /* EJTAG support */ | |
2786 | + rn = "DESAVE"; | |
2787 | + break; | |
2788 | + default: | |
2789 | + goto die; | |
2790 | + } | |
2791 | + /* Stop translation as we may have switched the execution mode */ | |
2792 | + ctx->bstate = BS_STOP; | |
1689 | 2793 | break; |
1690 | 2794 | default: |
1691 | - rn = "unknown"; | |
1692 | 2795 | goto die; |
1693 | 2796 | } |
1694 | 2797 | #if defined MIPS_DEBUG_DISAS |
1695 | 2798 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1696 | - fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", | |
1697 | - env->PC, rn, T0, reg, sel); | |
2799 | + fprintf(logfile, "mtc0 %s (reg %d sel %d)\n", | |
2800 | + rn, reg, sel); | |
1698 | 2801 | } |
1699 | 2802 | #endif |
1700 | 2803 | return; |
... | ... | @@ -1702,16 +2805,16 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel) |
1702 | 2805 | die: |
1703 | 2806 | #if defined MIPS_DEBUG_DISAS |
1704 | 2807 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1705 | - fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", | |
1706 | - env->PC, rn, T0, reg, sel); | |
2808 | + fprintf(logfile, "mtc0 %s (reg %d sel %d)\n", | |
2809 | + rn, reg, sel); | |
1707 | 2810 | } |
1708 | 2811 | #endif |
1709 | 2812 | generate_exception(ctx, EXCP_RI); |
1710 | 2813 | } |
1711 | 2814 | |
1712 | -static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | |
2815 | +static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) | |
1713 | 2816 | { |
1714 | - const unsigned char *opn = "unk"; | |
2817 | + const char *opn = "unk"; | |
1715 | 2818 | |
1716 | 2819 | if (!(ctx->CP0_Status & (1 << CP0St_CU0)) && |
1717 | 2820 | (ctx->hflags & MIPS_HFLAG_UM) && |
... | ... | @@ -1720,7 +2823,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) |
1720 | 2823 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1721 | 2824 | fprintf(logfile, "CP0 is not usable\n"); |
1722 | 2825 | } |
1723 | - generate_exception_err (ctx, EXCP_CpU, 0); | |
2826 | + generate_exception (ctx, EXCP_CpU); | |
1724 | 2827 | return; |
1725 | 2828 | } |
1726 | 2829 | |
... | ... | @@ -1736,13 +2839,12 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) |
1736 | 2839 | break; |
1737 | 2840 | case OPC_MTC0: |
1738 | 2841 | /* If we get an exception, we want to restart at next instruction */ |
2842 | + /* XXX: breaks for mtc in delay slot */ | |
1739 | 2843 | ctx->pc += 4; |
1740 | 2844 | save_cpu_state(ctx, 1); |
1741 | 2845 | ctx->pc -= 4; |
1742 | 2846 | GEN_LOAD_REG_TN(T0, rt); |
1743 | 2847 | gen_mtc0(ctx, rd, ctx->opcode & 0x7); |
1744 | - /* Stop translation as we may have switched the execution mode */ | |
1745 | - ctx->bstate = BS_STOP; | |
1746 | 2848 | opn = "mtc0"; |
1747 | 2849 | break; |
1748 | 2850 | #if defined(MIPS_USES_R4K_TLB) |
... | ... | @@ -1800,31 +2902,30 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) |
1800 | 2902 | MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd); |
1801 | 2903 | } |
1802 | 2904 | |
1803 | -#ifdef MIPS_USES_FPU | |
1804 | 2905 | /* CP1 Branches (before delay slot) */ |
1805 | -static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond, | |
2906 | +static void gen_compute_branch1 (DisasContext *ctx, uint32_t op, | |
1806 | 2907 | int32_t offset) |
1807 | 2908 | { |
1808 | 2909 | target_ulong btarget; |
1809 | 2910 | |
1810 | 2911 | btarget = ctx->pc + 4 + offset; |
1811 | 2912 | |
1812 | - switch (cond) { | |
1813 | - case 0x0000: /* bc1f */ | |
2913 | + switch (op) { | |
2914 | + case OPC_BC1F: | |
1814 | 2915 | gen_op_bc1f(); |
1815 | 2916 | MIPS_DEBUG("bc1f %08x", btarget); |
1816 | 2917 | goto not_likely; |
1817 | - case 0x0002: /* bc1fl */ | |
2918 | + case OPC_BC1FL: | |
1818 | 2919 | gen_op_bc1f(); |
1819 | 2920 | MIPS_DEBUG("bc1fl %08x", btarget); |
1820 | 2921 | goto likely; |
1821 | - case 0x0001: /* bc1t */ | |
2922 | + case OPC_BC1T: | |
1822 | 2923 | gen_op_bc1t(); |
1823 | 2924 | MIPS_DEBUG("bc1t %08x", btarget); |
1824 | 2925 | not_likely: |
1825 | 2926 | ctx->hflags |= MIPS_HFLAG_BC; |
1826 | 2927 | break; |
1827 | - case 0x0003: /* bc1tl */ | |
2928 | + case OPC_BC1TL: | |
1828 | 2929 | gen_op_bc1t(); |
1829 | 2930 | MIPS_DEBUG("bc1tl %08x", btarget); |
1830 | 2931 | likely: |
... | ... | @@ -1832,7 +2933,7 @@ static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond, |
1832 | 2933 | break; |
1833 | 2934 | default: |
1834 | 2935 | MIPS_INVAL("cp1 branch/jump"); |
1835 | - generate_exception(ctx, EXCP_RI); | |
2936 | + generate_exception_err (ctx, EXCP_RI, 1); | |
1836 | 2937 | return; |
1837 | 2938 | } |
1838 | 2939 | gen_op_set_bcond(); |
... | ... | @@ -1845,9 +2946,9 @@ static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond, |
1845 | 2946 | } |
1846 | 2947 | |
1847 | 2948 | /* Coprocessor 1 (FPU) */ |
1848 | -static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | |
2949 | +static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) | |
1849 | 2950 | { |
1850 | - const unsigned char *opn = "unk"; | |
2951 | + const char *opn = "unk"; | |
1851 | 2952 | |
1852 | 2953 | switch (opc) { |
1853 | 2954 | case OPC_MFC1: |
... | ... | @@ -1865,7 +2966,7 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) |
1865 | 2966 | case OPC_CFC1: |
1866 | 2967 | if (fs != 0 && fs != 31) { |
1867 | 2968 | MIPS_INVAL("cfc1 freg"); |
1868 | - generate_exception(ctx, EXCP_RI); | |
2969 | + generate_exception_err (ctx, EXCP_RI, 1); | |
1869 | 2970 | return; |
1870 | 2971 | } |
1871 | 2972 | GEN_LOAD_IMM_TN(T1, fs); |
... | ... | @@ -1874,9 +2975,9 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) |
1874 | 2975 | opn = "cfc1"; |
1875 | 2976 | break; |
1876 | 2977 | case OPC_CTC1: |
1877 | - if (fs != 0 && fs != 31) { | |
2978 | + if (fs != 0 && fs != 31) { | |
1878 | 2979 | MIPS_INVAL("ctc1 freg"); |
1879 | - generate_exception(ctx, EXCP_RI); | |
2980 | + generate_exception_err (ctx, EXCP_RI, 1); | |
1880 | 2981 | return; |
1881 | 2982 | } |
1882 | 2983 | GEN_LOAD_IMM_TN(T1, fs); |
... | ... | @@ -1890,7 +2991,7 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) |
1890 | 2991 | ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F, |
1891 | 2992 | ((ctx->opcode >> 16) & 0x1F)); |
1892 | 2993 | } |
1893 | - generate_exception(ctx, EXCP_RI); | |
2994 | + generate_exception_err (ctx, EXCP_RI, 1); | |
1894 | 2995 | return; |
1895 | 2996 | } |
1896 | 2997 | MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]); |
... | ... | @@ -1908,16 +3009,16 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) |
1908 | 3009 | */ |
1909 | 3010 | #define CHECK_FR(ctx, freg) do { \ |
1910 | 3011 | if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \ |
1911 | - generate_exception(ctx, EXCP_RI); \ | |
3012 | + generate_exception_err (ctx, EXCP_RI, 1); \ | |
1912 | 3013 | return; \ |
1913 | 3014 | } \ |
1914 | 3015 | } while(0) |
1915 | 3016 | |
1916 | 3017 | #define FOP(func, fmt) (((fmt) << 21) | (func)) |
1917 | 3018 | |
1918 | -static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int func) | |
3019 | +static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd) | |
1919 | 3020 | { |
1920 | - const unsigned char *opn = "unk"; | |
3021 | + const char *opn = "unk"; | |
1921 | 3022 | const char *condnames[] = { |
1922 | 3023 | "c.f", |
1923 | 3024 | "c.un", |
... | ... | @@ -1937,7 +3038,8 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int |
1937 | 3038 | "c.ngt", |
1938 | 3039 | }; |
1939 | 3040 | int binary = 0; |
1940 | - | |
3041 | + uint32_t func = ctx->opcode & 0x3f; | |
3042 | + | |
1941 | 3043 | switch (ctx->opcode & FOP(0x3f, 0x1f)) { |
1942 | 3044 | case FOP(0, 17): |
1943 | 3045 | CHECK_FR(ctx, fs | ft | fd); |
... | ... | @@ -2033,7 +3135,7 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int |
2033 | 3135 | GEN_LOAD_FREG_FTN(DT0, fs); |
2034 | 3136 | gen_op_float_floorw_d(); |
2035 | 3137 | GEN_STORE_FTN_FREG(fd, WT2); |
2036 | - opn = "ceil.w.d"; | |
3138 | + opn = "floor.w.d"; | |
2037 | 3139 | break; |
2038 | 3140 | case FOP(33, 16): /* cvt.d.s */ |
2039 | 3141 | CHECK_FR(ctx, fs | fd); |
... | ... | @@ -2201,11 +3303,11 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int |
2201 | 3303 | break; |
2202 | 3304 | default: |
2203 | 3305 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
2204 | - fprintf(logfile, "Invalid arith function: %08x %03x %03x %03x\n", | |
3306 | + fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n", | |
2205 | 3307 | ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F, |
2206 | 3308 | ((ctx->opcode >> 16) & 0x1F)); |
2207 | 3309 | } |
2208 | - generate_exception(ctx, EXCP_RI); | |
3310 | + generate_exception_err (ctx, EXCP_RI, 1); | |
2209 | 3311 | return; |
2210 | 3312 | } |
2211 | 3313 | if (binary) |
... | ... | @@ -2213,14 +3315,27 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int |
2213 | 3315 | else |
2214 | 3316 | MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); |
2215 | 3317 | } |
2216 | -#endif | |
2217 | 3318 | |
2218 | -/* ISA extensions */ | |
3319 | +static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf) | |
3320 | +{ | |
3321 | + uint32_t ccbit; | |
3322 | + | |
3323 | + if (cc) | |
3324 | + ccbit = 1 << (24 + cc); | |
3325 | + else | |
3326 | + ccbit = 1 << 23; | |
3327 | + if (!tf) | |
3328 | + gen_op_movf(ccbit, rd, rs); | |
3329 | + else | |
3330 | + gen_op_movt(ccbit, rd, rs); | |
3331 | +} | |
3332 | + | |
3333 | +/* ISA extensions (ASEs) */ | |
2219 | 3334 | /* MIPS16 extension to MIPS32 */ |
2220 | 3335 | /* SmartMIPS extension to MIPS32 */ |
2221 | 3336 | |
2222 | -#ifdef TARGET_MIPS64 | |
2223 | -static void gen_arith64 (DisasContext *ctx, uint16_t opc) | |
3337 | +#ifdef MIPS_HAS_MIPS64 | |
3338 | +static void gen_arith64 (DisasContext *ctx, uint32_t opc) | |
2224 | 3339 | { |
2225 | 3340 | if (func == 0x02 && rd == 0) { |
2226 | 3341 | /* NOP */ |
... | ... | @@ -2265,7 +3380,7 @@ static void decode_opc (DisasContext *ctx) |
2265 | 3380 | { |
2266 | 3381 | int32_t offset; |
2267 | 3382 | int rs, rt, rd, sa; |
2268 | - uint16_t op, op1; | |
3383 | + uint32_t op, op1, op2; | |
2269 | 3384 | int16_t imm; |
2270 | 3385 | |
2271 | 3386 | /* make sure instructions are on a word boundary */ |
... | ... | @@ -2279,76 +3394,86 @@ static void decode_opc (DisasContext *ctx) |
2279 | 3394 | MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4); |
2280 | 3395 | gen_blikely(ctx); |
2281 | 3396 | } |
2282 | - op = ctx->opcode >> 26; | |
2283 | - rs = ((ctx->opcode >> 21) & 0x1F); | |
2284 | - rt = ((ctx->opcode >> 16) & 0x1F); | |
2285 | - rd = ((ctx->opcode >> 11) & 0x1F); | |
2286 | - sa = ((ctx->opcode >> 6) & 0x1F); | |
3397 | + op = MASK_OP_MAJOR(ctx->opcode); | |
3398 | + rs = (ctx->opcode >> 21) & 0x1f; | |
3399 | + rt = (ctx->opcode >> 16) & 0x1f; | |
3400 | + rd = (ctx->opcode >> 11) & 0x1f; | |
3401 | + sa = (ctx->opcode >> 6) & 0x1f; | |
2287 | 3402 | imm = (int16_t)ctx->opcode; |
2288 | 3403 | switch (op) { |
2289 | - case 0x00: /* Special opcode */ | |
2290 | - op1 = ctx->opcode & 0x3F; | |
3404 | + case OPC_SPECIAL: | |
3405 | + op1 = MASK_SPECIAL(ctx->opcode); | |
2291 | 3406 | switch (op1) { |
2292 | - case 0x00: /* Arithmetic with immediate */ | |
2293 | - case 0x02 ... 0x03: | |
2294 | - gen_arith_imm(ctx, op1 | EXT_SPECIAL, rd, rt, sa); | |
2295 | - break; | |
2296 | - case 0x04: /* Arithmetic */ | |
2297 | - case 0x06 ... 0x07: | |
2298 | - case 0x0A ... 0x0B: | |
2299 | - case 0x20 ... 0x27: | |
2300 | - case 0x2A ... 0x2B: | |
2301 | - gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt); | |
2302 | - break; | |
2303 | - case 0x18 ... 0x1B: /* MULT / DIV */ | |
2304 | - gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt); | |
2305 | - break; | |
2306 | - case 0x08 ... 0x09: /* Jumps */ | |
2307 | - gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa); | |
3407 | + case OPC_SLL: /* Arithmetic with immediate */ | |
3408 | + case OPC_SRL ... OPC_SRA: | |
3409 | + gen_arith_imm(ctx, op1, rd, rt, sa); | |
3410 | + break; | |
3411 | + case OPC_SLLV: /* Arithmetic */ | |
3412 | + case OPC_SRLV ... OPC_SRAV: | |
3413 | + case OPC_MOVZ ... OPC_MOVN: | |
3414 | + case OPC_ADD ... OPC_NOR: | |
3415 | + case OPC_SLT ... OPC_SLTU: | |
3416 | + gen_arith(ctx, op1, rd, rs, rt); | |
3417 | + break; | |
3418 | + case OPC_MULT ... OPC_DIVU: | |
3419 | + gen_muldiv(ctx, op1, rs, rt); | |
3420 | + break; | |
3421 | + case OPC_JR ... OPC_JALR: | |
3422 | + gen_compute_branch(ctx, op1, rs, rd, sa); | |
2308 | 3423 | return; |
2309 | - case 0x30 ... 0x34: /* Traps */ | |
2310 | - case 0x36: | |
2311 | - gen_trap(ctx, op1 | EXT_SPECIAL, rs, rt, -1); | |
3424 | + case OPC_TGE ... OPC_TEQ: /* Traps */ | |
3425 | + case OPC_TNE: | |
3426 | + gen_trap(ctx, op1, rs, rt, -1); | |
2312 | 3427 | break; |
2313 | - case 0x10: /* Move from HI/LO */ | |
2314 | - case 0x12: | |
2315 | - gen_HILO(ctx, op1 | EXT_SPECIAL, rd); | |
3428 | + case OPC_MFHI: /* Move from HI/LO */ | |
3429 | + case OPC_MFLO: | |
3430 | + gen_HILO(ctx, op1, rd); | |
2316 | 3431 | break; |
2317 | - case 0x11: | |
2318 | - case 0x13: /* Move to HI/LO */ | |
2319 | - gen_HILO(ctx, op1 | EXT_SPECIAL, rs); | |
3432 | + case OPC_MTHI: | |
3433 | + case OPC_MTLO: /* Move to HI/LO */ | |
3434 | + gen_HILO(ctx, op1, rs); | |
2320 | 3435 | break; |
2321 | - case 0x0C: /* SYSCALL */ | |
3436 | + case OPC_PMON: /* Pmon entry point */ | |
3437 | + gen_op_pmon(sa); | |
3438 | + break; | |
3439 | + case OPC_SYSCALL: | |
2322 | 3440 | generate_exception(ctx, EXCP_SYSCALL); |
3441 | + ctx->bstate = BS_EXCP; | |
2323 | 3442 | break; |
2324 | - case 0x0D: /* BREAK */ | |
3443 | + case OPC_BREAK: | |
2325 | 3444 | generate_exception(ctx, EXCP_BREAK); |
2326 | 3445 | break; |
2327 | - case 0x0F: /* SYNC */ | |
2328 | - /* Treat as a noop */ | |
3446 | + case OPC_SPIM: /* SPIM ? */ | |
3447 | + /* Implemented as RI exception for now. */ | |
3448 | + MIPS_INVAL("spim (unofficial)"); | |
3449 | + generate_exception(ctx, EXCP_RI); | |
2329 | 3450 | break; |
2330 | - case 0x05: /* Pmon entry point */ | |
2331 | - gen_op_pmon((ctx->opcode >> 6) & 0x1F); | |
3451 | + case OPC_SYNC: | |
3452 | + /* Treat as a noop. */ | |
2332 | 3453 | break; |
2333 | 3454 | |
2334 | - case 0x01: /* MOVCI */ | |
2335 | -#if defined (MIPS_HAS_MOVCI) | |
2336 | - /* XXX */ | |
2337 | -#else | |
2338 | - /* Not implemented */ | |
2339 | - generate_exception_err (ctx, EXCP_CpU, 1); | |
2340 | -#endif | |
3455 | + case OPC_MOVCI: | |
3456 | + gen_op_cp1_enabled(); | |
3457 | + gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7, | |
3458 | + (ctx->opcode >> 16) & 1); | |
2341 | 3459 | break; |
2342 | 3460 | |
2343 | -#if defined (TARGET_MIPS64) | |
2344 | - case 0x14: /* MIPS64 specific opcodes */ | |
2345 | - case 0x16: | |
2346 | - case 0x17: | |
2347 | - case 0x1C ... 0x1F: | |
2348 | - case 0x2C ... 0x2F: | |
2349 | - case 0x37: | |
2350 | - case 0x39 ... 0x3B: | |
2351 | - case 0x3E ... 0x3F: | |
3461 | +#ifdef MIPS_HAS_MIPS64 | |
3462 | + /* MIPS64 specific opcodes */ | |
3463 | + case OPC_DSLL: | |
3464 | + case OPC_DSRL ... OPC_DSRA: | |
3465 | + case OPC_DSLL32: | |
3466 | + case OPC_DSRL32 ... OPC_DSRA32: | |
3467 | + gen_arith_imm(ctx, op1, rd, rt, sa); | |
3468 | + break; | |
3469 | + case OPC_DSLLV: | |
3470 | + case OPC_DSRLV ... OPC_DSRAV: | |
3471 | + case OPC_DADD ... OPC_DSUBU: | |
3472 | + gen_arith(ctx, op1, rd, rs, rt); | |
3473 | + break; | |
3474 | + case OPC_DMULT ... OPC_DDIVU: | |
3475 | + gen_muldiv(ctx, op1, rs, rt); | |
3476 | + break; | |
2352 | 3477 | #endif |
2353 | 3478 | default: /* Invalid */ |
2354 | 3479 | MIPS_INVAL("special"); |
... | ... | @@ -2356,23 +3481,20 @@ static void decode_opc (DisasContext *ctx) |
2356 | 3481 | break; |
2357 | 3482 | } |
2358 | 3483 | break; |
2359 | - case 0x1C: /* Special2 opcode */ | |
2360 | - op1 = ctx->opcode & 0x3F; | |
3484 | + case OPC_SPECIAL2: | |
3485 | + op1 = MASK_SPECIAL2(ctx->opcode); | |
2361 | 3486 | switch (op1) { |
2362 | -#if defined (MIPS_USES_R4K_EXT) | |
2363 | - /* Those instructions are not part of MIPS32 core */ | |
2364 | - case 0x00 ... 0x01: /* Multiply and add/sub */ | |
2365 | - case 0x04 ... 0x05: | |
2366 | - gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt); | |
3487 | + case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */ | |
3488 | + case OPC_MSUB ... OPC_MSUBU: | |
3489 | + gen_muldiv(ctx, op1, rs, rt); | |
2367 | 3490 | break; |
2368 | - case 0x02: /* MUL */ | |
2369 | - gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt); | |
3491 | + case OPC_MUL: | |
3492 | + gen_arith(ctx, op1, rd, rs, rt); | |
2370 | 3493 | break; |
2371 | - case 0x20 ... 0x21: /* CLO / CLZ */ | |
2372 | - gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs); | |
3494 | + case OPC_CLZ ... OPC_CLO: | |
3495 | + gen_cl(ctx, op1, rd, rs); | |
2373 | 3496 | break; |
2374 | -#endif | |
2375 | - case 0x3F: /* SDBBP */ | |
3497 | + case OPC_SDBBP: | |
2376 | 3498 | /* XXX: not clear which exception should be raised |
2377 | 3499 | * when in debug mode... |
2378 | 3500 | */ |
... | ... | @@ -2383,22 +3505,109 @@ static void decode_opc (DisasContext *ctx) |
2383 | 3505 | } |
2384 | 3506 | /* Treat as a noop */ |
2385 | 3507 | break; |
3508 | +#ifdef MIPS_HAS_MIPS64 | |
3509 | + case OPC_DCLZ ... OPC_DCLO: | |
3510 | + gen_cl(ctx, op1, rd, rs); | |
3511 | + break; | |
3512 | +#endif | |
2386 | 3513 | default: /* Invalid */ |
2387 | 3514 | MIPS_INVAL("special2"); |
2388 | 3515 | generate_exception(ctx, EXCP_RI); |
2389 | 3516 | break; |
2390 | 3517 | } |
2391 | 3518 | break; |
2392 | - case 0x01: /* B REGIMM opcode */ | |
2393 | - op1 = ((ctx->opcode >> 16) & 0x1F); | |
3519 | + case OPC_SPECIAL3: | |
3520 | + op1 = MASK_SPECIAL3(ctx->opcode); | |
2394 | 3521 | switch (op1) { |
2395 | - case 0x00 ... 0x03: /* REGIMM branches */ | |
2396 | - case 0x10 ... 0x13: | |
2397 | - gen_compute_branch(ctx, op1 | EXT_REGIMM, rs, -1, imm << 2); | |
3522 | + case OPC_EXT: | |
3523 | + case OPC_INS: | |
3524 | + gen_bitops(ctx, op1, rt, rs, sa, rd); | |
3525 | + break; | |
3526 | + case OPC_BSHFL: | |
3527 | + op2 = MASK_BSHFL(ctx->opcode); | |
3528 | + switch (op2) { | |
3529 | + case OPC_WSBH: | |
3530 | + GEN_LOAD_REG_TN(T1, rt); | |
3531 | + gen_op_wsbh(); | |
3532 | + break; | |
3533 | + case OPC_SEB: | |
3534 | + GEN_LOAD_REG_TN(T1, rt); | |
3535 | + gen_op_seb(); | |
3536 | + break; | |
3537 | + case OPC_SEH: | |
3538 | + GEN_LOAD_REG_TN(T1, rt); | |
3539 | + gen_op_seh(); | |
3540 | + break; | |
3541 | + default: /* Invalid */ | |
3542 | + MIPS_INVAL("bshfl"); | |
3543 | + generate_exception(ctx, EXCP_RI); | |
3544 | + break; | |
3545 | + } | |
3546 | + GEN_STORE_TN_REG(rd, T0); | |
3547 | + break; | |
3548 | + case OPC_RDHWR: | |
3549 | + switch (rd) { | |
3550 | + case 0: | |
3551 | + gen_op_rdhwr_cpunum(); | |
3552 | + break; | |
3553 | + case 1: | |
3554 | + gen_op_rdhwr_synci_step(); | |
3555 | + break; | |
3556 | + case 2: | |
3557 | + gen_op_rdhwr_cc(); | |
3558 | + break; | |
3559 | + case 3: | |
3560 | + gen_op_rdhwr_ccres(); | |
3561 | + break; | |
3562 | + default: /* Invalid */ | |
3563 | + MIPS_INVAL("rdhwr"); | |
3564 | + generate_exception(ctx, EXCP_RI); | |
3565 | + break; | |
3566 | + } | |
3567 | + GEN_STORE_TN_REG(rt, T0); | |
3568 | + break; | |
3569 | +#ifdef MIPS_HAS_MIPS64 | |
3570 | + case OPC_DEXTM ... OPC_DEXT: | |
3571 | + case OPC_DINSM ... OPC_DINS: | |
3572 | + gen_bitops(ctx, op1, rt, rs, sa, rd); | |
3573 | + break; | |
3574 | + case OPC_DBSHFL: | |
3575 | + op2 = MASK_DBSHFL(ctx->opcode); | |
3576 | + switch (op2) { | |
3577 | + case OPC_DSBH: | |
3578 | + GEN_LOAD_REG_TN(T1, rt); | |
3579 | + gen_op_dsbh(); | |
3580 | + break; | |
3581 | + case OPC_DSHD: | |
3582 | + GEN_LOAD_REG_TN(T1, rt); | |
3583 | + gen_op_dshd(); | |
3584 | + break; | |
3585 | + default: /* Invalid */ | |
3586 | + MIPS_INVAL("dbshfl"); | |
3587 | + generate_exception(ctx, EXCP_RI); | |
3588 | + break; | |
3589 | + } | |
3590 | + GEN_STORE_TN_REG(rd, T0); | |
3591 | +#endif | |
3592 | + default: /* Invalid */ | |
3593 | + MIPS_INVAL("special3"); | |
3594 | + generate_exception(ctx, EXCP_RI); | |
3595 | + break; | |
3596 | + } | |
3597 | + break; | |
3598 | + case OPC_REGIMM: | |
3599 | + op1 = MASK_REGIMM(ctx->opcode); | |
3600 | + switch (op1) { | |
3601 | + case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */ | |
3602 | + case OPC_BLTZAL ... OPC_BGEZALL: | |
3603 | + gen_compute_branch(ctx, op1, rs, -1, imm << 2); | |
2398 | 3604 | return; |
2399 | - case 0x08 ... 0x0C: /* Traps */ | |
2400 | - case 0x0E: | |
2401 | - gen_trap(ctx, op1 | EXT_REGIMM, rs, -1, imm); | |
3605 | + case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */ | |
3606 | + case OPC_TNEI: | |
3607 | + gen_trap(ctx, op1, rs, -1, imm); | |
3608 | + break; | |
3609 | + case OPC_SYNCI: | |
3610 | + /* treat as noop */ | |
2402 | 3611 | break; |
2403 | 3612 | default: /* Invalid */ |
2404 | 3613 | MIPS_INVAL("REGIMM"); |
... | ... | @@ -2406,48 +3615,78 @@ static void decode_opc (DisasContext *ctx) |
2406 | 3615 | break; |
2407 | 3616 | } |
2408 | 3617 | break; |
2409 | - case 0x10: /* CP0 opcode */ | |
2410 | - op1 = ((ctx->opcode >> 21) & 0x1F); | |
3618 | + case OPC_CP0: | |
3619 | + op1 = MASK_CP0(ctx->opcode); | |
2411 | 3620 | switch (op1) { |
2412 | - case 0x00: | |
2413 | - case 0x04: | |
2414 | - gen_cp0(ctx, op1 | EXT_CP0, rt, rd); | |
3621 | + case OPC_MFC0: | |
3622 | + case OPC_MTC0: | |
3623 | +#ifdef MIPS_HAS_MIPS64 | |
3624 | + case OPC_DMFC0: | |
3625 | + case OPC_DMTC0: | |
3626 | +#endif | |
3627 | + gen_cp0(ctx, op1, rt, rd); | |
3628 | + break; | |
3629 | + case OPC_C0_FIRST ... OPC_C0_LAST: | |
3630 | + gen_cp0(ctx, MASK_C0(ctx->opcode), rt, rd); | |
3631 | + break; | |
3632 | + case OPC_MFMC0: | |
3633 | + op2 = MASK_MFMC0(ctx->opcode); | |
3634 | + switch (op2) { | |
3635 | + case OPC_DI: | |
3636 | + gen_op_di(); | |
3637 | + /* Stop translation as we may have switched the execution mode */ | |
3638 | + ctx->bstate = BS_STOP; | |
3639 | + break; | |
3640 | + case OPC_EI: | |
3641 | + gen_op_ei(); | |
3642 | + /* Stop translation as we may have switched the execution mode */ | |
3643 | + ctx->bstate = BS_STOP; | |
3644 | + break; | |
3645 | + default: /* Invalid */ | |
3646 | + MIPS_INVAL("MFMC0"); | |
3647 | + generate_exception(ctx, EXCP_RI); | |
3648 | + break; | |
3649 | + } | |
3650 | + GEN_STORE_TN_REG(rt, T0); | |
2415 | 3651 | break; |
3652 | + /* Shadow registers (not implemented). */ | |
3653 | + case OPC_RDPGPR: | |
3654 | + case OPC_WRPGPR: | |
2416 | 3655 | default: |
2417 | - gen_cp0(ctx, (ctx->opcode & 0x3F) | EXT_CP0, rt, rd); | |
3656 | + generate_exception(ctx, EXCP_RI); | |
2418 | 3657 | break; |
2419 | 3658 | } |
2420 | 3659 | break; |
2421 | - case 0x08 ... 0x0F: /* Arithmetic with immediate opcode */ | |
2422 | - gen_arith_imm(ctx, op, rt, rs, imm); | |
2423 | - break; | |
2424 | - case 0x02 ... 0x03: /* Jump */ | |
2425 | - offset = (int32_t)(ctx->opcode & 0x03FFFFFF) << 2; | |
2426 | - gen_compute_branch(ctx, op, rs, rt, offset); | |
2427 | - return; | |
2428 | - case 0x04 ... 0x07: /* Branch */ | |
2429 | - case 0x14 ... 0x17: | |
2430 | - gen_compute_branch(ctx, op, rs, rt, imm << 2); | |
2431 | - return; | |
2432 | - case 0x20 ... 0x2E: /* Load and stores */ | |
2433 | - case 0x30: | |
2434 | - case 0x38: | |
2435 | - gen_ldst(ctx, op, rt, rs, imm); | |
2436 | - break; | |
2437 | - case 0x2F: /* Cache operation */ | |
2438 | - /* Treat as a noop */ | |
2439 | - break; | |
2440 | - case 0x33: /* Prefetch */ | |
3660 | + case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */ | |
3661 | + gen_arith_imm(ctx, op, rt, rs, imm); | |
3662 | + break; | |
3663 | + case OPC_J ... OPC_JAL: /* Jump */ | |
3664 | + offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; | |
3665 | + gen_compute_branch(ctx, op, rs, rt, offset); | |
3666 | + return; | |
3667 | + case OPC_BEQ ... OPC_BGTZ: /* Branch */ | |
3668 | + case OPC_BEQL ... OPC_BGTZL: | |
3669 | + gen_compute_branch(ctx, op, rs, rt, imm << 2); | |
3670 | + return; | |
3671 | + case OPC_LB ... OPC_LWR: /* Load and stores */ | |
3672 | + case OPC_SB ... OPC_SW: | |
3673 | + case OPC_SWR: | |
3674 | + case OPC_LL: | |
3675 | + case OPC_SC: | |
3676 | + gen_ldst(ctx, op, rt, rs, imm); | |
3677 | + break; | |
3678 | + case OPC_CACHE: | |
3679 | + /* Treat as a noop */ | |
3680 | + break; | |
3681 | + case OPC_PREF: | |
2441 | 3682 | /* Treat as a noop */ |
2442 | 3683 | break; |
2443 | - case 0x3F: /* HACK */ | |
2444 | - break; | |
2445 | 3684 | |
2446 | 3685 | /* Floating point. */ |
2447 | - case 0x31: /* LWC1 */ | |
2448 | - case 0x35: /* LDC1 */ | |
2449 | - case 0x39: /* SWC1 */ | |
2450 | - case 0x3D: /* SDC1 */ | |
3686 | + case OPC_LWC1: | |
3687 | + case OPC_LDC1: | |
3688 | + case OPC_SWC1: | |
3689 | + case OPC_SDC1: | |
2451 | 3690 | #if defined(MIPS_USES_FPU) |
2452 | 3691 | save_cpu_state(ctx, 1); |
2453 | 3692 | gen_op_cp1_enabled(); |
... | ... | @@ -2457,65 +3696,80 @@ static void decode_opc (DisasContext *ctx) |
2457 | 3696 | #endif |
2458 | 3697 | break; |
2459 | 3698 | |
2460 | - case 0x11: /* CP1 opcode */ | |
3699 | + case OPC_CP1: | |
2461 | 3700 | #if defined(MIPS_USES_FPU) |
2462 | 3701 | save_cpu_state(ctx, 1); |
2463 | 3702 | gen_op_cp1_enabled(); |
2464 | - op1 = ((ctx->opcode >> 21) & 0x1F); | |
3703 | + op1 = MASK_CP1(ctx->opcode); | |
2465 | 3704 | switch (op1) { |
2466 | - case 0x00: /* mfc1 */ | |
2467 | - case 0x02: /* cfc1 */ | |
2468 | - case 0x04: /* mtc1 */ | |
2469 | - case 0x06: /* ctc1 */ | |
2470 | - gen_cp1(ctx, op1 | EXT_CP1, rt, rd); | |
2471 | - break; | |
2472 | - case 0x08: /* bc */ | |
2473 | - gen_compute_branch1(ctx, rt, imm << 2); | |
3705 | + case OPC_MFC1: | |
3706 | + case OPC_CFC1: | |
3707 | + case OPC_MTC1: | |
3708 | + case OPC_CTC1: | |
3709 | + gen_cp1(ctx, op1, rt, rd); | |
3710 | + break; | |
3711 | + case OPC_BC1: | |
3712 | + gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2); | |
2474 | 3713 | return; |
2475 | - case 0x10: /* 16: fmt=single fp */ | |
2476 | - case 0x11: /* 17: fmt=double fp */ | |
2477 | - case 0x14: /* 20: fmt=32bit fixed */ | |
2478 | - case 0x15: /* 21: fmt=64bit fixed */ | |
2479 | - gen_farith(ctx, op1, rt, rd, sa, ctx->opcode & 0x3f); | |
3714 | + case OPC_S_FMT: | |
3715 | + case OPC_D_FMT: | |
3716 | + case OPC_W_FMT: | |
3717 | + case OPC_L_FMT: | |
3718 | + gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa); | |
2480 | 3719 | break; |
2481 | 3720 | default: |
2482 | 3721 | generate_exception_err(ctx, EXCP_RI, 1); |
2483 | 3722 | break; |
2484 | 3723 | } |
2485 | - break; | |
2486 | 3724 | #else |
2487 | 3725 | generate_exception_err(ctx, EXCP_CpU, 1); |
2488 | 3726 | #endif |
2489 | 3727 | break; |
2490 | 3728 | |
2491 | 3729 | /* COP2. */ |
2492 | - case 0x32: /* LWC2 */ | |
2493 | - case 0x36: /* LDC2 */ | |
2494 | - case 0x3A: /* SWC2 */ | |
2495 | - case 0x3E: /* SDC2 */ | |
2496 | - case 0x12: /* CP2 opcode */ | |
2497 | - /* Not implemented */ | |
3730 | + case OPC_LWC2: | |
3731 | + case OPC_LDC2: | |
3732 | + case OPC_SWC2: | |
3733 | + case OPC_SDC2: | |
3734 | + case OPC_CP2: | |
3735 | + /* COP2: Not implemented. */ | |
2498 | 3736 | generate_exception_err(ctx, EXCP_CpU, 2); |
2499 | 3737 | break; |
2500 | 3738 | |
2501 | - case 0x13: /* CP3 opcode */ | |
3739 | + case OPC_CP3: | |
3740 | + gen_op_cp1_enabled(); | |
3741 | + op1 = MASK_CP3(ctx->opcode); | |
3742 | + switch (op1) { | |
2502 | 3743 | /* Not implemented */ |
2503 | - generate_exception_err(ctx, EXCP_CpU, 3); | |
3744 | + default: | |
3745 | + generate_exception_err(ctx, EXCP_RI, 1); | |
3746 | + break; | |
3747 | + } | |
2504 | 3748 | break; |
2505 | 3749 | |
2506 | -#if defined (TARGET_MIPS64) | |
2507 | - case 0x18 ... 0x1B: | |
2508 | - case 0x27: | |
2509 | - case 0x34: | |
2510 | - case 0x37: | |
2511 | - /* MIPS64 opcodes */ | |
3750 | +#ifdef MIPS_HAS_MIPS64 | |
3751 | + /* MIPS64 opcodes */ | |
3752 | + case OPC_LWU: | |
3753 | + case OPC_LDL ... OPC_LDR: | |
3754 | + case OPC_SDL ... OPC_SDR: | |
3755 | + case OPC_LLD: | |
3756 | + case OPC_LD: | |
3757 | + case OPC_SCD: | |
3758 | + case OPC_SD: | |
3759 | + gen_ldst(ctx, op, rt, rs, imm); | |
3760 | + break; | |
3761 | + case OPC_DADDI ... OPC_DADDIU: | |
3762 | + gen_arith_imm(ctx, op, rt, rs, imm); | |
3763 | + break; | |
2512 | 3764 | #endif |
2513 | -#if defined (MIPS_HAS_JALX) | |
2514 | - case 0x1D: | |
2515 | - /* JALX: not implemented */ | |
3765 | +#ifdef MIPS_HAS_MIPS16 | |
3766 | + case OPC_JALX: | |
3767 | + /* MIPS16: Not implemented. */ | |
3768 | +#endif | |
3769 | +#ifdef MIPS_HAS_MDMX | |
3770 | + case OPC_MDMX: | |
3771 | + /* MDMX: Not implemented. */ | |
2516 | 3772 | #endif |
2517 | - case 0x1E: | |
2518 | - /* ASE specific */ | |
2519 | 3773 | default: /* Invalid */ |
2520 | 3774 | MIPS_INVAL(""); |
2521 | 3775 | generate_exception(ctx, EXCP_RI); |
... | ... | @@ -2707,7 +3961,6 @@ int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) |
2707 | 3961 | return gen_intermediate_code_internal(env, tb, 1); |
2708 | 3962 | } |
2709 | 3963 | |
2710 | -#ifdef MIPS_USES_FPU | |
2711 | 3964 | void fpu_dump_state(CPUState *env, FILE *f, |
2712 | 3965 | int (*fpu_fprintf)(FILE *f, const char *fmt, ...), |
2713 | 3966 | int flags) |
... | ... | @@ -2721,19 +3974,19 @@ void fpu_dump_state(CPUState *env, FILE *f, |
2721 | 3974 | |
2722 | 3975 | fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d\n", |
2723 | 3976 | env->fcr0, env->fcr31, |
2724 | - (env->CP0_Status & (1<<CP0St_FR)) != 0); | |
3977 | + (env->CP0_Status & (1 << CP0St_FR)) != 0); | |
2725 | 3978 | fpu_fprintf(f, "FT0: "); printfpr(&env->ft0); |
2726 | 3979 | fpu_fprintf(f, "FT1: "); printfpr(&env->ft1); |
2727 | 3980 | fpu_fprintf(f, "FT2: "); printfpr(&env->ft2); |
2728 | - for(i=0; i < 32; i+=2) { | |
2729 | - fpu_fprintf(f, "f%02d: ", i); | |
3981 | + for(i = 0; i < 32; i += 2) { | |
3982 | + fpu_fprintf(f, "%s: ", fregnames[i]); | |
2730 | 3983 | printfpr(FPR(env, i)); |
2731 | 3984 | } |
2732 | 3985 | |
2733 | 3986 | #undef printfpr |
2734 | 3987 | } |
2735 | 3988 | |
2736 | -void dump_fpu(CPUState *env) | |
3989 | +void dump_fpu (CPUState *env) | |
2737 | 3990 | { |
2738 | 3991 | if (loglevel) { |
2739 | 3992 | fprintf(logfile, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n", |
... | ... | @@ -2741,7 +3994,6 @@ void dump_fpu(CPUState *env) |
2741 | 3994 | fpu_dump_state(env, logfile, fprintf, 0); |
2742 | 3995 | } |
2743 | 3996 | } |
2744 | -#endif /* MIPS_USES_FPU */ | |
2745 | 3997 | |
2746 | 3998 | void cpu_dump_state (CPUState *env, FILE *f, |
2747 | 3999 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...), |
... | ... | @@ -2772,9 +4024,8 @@ void cpu_dump_state (CPUState *env, FILE *f, |
2772 | 4024 | c0_status, env->CP0_Cause, env->CP0_EPC); |
2773 | 4025 | cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n", |
2774 | 4026 | env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr); |
2775 | -#ifdef MIPS_USES_FPU | |
2776 | - fpu_dump_state(env, f, cpu_fprintf, flags); | |
2777 | -#endif | |
4027 | + if (c0_status & (1 << CP0St_CU1)) | |
4028 | + fpu_dump_state(env, f, cpu_fprintf, flags); | |
2778 | 4029 | } |
2779 | 4030 | |
2780 | 4031 | CPUMIPSState *cpu_mips_init (void) |
... | ... | @@ -2802,16 +4053,12 @@ void cpu_reset (CPUMIPSState *env) |
2802 | 4053 | env->tlb_in_use = MIPS_TLB_NB; |
2803 | 4054 | #endif |
2804 | 4055 | env->CP0_Wired = 0; |
4056 | + /* SMP not implemented */ | |
4057 | + env->CP0_EBase = 0x80000000; | |
2805 | 4058 | env->CP0_Config0 = MIPS_CONFIG0; |
2806 | -#if defined (MIPS_CONFIG1) | |
2807 | - env->CP0_Config1 = MIPS_CONFIG1; | |
2808 | -#endif | |
2809 | -#if defined (MIPS_CONFIG2) | |
2810 | - env->CP0_Config2 = MIPS_CONFIG2; | |
2811 | -#endif | |
2812 | -#if defined (MIPS_CONFIG3) | |
2813 | - env->CP0_Config3 = MIPS_CONFIG3; | |
2814 | -#endif | |
4059 | + env->CP0_Config1 = MIPS_CONFIG1; | |
4060 | + env->CP0_Config2 = MIPS_CONFIG2; | |
4061 | + env->CP0_Config3 = MIPS_CONFIG3; | |
2815 | 4062 | env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); |
2816 | 4063 | env->CP0_WatchLo = 0; |
2817 | 4064 | env->hflags = MIPS_HFLAG_ERL; |
... | ... | @@ -2825,4 +4072,7 @@ void cpu_reset (CPUMIPSState *env) |
2825 | 4072 | #ifdef MIPS_USES_FPU |
2826 | 4073 | env->fcr0 = MIPS_FCR0; |
2827 | 4074 | #endif |
4075 | + /* XXX some guesswork here, values are CPU specific */ | |
4076 | + env->SYNCI_Step = 16; | |
4077 | + env->CCRes = 2; | |
2828 | 4078 | } | ... | ... |