Commit 873eb01234e67d27f3719310f7a89892e4727546

Authored by ths
1 parent 6ae81775

Dynamically translate MIPS mfc0 instructions.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2222 c046a42c-6fe2-441c-8c8c-71466251a162
target-mips/exec.h
... ... @@ -66,7 +66,8 @@ void do_maddu (void);
66 66 void do_msub (void);
67 67 void do_msubu (void);
68 68 #endif
69   -void do_mfc0(int reg, int sel);
  69 +void do_mfc0_random(void);
  70 +void do_mfc0_count(void);
70 71 void do_mtc0(int reg, int sel);
71 72 void do_tlbwi (void);
72 73 void do_tlbwr (void);
... ...
target-mips/op.c
... ... @@ -688,9 +688,167 @@ void op_jnz_T2 (void)
688 688 }
689 689  
690 690 /* CP0 functions */
691   -void op_mfc0 (void)
  691 +void op_mfc0_index (void)
692 692 {
693   - CALL_FROM_TB2(do_mfc0, PARAM1, PARAM2);
  693 + T0 = env->CP0_index;
  694 + RETURN();
  695 +}
  696 +
  697 +void op_mfc0_random (void)
  698 +{
  699 + CALL_FROM_TB0(do_mfc0_random);
  700 + RETURN();
  701 +}
  702 +
  703 +void op_mfc0_entrylo0 (void)
  704 +{
  705 + T0 = env->CP0_EntryLo0;
  706 + RETURN();
  707 +}
  708 +
  709 +void op_mfc0_entrylo1 (void)
  710 +{
  711 + T0 = env->CP0_EntryLo1;
  712 + RETURN();
  713 +}
  714 +
  715 +void op_mfc0_context (void)
  716 +{
  717 + T0 = env->CP0_Context;
  718 + RETURN();
  719 +}
  720 +
  721 +void op_mfc0_pagemask (void)
  722 +{
  723 + T0 = env->CP0_PageMask;
  724 + RETURN();
  725 +}
  726 +
  727 +void op_mfc0_wired (void)
  728 +{
  729 + T0 = env->CP0_Wired;
  730 + RETURN();
  731 +}
  732 +
  733 +void op_mfc0_badvaddr (void)
  734 +{
  735 + T0 = env->CP0_BadVAddr;
  736 + RETURN();
  737 +}
  738 +
  739 +void op_mfc0_count (void)
  740 +{
  741 + CALL_FROM_TB0(do_mfc0_count);
  742 + RETURN();
  743 +}
  744 +
  745 +void op_mfc0_entryhi (void)
  746 +{
  747 + T0 = env->CP0_EntryHi;
  748 + RETURN();
  749 +}
  750 +
  751 +void op_mfc0_compare (void)
  752 +{
  753 + T0 = env->CP0_Compare;
  754 + RETURN();
  755 +}
  756 +
  757 +void op_mfc0_status (void)
  758 +{
  759 + T0 = env->CP0_Status;
  760 + if (env->hflags & MIPS_HFLAG_UM)
  761 + T0 |= (1 << CP0St_UM);
  762 + if (env->hflags & MIPS_HFLAG_ERL)
  763 + T0 |= (1 << CP0St_ERL);
  764 + if (env->hflags & MIPS_HFLAG_EXL)
  765 + T0 |= (1 << CP0St_EXL);
  766 + RETURN();
  767 +}
  768 +
  769 +void op_mfc0_cause (void)
  770 +{
  771 + T0 = env->CP0_Cause;
  772 + RETURN();
  773 +}
  774 +
  775 +void op_mfc0_epc (void)
  776 +{
  777 + T0 = env->CP0_EPC;
  778 + RETURN();
  779 +}
  780 +
  781 +void op_mfc0_prid (void)
  782 +{
  783 + T0 = env->CP0_PRid;
  784 + RETURN();
  785 +}
  786 +
  787 +void op_mfc0_config0 (void)
  788 +{
  789 + T0 = env->CP0_Config0;
  790 + RETURN();
  791 +}
  792 +
  793 +void op_mfc0_config1 (void)
  794 +{
  795 + T0 = env->CP0_Config1;
  796 + RETURN();
  797 +}
  798 +
  799 +void op_mfc0_lladdr (void)
  800 +{
  801 + T0 = env->CP0_LLAddr >> 4;
  802 + RETURN();
  803 +}
  804 +
  805 +void op_mfc0_watchlo (void)
  806 +{
  807 + T0 = env->CP0_WatchLo;
  808 + RETURN();
  809 +}
  810 +
  811 +void op_mfc0_watchhi (void)
  812 +{
  813 + T0 = env->CP0_WatchHi;
  814 + RETURN();
  815 +}
  816 +
  817 +void op_mfc0_debug (void)
  818 +{
  819 + T0 = env->CP0_Debug;
  820 + if (env->hflags & MIPS_HFLAG_DM)
  821 + T0 |= 1 << CP0DB_DM;
  822 + RETURN();
  823 +}
  824 +
  825 +void op_mfc0_depc (void)
  826 +{
  827 + T0 = env->CP0_DEPC;
  828 + RETURN();
  829 +}
  830 +
  831 +void op_mfc0_taglo (void)
  832 +{
  833 + T0 = env->CP0_TagLo;
  834 + RETURN();
  835 +}
  836 +
  837 +void op_mfc0_datalo (void)
  838 +{
  839 + T0 = env->CP0_DataLo;
  840 + RETURN();
  841 +}
  842 +
  843 +void op_mfc0_errorepc (void)
  844 +{
  845 + T0 = env->CP0_ErrorEPC;
  846 + RETURN();
  847 +}
  848 +
  849 +void op_mfc0_desave (void)
  850 +{
  851 + T0 = env->CP0_DESAVE;
694 852 RETURN();
695 853 }
696 854  
... ...
target-mips/op_helper.c
... ... @@ -131,10 +131,16 @@ void do_msubu (void)
131 131 #endif
132 132  
133 133 #if defined(CONFIG_USER_ONLY)
134   -void do_mfc0 (int reg, int sel)
  134 +void do_mfc0_random (void)
