Commit 8c0fdd856c63eb11ec5ef955731b1b0cda51f967

Authored by ths
1 parent 873eb012

Dynamically translate MIPS mtc0 instructions.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2223 c046a42c-6fe2-441c-8c8c-71466251a162
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";
... ...