Commit 8c0fdd856c63eb11ec5ef955731b1b0cda51f967
1 parent
873eb012
Dynamically translate MIPS mtc0 instructions.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2223 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
423 additions
and
220 deletions
target-mips/exec.h
... | ... | @@ -68,7 +68,8 @@ 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(int reg, int sel); | |
71 | +void do_mtc0_status_debug(uint32_t old, uint32_t val); | |
72 | +void do_mtc0_status_irqraise_debug(void); | |
72 | 73 | void do_tlbwi (void); |
73 | 74 | void do_tlbwr (void); |
74 | 75 | void do_tlbp (void); | ... | ... |
target-mips/op.c
... | ... | @@ -852,9 +852,185 @@ void op_mfc0_desave (void) |
852 | 852 | RETURN(); |
853 | 853 | } |
854 | 854 | |
855 | -void op_mtc0 (void) | |
855 | +void op_mtc0_index (void) | |
856 | 856 | { |
857 | - CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2); | |
857 | + env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); | |
858 | + RETURN(); | |
859 | +} | |
860 | + | |
861 | +void op_mtc0_entrylo0 (void) | |
862 | +{ | |
863 | + env->CP0_EntryLo0 = T0 & 0x3FFFFFFF; | |
864 | + RETURN(); | |
865 | +} | |
866 | + | |
867 | +void op_mtc0_entrylo1 (void) | |
868 | +{ | |
869 | + env->CP0_EntryLo1 = T0 & 0x3FFFFFFF; | |
870 | + RETURN(); | |
871 | +} | |
872 | + | |
873 | +void op_mtc0_context (void) | |
874 | +{ | |
875 | + env->CP0_Context = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0); | |
876 | + RETURN(); | |
877 | +} | |
878 | + | |
879 | +void op_mtc0_pagemask (void) | |
880 | +{ | |
881 | + env->CP0_PageMask = T0 & 0x01FFE000; | |
882 | + RETURN(); | |
883 | +} | |
884 | + | |
885 | +void op_mtc0_wired (void) | |
886 | +{ | |
887 | + env->CP0_Wired = T0 & 0x0000000F; | |
888 | + RETURN(); | |
889 | +} | |
890 | + | |
891 | +void op_mtc0_count (void) | |
892 | +{ | |
893 | + CALL_FROM_TB2(cpu_mips_store_count, env, T0); | |
894 | + RETURN(); | |
895 | +} | |
896 | + | |
897 | +void op_mtc0_entryhi (void) | |
898 | +{ | |
899 | + uint32_t old, val; | |
900 | + | |
901 | + val = T0 & 0xFFFFE0FF; | |
902 | + old = env->CP0_EntryHi; | |
903 | + env->CP0_EntryHi = val; | |
904 | + /* If the ASID changes, flush qemu's TLB. */ | |
905 | + if ((old & 0xFF) != (val & 0xFF)) | |
906 | + CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1); | |
907 | + RETURN(); | |
908 | +} | |
909 | + | |
910 | +void op_mtc0_compare (void) | |
911 | +{ | |
912 | + CALL_FROM_TB2(cpu_mips_store_compare, env, T0); | |
913 | + RETURN(); | |
914 | +} | |
915 | + | |
916 | +void op_mtc0_status (void) | |
917 | +{ | |
918 | + uint32_t val, old, mask; | |
919 | + | |
920 | + val = T0 & 0xFA78FF01; | |
921 | + old = env->CP0_Status; | |
922 | + if (T0 & (1 << CP0St_UM)) | |
923 | + env->hflags |= MIPS_HFLAG_UM; | |
924 | + else | |
925 | + env->hflags &= ~MIPS_HFLAG_UM; | |
926 | + if (T0 & (1 << CP0St_ERL)) | |
927 | + env->hflags |= MIPS_HFLAG_ERL; | |
928 | + else | |
929 | + env->hflags &= ~MIPS_HFLAG_ERL; | |
930 | + if (T0 & (1 << CP0St_EXL)) | |
931 | + env->hflags |= MIPS_HFLAG_EXL; | |
932 | + else | |
933 | + env->hflags &= ~MIPS_HFLAG_EXL; | |
934 | + env->CP0_Status = val; | |
935 | + /* If we unmasked an asserted IRQ, raise it */ | |
936 | + mask = 0x0000FF00; | |
937 | + if (loglevel & CPU_LOG_TB_IN_ASM) | |
938 | + CALL_FROM_TB2(do_mtc0_status_debug, old, val); | |
939 | + if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) && | |
940 | + !(env->hflags & MIPS_HFLAG_EXL) && | |
941 | + !(env->hflags & MIPS_HFLAG_ERL) && | |
942 | + !(env->hflags & MIPS_HFLAG_DM) && | |
943 | + (env->CP0_Status & env->CP0_Cause & mask)) { | |
944 | + env->interrupt_request |= CPU_INTERRUPT_HARD; | |
945 | + if (logfile) | |
946 | + CALL_FROM_TB0(do_mtc0_status_irqraise_debug); | |
947 | + } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) { | |
948 | + env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
949 | + } | |
950 | + RETURN(); | |
951 | +} | |
952 | + | |
953 | +void op_mtc0_cause (void) | |
954 | +{ | |
955 | + uint32_t val, old; | |
956 | + | |
957 | + val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300); | |
958 | + old = env->CP0_Cause; | |
959 | + env->CP0_Cause = val; | |
960 | +#if 0 | |
961 | + { | |
962 | + int i, mask; | |
963 | + | |
964 | + /* Check if we ever asserted a software IRQ */ | |
965 | + for (i = 0; i < 2; i++) { | |
966 | + mask = 0x100 << i; | |
967 | + if ((val & mask) & !(old & mask)) | |
968 | + CALL_FROM_TB1(mips_set_irq, i); | |
969 | + } | |
970 | + } | |
971 | +#endif | |
972 | + RETURN(); | |
973 | +} | |
974 | + | |
975 | +void op_mtc0_epc (void) | |
976 | +{ | |
977 | + env->CP0_EPC = T0; | |
978 | + RETURN(); | |
979 | +} | |
980 | + | |
981 | +void op_mtc0_config0 (void) | |
982 | +{ | |
983 | +#if defined(MIPS_USES_R4K_TLB) | |
984 | + env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); | |
985 | +#else | |
986 | + env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); | |
987 | +#endif | |
988 | + RETURN(); | |
989 | +} | |
990 | + | |
991 | +void op_mtc0_watchlo (void) | |
992 | +{ | |
993 | + env->CP0_WatchLo = T0; | |
994 | + RETURN(); | |
995 | +} | |
996 | + | |
997 | +void op_mtc0_watchhi (void) | |
998 | +{ | |
999 | + env->CP0_WatchHi = T0 & 0x40FF0FF8; | |
1000 | + RETURN(); | |
1001 | +} | |
1002 | + | |
1003 | +void op_mtc0_debug (void) | |
1004 | +{ | |
1005 | + env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); | |
1006 | + if (T0 & (1 << CP0DB_DM)) | |
1007 | + env->hflags |= MIPS_HFLAG_DM; | |
1008 | + else | |
1009 | + env->hflags &= ~MIPS_HFLAG_DM; | |
1010 | + RETURN(); | |
1011 | +} | |
1012 | + | |
1013 | +void op_mtc0_depc (void) | |
1014 | +{ | |
1015 | + env->CP0_DEPC = T0; | |
1016 | + RETURN(); | |
1017 | +} | |
1018 | + | |
1019 | +void op_mtc0_taglo (void) | |
1020 | +{ | |
1021 | + env->CP0_TagLo = T0 & 0xFFFFFCF6; | |
1022 | + RETURN(); | |
1023 | +} | |
1024 | + | |
1025 | +void op_mtc0_errorepc (void) | |
1026 | +{ | |
1027 | + env->CP0_ErrorEPC = T0; | |
1028 | + RETURN(); | |
1029 | +} | |
1030 | + | |
1031 | +void op_mtc0_desave (void) | |
1032 | +{ | |
1033 | + env->CP0_DESAVE = T0; | |
858 | 1034 | RETURN(); |
859 | 1035 | } |
860 | 1036 | ... | ... |
target-mips/op_helper.c
... | ... | @@ -141,9 +141,24 @@ void do_mfc0_count (void) |
141 | 141 | cpu_abort(env, "mfc0 count\n"); |
142 | 142 | } |
143 | 143 | |
144 | -void do_mtc0 (int reg, int sel) | |
144 | +void cpu_mips_store_count(CPUState *env, uint32_t value) | |
145 | 145 | { |
146 | - cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel); | |
146 | + cpu_abort(env, "mtc0 count\n"); | |
147 | +} | |
148 | + | |
149 | +void cpu_mips_store_compare(CPUState *env, uint32_t value) | |
150 | +{ | |
151 | + cpu_abort(env, "mtc0 compare\n"); | |
152 | +} | |
153 | + | |
154 | +void do_mtc0_status_debug(uint32_t old, uint32_t val) | |
155 | +{ | |
156 | + cpu_abort(env, "mtc0 status\n"); | |
157 | +} | |
158 | + | |
159 | +void do_mtc0_status_irqraise_debug(void) | |
160 | +{ | |
161 | + cpu_abort(env, "mtc0 status\n"); | |
147 | 162 | } |
148 | 163 | |
149 | 164 | void do_tlbwi (void) |
... | ... | @@ -166,6 +181,11 @@ void do_tlbr (void) |
166 | 181 | cpu_abort(env, "tlbr\n"); |
167 | 182 | } |
168 | 183 | |
184 | +void cpu_mips_tlb_flush (CPUState *env, int flush_global) | |
185 | +{ | |
186 | + cpu_abort(env, "mips_tlb_flush\n"); | |
187 | +} | |
188 | + | |
169 | 189 | #else |
170 | 190 | |
171 | 191 | /* CP0 helpers */ |
... | ... | @@ -179,222 +199,17 @@ void do_mfc0_count (void) |
179 | 199 | T0 = cpu_mips_get_count(env); |
180 | 200 | } |
181 | 201 | |
182 | -void do_mtc0 (int reg, int sel) | |
202 | +void do_mtc0_status_debug(uint32_t old, uint32_t val) | |
183 | 203 | { |
184 | - const unsigned char *rn; | |
185 | - uint32_t val, old, mask; | |
204 | + const uint32_t mask = 0x0000FF00; | |
205 | + fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n", | |
206 | + old, val, env->CP0_Cause, old & mask, val & mask, | |
207 | + env->CP0_Cause & mask); | |
208 | +} | |
186 | 209 | |
187 | - if (sel != 0 && reg != 16 && reg != 28) { | |
188 | - val = -1; | |
189 | - old = -1; | |
190 | - rn = "invalid"; | |
191 | - goto print; | |
192 | - } | |
193 | - switch (reg) { | |
194 | - case 0: | |
195 | - val = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); | |
196 | - old = env->CP0_index; | |
197 | - env->CP0_index = val; | |
198 | - rn = "Index"; | |
199 | - break; | |
200 | - case 2: | |
201 | - val = T0 & 0x3FFFFFFF; | |
202 | - old = env->CP0_EntryLo0; | |
203 | - env->CP0_EntryLo0 = val; | |
204 | - rn = "EntryLo0"; | |
205 | - break; | |
206 | - case 3: | |
207 | - val = T0 & 0x3FFFFFFF; | |
208 | - old = env->CP0_EntryLo1; | |
209 | - env->CP0_EntryLo1 = val; | |
210 | - rn = "EntryLo1"; | |
211 | - break; | |
212 | - case 4: | |
213 | - val = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0); | |
214 | - old = env->CP0_Context; | |
215 | - env->CP0_Context = val; | |
216 | - rn = "Context"; | |
217 | - break; | |
218 | - case 5: | |
219 | - val = T0 & 0x01FFE000; | |
220 | - old = env->CP0_PageMask; | |
221 | - env->CP0_PageMask = val; | |
222 | - rn = "PageMask"; | |
223 | - break; | |
224 | - case 6: | |
225 | - val = T0 & 0x0000000F; | |
226 | - old = env->CP0_Wired; | |
227 | - env->CP0_Wired = val; | |
228 | - rn = "Wired"; | |
229 | - break; | |
230 | - case 9: | |
231 | - val = T0; | |
232 | - old = cpu_mips_get_count(env); | |
233 | - cpu_mips_store_count(env, val); | |
234 | - rn = "Count"; | |
235 | - break; | |
236 | - case 10: | |
237 | - val = T0 & 0xFFFFE0FF; | |
238 | - old = env->CP0_EntryHi; | |
239 | - env->CP0_EntryHi = val; | |
240 | - /* If the ASID changes, flush qemu's TLB. */ | |
241 | - if ((old & 0xFF) != (val & 0xFF)) | |
242 | - cpu_mips_tlb_flush (env, 1); | |
243 | - rn = "EntryHi"; | |
244 | - break; | |
245 | - case 11: | |
246 | - val = T0; | |
247 | - old = env->CP0_Compare; | |
248 | - cpu_mips_store_compare(env, val); | |
249 | - rn = "Compare"; | |
250 | - break; | |
251 | - case 12: | |
252 | - val = T0 & 0xFA78FF01; | |
253 | - if (T0 & (1 << CP0St_UM)) | |
254 | - env->hflags |= MIPS_HFLAG_UM; | |
255 | - else | |
256 | - env->hflags &= ~MIPS_HFLAG_UM; | |
257 | - if (T0 & (1 << CP0St_ERL)) | |
258 | - env->hflags |= MIPS_HFLAG_ERL; | |
259 | - else | |
260 | - env->hflags &= ~MIPS_HFLAG_ERL; | |
261 | - if (T0 & (1 << CP0St_EXL)) | |
262 | - env->hflags |= MIPS_HFLAG_EXL; | |
263 | - else | |
264 | - env->hflags &= ~MIPS_HFLAG_EXL; | |
265 | - old = env->CP0_Status; | |
266 | - env->CP0_Status = val; | |
267 | - /* If we unmasked an asserted IRQ, raise it */ | |
268 | - mask = 0x0000FF00; | |
269 | - if (loglevel & CPU_LOG_TB_IN_ASM) { | |
270 | - fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n", | |
271 | - old, val, env->CP0_Cause, old & mask, val & mask, | |
272 | - env->CP0_Cause & mask); | |
273 | - } | |
274 | - if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) && | |
275 | - !(env->hflags & MIPS_HFLAG_EXL) && | |
276 | - !(env->hflags & MIPS_HFLAG_ERL) && | |
277 | - !(env->hflags & MIPS_HFLAG_DM) && | |
278 | - (env->CP0_Status & env->CP0_Cause & mask)) { | |
279 | - if (logfile) | |
280 | - fprintf(logfile, "Raise pending IRQs\n"); | |
281 | - env->interrupt_request |= CPU_INTERRUPT_HARD; | |
282 | - } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) { | |
283 | - env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
284 | - } | |
285 | - rn = "Status"; | |
286 | - break; | |
287 | - case 13: | |
288 | - val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300); | |
289 | - old = env->CP0_Cause; | |
290 | - env->CP0_Cause = val; | |
291 | -#if 0 | |
292 | - { | |
293 | - int i; | |
294 | - /* Check if we ever asserted a software IRQ */ | |
295 | - for (i = 0; i < 2; i++) { | |
296 | - mask = 0x100 << i; | |
297 | - if ((val & mask) & !(old & mask)) | |
298 | - mips_set_irq(i); | |
299 | - } | |
300 | - } | |
301 | -#endif | |
302 | - rn = "Cause"; | |
303 | - break; | |
304 | - case 14: | |
305 | - val = T0; | |
306 | - old = env->CP0_EPC; | |
307 | - env->CP0_EPC = val; | |
308 | - rn = "EPC"; | |
309 | - break; | |
310 | - case 16: | |
311 | - switch (sel) { | |
312 | - case 0: | |
313 | -#if defined(MIPS_USES_R4K_TLB) | |
314 | - val = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); | |
315 | -#else | |
316 | - val = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); | |
317 | -#endif | |
318 | - old = env->CP0_Config0; | |
319 | - env->CP0_Config0 = val; | |
320 | - rn = "Config0"; | |
321 | - break; | |
322 | - default: | |
323 | - val = -1; | |
324 | - old = -1; | |
325 | - rn = "bad config selector"; | |
326 | - break; | |
327 | - } | |
328 | - break; | |
329 | - case 18: | |
330 | - val = T0; | |
331 | - old = env->CP0_WatchLo; | |
332 | - env->CP0_WatchLo = val; | |
333 | - rn = "WatchLo"; | |
334 | - break; | |
335 | - case 19: | |
336 | - val = T0 & 0x40FF0FF8; | |
337 | - old = env->CP0_WatchHi; | |
338 | - env->CP0_WatchHi = val; | |
339 | - rn = "WatchHi"; | |
340 | - break; | |
341 | - case 23: | |
342 | - val = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); | |
343 | - if (T0 & (1 << CP0DB_DM)) | |
344 | - env->hflags |= MIPS_HFLAG_DM; | |
345 | - else | |
346 | - env->hflags &= ~MIPS_HFLAG_DM; | |
347 | - old = env->CP0_Debug; | |
348 | - env->CP0_Debug = val; | |
349 | - rn = "Debug"; | |
350 | - break; | |
351 | - case 24: | |
352 | - val = T0; | |
353 | - old = env->CP0_DEPC; | |
354 | - env->CP0_DEPC = val; | |
355 | - rn = "DEPC"; | |
356 | - break; | |
357 | - case 28: | |
358 | - switch (sel) { | |
359 | - case 0: | |
360 | - val = T0 & 0xFFFFFCF6; | |
361 | - old = env->CP0_TagLo; | |
362 | - env->CP0_TagLo = val; | |
363 | - rn = "TagLo"; | |
364 | - break; | |
365 | - default: | |
366 | - val = -1; | |
367 | - old = -1; | |
368 | - rn = "invalid sel"; | |
369 | - break; | |
370 | - } | |
371 | - break; | |
372 | - case 30: | |
373 | - val = T0; | |
374 | - old = env->CP0_ErrorEPC; | |
375 | - env->CP0_ErrorEPC = val; | |
376 | - rn = "EPC"; | |
377 | - break; | |
378 | - case 31: | |
379 | - val = T0; | |
380 | - old = env->CP0_DESAVE; | |
381 | - env->CP0_DESAVE = val; | |
382 | - rn = "DESAVE"; | |
383 | - break; | |
384 | - default: | |
385 | - val = -1; | |
386 | - old = -1; | |
387 | - rn = "unknown"; | |
388 | - break; | |
389 | - } | |
390 | - print: | |
391 | -#if defined MIPS_DEBUG_DISAS | |
392 | - if (loglevel & CPU_LOG_TB_IN_ASM) { | |
393 | - fprintf(logfile, "%08x mtc0 %s %08x => %08x (%d %d %08x)\n", | |
394 | - env->PC, rn, T0, val, reg, sel, old); | |
395 | - } | |
396 | -#endif | |
397 | - return; | |
210 | +void do_mtc0_status_irqraise_debug(void) | |
211 | +{ | |
212 | + fprintf(logfile, "Raise pending IRQs\n"); | |
398 | 213 | } |
399 | 214 | |
400 | 215 | #ifdef MIPS_USES_FPU | ... | ... |
target-mips/translate.c
... | ... | @@ -1371,6 +1371,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
1371 | 1371 | rn = "EntryLo0"; |
1372 | 1372 | break; |
1373 | 1373 | case 3: |
1374 | + /* also CONF */ | |
1374 | 1375 | gen_op_mfc0_entrylo1(); |
1375 | 1376 | rn = "EntryLo1"; |
1376 | 1377 | break; |
... | ... | @@ -1386,6 +1387,10 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
1386 | 1387 | gen_op_mfc0_wired(); |
1387 | 1388 | rn = "Wired"; |
1388 | 1389 | break; |
1390 | + case 7: | |
1391 | +// gen_op_mfc0_info(); | |
1392 | + rn = "Info"; | |
1393 | + break; | |
1389 | 1394 | case 8: |
1390 | 1395 | gen_op_mfc0_badvaddr(); |
1391 | 1396 | rn = "BadVaddr"; |
... | ... | @@ -1445,6 +1450,19 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
1445 | 1450 | gen_op_mfc0_watchhi(); |
1446 | 1451 | rn = "WatchHi"; |
1447 | 1452 | break; |
1453 | + case 20: | |
1454 | + /* 64 bit only */ | |
1455 | +// gen_op_mfc0_xcontext(); | |
1456 | + rn = "XContext"; | |
1457 | + break; | |
1458 | + case 21: | |
1459 | +// gen_op_mfc0_framemask(); | |
1460 | + rn = "Framemask"; | |
1461 | + break; | |
1462 | + case 22: | |
1463 | +// gen_op_mfc0_diagnostic(); | |
1464 | + rn = "'Diagnostic"; | |
1465 | + break; | |
1448 | 1466 | case 23: |
1449 | 1467 | gen_op_mfc0_debug(); |
1450 | 1468 | rn = "Debug"; |
... | ... | @@ -1453,6 +1471,18 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
1453 | 1471 | gen_op_mfc0_depc(); |
1454 | 1472 | rn = "DEPC"; |
1455 | 1473 | break; |
1474 | + case 25: | |
1475 | +// gen_op_mfc0_performance(); | |
1476 | + rn = "Performance"; | |
1477 | + break; | |
1478 | + case 26: | |
1479 | +// gen_op_mfc0_ecc(); | |
1480 | + rn = "ECC"; | |
1481 | + break; | |
1482 | + case 27: | |
1483 | +// gen_op_mfc0_cacheerr(); | |
1484 | + rn = "CacheErr"; | |
1485 | + break; | |
1456 | 1486 | case 28: |
1457 | 1487 | switch (sel) { |
1458 | 1488 | case 0: |
... | ... | @@ -1468,6 +1498,10 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
1468 | 1498 | goto die; |
1469 | 1499 | } |
1470 | 1500 | break; |
1501 | + case 29: | |
1502 | +// gen_op_mfc0_taghi(); | |
1503 | + rn = "TagHi"; | |
1504 | + break; | |
1471 | 1505 | case 30: |
1472 | 1506 | gen_op_mfc0_errorepc(); |
1473 | 1507 | rn = "ErrorEPC"; |
... | ... | @@ -1498,6 +1532,183 @@ die: |
1498 | 1532 | generate_exception(ctx, EXCP_RI); |
1499 | 1533 | } |
1500 | 1534 | |
1535 | +static void gen_mtc0 (DisasContext *ctx, int reg, int sel) | |
1536 | +{ | |
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 | + } | |
1546 | + switch (reg) { | |
1547 | + case 0: | |
1548 | + gen_op_mtc0_index(); | |
1549 | + rn = "Index"; | |
1550 | + break; | |
1551 | + case 1: | |
1552 | +// ignore or except? | |
1553 | + rn = "Random"; | |
1554 | + break; | |
1555 | + case 2: | |
1556 | + gen_op_mtc0_entrylo0(); | |
1557 | + rn = "EntryLo0"; | |
1558 | + break; | |
1559 | + case 3: | |
1560 | + gen_op_mtc0_entrylo1(); | |
1561 | + rn = "EntryLo1"; | |
1562 | + break; | |
1563 | + case 4: | |
1564 | + gen_op_mtc0_context(); | |
1565 | + rn = "Context"; | |
1566 | + break; | |
1567 | + case 5: | |
1568 | + gen_op_mtc0_pagemask(); | |
1569 | + rn = "PageMask"; | |
1570 | + break; | |
1571 | + case 6: | |
1572 | + gen_op_mtc0_wired(); | |
1573 | + rn = "Wired"; | |
1574 | + break; | |
1575 | + case 7: | |
1576 | +// ignore or except? | |
1577 | + rn = "Info"; | |
1578 | + break; | |
1579 | + case 8: | |
1580 | +// ignore or except? | |
1581 | + rn = "BadVaddr"; | |
1582 | + break; | |
1583 | + case 9: | |
1584 | + gen_op_mtc0_count(); | |
1585 | + rn = "Count"; | |
1586 | + break; | |
1587 | + case 10: | |
1588 | + gen_op_mtc0_entryhi(); | |
1589 | + rn = "EntryHi"; | |
1590 | + break; | |
1591 | + case 11: | |
1592 | + gen_op_mtc0_compare(); | |
1593 | + rn = "Compare"; | |
1594 | + break; | |
1595 | + case 12: | |
1596 | + gen_op_mtc0_status(); | |
1597 | + rn = "Status"; | |
1598 | + break; | |
1599 | + case 13: | |
1600 | + gen_op_mtc0_cause(); | |
1601 | + rn = "Cause"; | |
1602 | + break; | |
1603 | + case 14: | |
1604 | + gen_op_mtc0_epc(); | |
1605 | + rn = "EPC"; | |
1606 | + break; | |
1607 | + case 15: | |
1608 | +// ignore or except? | |
1609 | + rn = "PRid"; | |
1610 | + break; | |
1611 | + case 16: | |
1612 | + switch (sel) { | |
1613 | + case 0: | |
1614 | + gen_op_mtc0_config0(); | |
1615 | + rn = "Config0"; | |
1616 | + break; | |
1617 | + default: | |
1618 | + rn = "Invalid config selector"; | |
1619 | + goto die; | |
1620 | + } | |
1621 | + break; | |
1622 | + case 17: | |
1623 | +// ignore or except? | |
1624 | + rn = "LLaddr"; | |
1625 | + break; | |
1626 | + case 18: | |
1627 | + gen_op_mtc0_watchlo(); | |
1628 | + rn = "WatchLo"; | |
1629 | + break; | |
1630 | + case 19: | |
1631 | + gen_op_mtc0_watchhi(); | |
1632 | + rn = "WatchHi"; | |
1633 | + break; | |
1634 | + case 20: | |
1635 | + /* 64 bit only */ | |
1636 | +// gen_op_mtc0_xcontext(); | |
1637 | + rn = "XContext"; | |
1638 | + break; | |
1639 | + case 21: | |
1640 | +// gen_op_mtc0_framemask(); | |
1641 | + rn = "Framemask"; | |
1642 | + break; | |
1643 | + case 22: | |
1644 | +// ignore or except? | |
1645 | + rn = "Diagnostic"; | |
1646 | + break; | |
1647 | + case 23: | |
1648 | + gen_op_mtc0_debug(); | |
1649 | + rn = "Debug"; | |
1650 | + break; | |
1651 | + case 24: | |
1652 | + gen_op_mtc0_depc(); | |
1653 | + rn = "DEPC"; | |
1654 | + break; | |
1655 | + case 25: | |
1656 | +// ignore or except? | |
1657 | + rn = "Performance"; | |
1658 | + break; | |
1659 | + case 26: | |
1660 | +// ignore or except? | |
1661 | + rn = "ECC"; | |
1662 | + break; | |
1663 | + case 27: | |
1664 | +// ignore or except? | |
1665 | + rn = "CacheErr"; | |
1666 | + break; | |
1667 | + case 28: | |
1668 | + switch (sel) { | |
1669 | + case 0: | |
1670 | + gen_op_mtc0_taglo(); | |
1671 | + rn = "TagLo"; | |
1672 | + break; | |
1673 | + default: | |
1674 | + rn = "invalid sel"; | |
1675 | + goto die; | |
1676 | + } | |
1677 | + break; | |
1678 | + case 29: | |
1679 | +// gen_op_mtc0_taghi(); | |
1680 | + rn = "TagHi"; | |
1681 | + break; | |
1682 | + case 30: | |
1683 | + gen_op_mtc0_errorepc(); | |
1684 | + rn = "ErrorEPC"; | |
1685 | + break; | |
1686 | + case 31: | |
1687 | + gen_op_mtc0_desave(); | |
1688 | + rn = "DESAVE"; | |
1689 | + break; | |
1690 | + default: | |
1691 | + rn = "unknown"; | |
1692 | + goto die; | |
1693 | + } | |
1694 | +#if defined MIPS_DEBUG_DISAS | |
1695 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | |
1696 | + fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", | |
1697 | + env->PC, rn, T0, reg, sel); | |
1698 | + } | |
1699 | +#endif | |
1700 | + return; | |
1701 | + | |
1702 | +die: | |
1703 | +#if defined MIPS_DEBUG_DISAS | |
1704 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | |
1705 | + fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", | |
1706 | + env->PC, rn, T0, reg, sel); | |
1707 | + } | |
1708 | +#endif | |
1709 | + generate_exception(ctx, EXCP_RI); | |
1710 | +} | |
1711 | + | |
1501 | 1712 | static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) |
1502 | 1713 | { |
1503 | 1714 | const unsigned char *opn = "unk"; |
... | ... | @@ -1529,7 +1740,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) |
1529 | 1740 | save_cpu_state(ctx, 1); |
1530 | 1741 | ctx->pc -= 4; |
1531 | 1742 | GEN_LOAD_REG_TN(T0, rt); |
1532 | - gen_op_mtc0(rd, ctx->opcode & 0x7); | |
1743 | + gen_mtc0(ctx, rd, ctx->opcode & 0x7); | |
1533 | 1744 | /* Stop translation as we may have switched the execution mode */ |
1534 | 1745 | ctx->bstate = BS_STOP; |
1535 | 1746 | opn = "mtc0"; | ... | ... |