135 135 {
136   - cpu_abort(env, "mfc0 reg=%d sel=%d\n", reg, sel);
  136 + cpu_abort(env, "mfc0 random\n");
137 137 }
  138 +
  139 +void do_mfc0_count (void)
  140 +{
  141 + cpu_abort(env, "mfc0 count\n");
  142 +}
  143 +
138 144 void do_mtc0 (int reg, int sel)
139 145 {
140 146 cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel);
... ... @@ -159,152 +165,18 @@ void do_tlbr (void)
159 165 {
160 166 cpu_abort(env, "tlbr\n");
161 167 }
  168 +
162 169 #else
163 170  
164 171 /* CP0 helpers */
165   -void do_mfc0 (int reg, int sel)
  172 +void do_mfc0_random (void)
166 173 {
167   - const unsigned char *rn;
  174 + T0 = cpu_mips_get_random(env);
  175 +}
168 176  
169   - if (sel != 0 && reg != 16 && reg != 28) {
170   - rn = "invalid";
171   - goto print;
172   - }
173   - switch (reg) {
174   - case 0:
175   - T0 = env->CP0_index;
176   - rn = "Index";
177   - break;
178   - case 1:
179   - T0 = cpu_mips_get_random(env);
180   - rn = "Random";
181   - break;
182   - case 2:
183   - T0 = env->CP0_EntryLo0;
184   - rn = "EntryLo0";
185   - break;
186   - case 3:
187   - T0 = env->CP0_EntryLo1;
188   - rn = "EntryLo1";
189   - break;
190   - case 4:
191   - T0 = env->CP0_Context;
192   - rn = "Context";
193   - break;
194   - case 5:
195   - T0 = env->CP0_PageMask;
196   - rn = "PageMask";
197   - break;
198   - case 6:
199   - T0 = env->CP0_Wired;
200   - rn = "Wired";
201   - break;
202   - case 8:
203   - T0 = env->CP0_BadVAddr;
204   - rn = "BadVaddr";
205   - break;
206   - case 9:
207   - T0 = cpu_mips_get_count(env);
208   - rn = "Count";
209   - break;
210   - case 10:
211   - T0 = env->CP0_EntryHi;
212   - rn = "EntryHi";
213   - break;
214   - case 11:
215   - T0 = env->CP0_Compare;
216   - rn = "Compare";
217   - break;
218   - case 12:
219   - T0 = env->CP0_Status;
220   - if (env->hflags & MIPS_HFLAG_UM)
221   - T0 |= (1 << CP0St_UM);
222   - rn = "Status";
223   - break;
224   - case 13:
225   - T0 = env->CP0_Cause;
226   - rn = "Cause";
227   - break;
228   - case 14:
229   - T0 = env->CP0_EPC;
230   - rn = "EPC";
231   - break;
232   - case 15:
233   - T0 = env->CP0_PRid;
234   - rn = "PRid";
235   - break;
236   - case 16:
237   - switch (sel) {
238   - case 0:
239   - T0 = env->CP0_Config0;
240   - rn = "Config";
241   - break;
242   - case 1:
243   - T0 = env->CP0_Config1;
244   - rn = "Config1";
245   - break;
246   - default:
247   - rn = "Unknown config register";
248   - break;
249   - }
250   - break;
251   - case 17:
252   - T0 = env->CP0_LLAddr >> 4;
253   - rn = "LLAddr";
254   - break;
255   - case 18:
256   - T0 = env->CP0_WatchLo;
257   - rn = "WatchLo";
258   - break;
259   - case 19:
260   - T0 = env->CP0_WatchHi;
261   - rn = "WatchHi";
262   - break;
263   - case 23:
264   - T0 = env->CP0_Debug;
265   - if (env->hflags & MIPS_HFLAG_DM)
266   - T0 |= 1 << CP0DB_DM;
267   - rn = "Debug";
268   - break;
269   - case 24:
270   - T0 = env->CP0_DEPC;
271   - rn = "DEPC";
272   - break;
273   - case 28:
274   - switch (sel) {
275   - case 0:
276   - T0 = env->CP0_TagLo;
277   - rn = "TagLo";
278   - break;
279   - case 1:
280   - T0 = env->CP0_DataLo;
281   - rn = "DataLo";
282   - break;
283   - default:
284   - rn = "unknown sel";
285   - break;
286   - }
287   - break;
288   - case 30:
289   - T0 = env->CP0_ErrorEPC;
290   - rn = "ErrorEPC";
291   - break;
292   - case 31:
293   - T0 = env->CP0_DESAVE;
294   - rn = "DESAVE";
295   - break;
296   - default:
297   - rn = "unknown";
298   - break;
299   - }
300   - print:
301   -#if defined MIPS_DEBUG_DISAS
302   - if (loglevel & CPU_LOG_TB_IN_ASM) {
303   - fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n",
304   - env->PC, rn, T0, reg, sel);
305   - }
306   -#endif
307   - return;
  177 +void do_mfc0_count (void)
  178 +{
  179 + T0 = cpu_mips_get_count(env);
308 180 }
309 181  
310 182 void do_mtc0 (int reg, int sel)
... ...
target-mips/translate.c
... ... @@ -1349,6 +1349,155 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
1349 1349 }
1350 1350  
1351 1351 /* CP0 (MMU and control) */
  1352 +static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
  1353 +{
  1354 + const unsigned char *rn;
  1355 +
  1356 + if (sel != 0 && reg != 16 && reg != 28) {
  1357 + rn = "invalid";
  1358 + goto die;
  1359 + }
  1360 + switch (reg) {
  1361 + case 0:
  1362 + gen_op_mfc0_index();
  1363 + rn = "Index";
  1364 + break;
  1365 + case 1:
  1366 + gen_op_mfc0_random();
  1367 + rn = "Random";
  1368 + break;
  1369 + case 2:
  1370 + gen_op_mfc0_entrylo0();
  1371 + rn = "EntryLo0";
  1372 + break;
  1373 + case 3:
  1374 + gen_op_mfc0_entrylo1();
  1375 + rn = "EntryLo1";
  1376 + break;
  1377 + case 4:
  1378 + gen_op_mfc0_context();
  1379 + rn = "Context";
  1380 + break;
  1381 + case 5:
  1382 + gen_op_mfc0_pagemask();
  1383 + rn = "PageMask";
  1384 + break;
  1385 + case 6:
  1386 + gen_op_mfc0_wired();
  1387 + rn = "Wired";
  1388 + break;
  1389 + case 8:
  1390 + gen_op_mfc0_badvaddr();
  1391 + rn = "BadVaddr";
  1392 + break;
  1393 + case 9:
  1394 + gen_op_mfc0_count();
  1395 + rn = "Count";
  1396 + break;
  1397 + case 10:
  1398 + gen_op_mfc0_entryhi();
  1399 + rn = "EntryHi";
  1400 + break;
  1401 + case 11:
  1402 + gen_op_mfc0_compare();
  1403 + rn = "Compare";
  1404 + break;
  1405 + case 12:
  1406 + gen_op_mfc0_status();
  1407 + rn = "Status";
  1408 + break;
  1409 + case 13:
  1410 + gen_op_mfc0_cause();
  1411 + rn = "Cause";
  1412 + break;
  1413 + case 14:
  1414 + gen_op_mfc0_epc();
  1415 + rn = "EPC";
  1416 + break;
  1417 + case 15:
  1418 + gen_op_mfc0_prid();
  1419 + rn = "PRid";
  1420 + break;
  1421 + case 16:
  1422 + switch (sel) {
  1423 + case 0:
  1424 + gen_op_mfc0_config0();
  1425 + rn = "Config";
  1426 + break;
  1427 + case 1:
  1428 + gen_op_mfc0_config1();
  1429 + rn = "Config1";
  1430 + break;
  1431 + default:
  1432 + rn = "Unknown config register";
  1433 + goto die;
  1434 + }
  1435 + break;
  1436 + case 17:
  1437 + gen_op_mfc0_lladdr();
  1438 + rn = "LLAddr";
  1439 + break;
  1440 + case 18:
  1441 + gen_op_mfc0_watchlo();
  1442 + rn = "WatchLo";
  1443 + break;
  1444 + case 19:
  1445 + gen_op_mfc0_watchhi();
  1446 + rn = "WatchHi";
  1447 + break;
  1448 + case 23:
  1449 + gen_op_mfc0_debug();
  1450 + rn = "Debug";
  1451 + break;
  1452 + case 24:
  1453 + gen_op_mfc0_depc();
  1454 + rn = "DEPC";
  1455 + break;
  1456 + case 28:
  1457 + switch (sel) {
  1458 + case 0:
  1459 + gen_op_mfc0_taglo();
  1460 + rn = "TagLo";
  1461 + break;
  1462 + case 1:
  1463 + gen_op_mfc0_datalo();
  1464 + rn = "DataLo";
  1465 + break;
  1466 + default:
  1467 + rn = "unknown sel";
  1468 + goto die;
  1469 + }
  1470 + break;
  1471 + case 30:
  1472 + gen_op_mfc0_errorepc();
  1473 + rn = "ErrorEPC";
  1474 + break;
  1475 + case 31:
  1476 + gen_op_mfc0_desave();
  1477 + rn = "DESAVE";
  1478 + break;
  1479 + default:
  1480 + rn = "unknown";
  1481 + goto die;
  1482 + }
  1483 +#if defined MIPS_DEBUG_DISAS
  1484 + if (loglevel & CPU_LOG_TB_IN_ASM) {
  1485 + fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n",
  1486 + env->PC, rn, T0, reg, sel);
  1487 + }
  1488 +#endif
  1489 + return;
  1490 +
  1491 +die:
  1492 +#if defined MIPS_DEBUG_DISAS
  1493 + if (loglevel & CPU_LOG_TB_IN_ASM) {
  1494 + fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n",
  1495 + env->PC, rn, T0, reg, sel);
  1496 + }
  1497 +#endif
  1498 + generate_exception(ctx, EXCP_RI);
  1499 +}
  1500 +
1352 1501 static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1353 1502 {
1354 1503 const unsigned char *opn = "unk";
... ... @@ -1370,7 +1519,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1370 1519 /* Treat as NOP */
1371 1520 return;
1372 1521 }
1373   - gen_op_mfc0(rd, ctx->opcode & 0x7);
  1522 + gen_mfc0(ctx, rd, ctx->opcode & 0x7);
1374 1523 gen_op_store_T0_gpr(rt);
1375 1524 opn = "mfc0";
1376 1525 break;
... ...