Commit 3a95e3a7d9a6fd7610fe483778ff7016d23be5ec

Authored by ths
1 parent 2538deb2

Check for R2 instructions, and throw RI if we don't emulate R2.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2921 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 50 additions and 18 deletions
target-mips/translate.c
... ... @@ -732,6 +732,14 @@ void check_cp1_registers(DisasContext *ctx, int regs)
732 732 generate_exception(ctx, EXCP_RI);
733 733 }
734 734  
  735 +/* This code generates a "reserved instruction" exception if the
  736 + CPU is not a MIPS R2 (or higher) CPU. */
  737 +static inline void check_mips_r2(CPUState *env, DisasContext *ctx)
  738 +{
  739 + if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) < (1 << CP0C0_AR))
  740 + generate_exception(ctx, EXCP_RI);
  741 +}
  742 +
735 743 #if defined(CONFIG_USER_ONLY)
736 744 #define op_ldst(name) gen_op_##name##_raw()
737 745 #define OP_LD_TABLE(width)
... ... @@ -1866,7 +1874,7 @@ fail:
1866 1874 }
1867 1875  
1868 1876 /* CP0 (MMU and control) */
1869   -static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
  1877 +static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
1870 1878 {
1871 1879 const char *rn = "invalid";
1872 1880  
... ... @@ -2000,6 +2008,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
2000 2008 rn = "PageMask";
2001 2009 break;
2002 2010 case 1:
  2011 + check_mips_r2(env, ctx);
2003 2012 gen_op_mfc0_pagegrain();
2004 2013 rn = "PageGrain";
2005 2014 break;
... ... @@ -2040,6 +2049,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
2040 2049 case 7:
2041 2050 switch (sel) {
2042 2051 case 0:
  2052 + check_mips_r2(env, ctx);
2043 2053 gen_op_mfc0_hwrena();
2044 2054 rn = "HWREna";
2045 2055 break;
... ... @@ -2096,14 +2106,17 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
2096 2106 rn = "Status";
2097 2107 break;
2098 2108 case 1:
  2109 + check_mips_r2(env, ctx);
2099 2110 gen_op_mfc0_intctl();
2100 2111 rn = "IntCtl";
2101 2112 break;
2102 2113 case 2:
  2114 + check_mips_r2(env, ctx);
2103 2115 gen_op_mfc0_srsctl();
2104 2116 rn = "SRSCtl";
2105 2117 break;
2106 2118 case 3:
  2119 + check_mips_r2(env, ctx);
2107 2120 gen_op_mfc0_srsmap();
2108 2121 rn = "SRSMap";
2109 2122 break;
... ... @@ -2138,6 +2151,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
2138 2151 rn = "PRid";
2139 2152 break;
2140 2153 case 1:
  2154 + check_mips_r2(env, ctx);
2141 2155 gen_op_mfc0_ebase();
2142 2156 rn = "EBase";
2143 2157 break;
... ... @@ -2402,7 +2416,7 @@ die:
2402 2416 generate_exception(ctx, EXCP_RI);
2403 2417 }
2404 2418  
2405   -static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
  2419 +static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
2406 2420 {
2407 2421 const char *rn = "invalid";
2408 2422  
... ... @@ -2536,6 +2550,7 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2536 2550 rn = "PageMask";
2537 2551 break;
2538 2552 case 1:
  2553 + check_mips_r2(env, ctx);
2539 2554 gen_op_mtc0_pagegrain();
2540 2555 rn = "PageGrain";
2541 2556 break;
... ... @@ -2576,6 +2591,7 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2576 2591 case 7:
2577 2592 switch (sel) {
2578 2593 case 0:
  2594 + check_mips_r2(env, ctx);
2579 2595 gen_op_mtc0_hwrena();
2580 2596 rn = "HWREna";
2581 2597 break;
... ... @@ -2633,18 +2649,21 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2633 2649 rn = "Status";
2634 2650 break;
2635 2651 case 1:
  2652 + check_mips_r2(env, ctx);
2636 2653 gen_op_mtc0_intctl();
2637 2654 /* Stop translation as we may have switched the execution mode */
2638 2655 ctx->bstate = BS_STOP;
2639 2656 rn = "IntCtl";
2640 2657 break;
2641 2658 case 2:
  2659 + check_mips_r2(env, ctx);
2642 2660 gen_op_mtc0_srsctl();
2643 2661 /* Stop translation as we may have switched the execution mode */
2644 2662 ctx->bstate = BS_STOP;
2645 2663 rn = "SRSCtl";
2646 2664 break;
2647 2665 case 3:
  2666 + check_mips_r2(env, ctx);
2648 2667 gen_op_mtc0_srsmap();
2649 2668 /* Stop translation as we may have switched the execution mode */
2650 2669 ctx->bstate = BS_STOP;
... ... @@ -2683,6 +2702,7 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2683 2702 rn = "PRid";
2684 2703 break;
2685 2704 case 1:
  2705 + check_mips_r2(env, ctx);
2686 2706 gen_op_mtc0_ebase();
2687 2707 rn = "EBase";
2688 2708 break;
... ... @@ -2970,7 +2990,7 @@ die:
2970 2990 }
2971 2991  
2972 2992 #ifdef TARGET_MIPS64
2973   -static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
  2993 +static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
2974 2994 {
2975 2995 const char *rn = "invalid";
2976 2996  
... ... @@ -3104,6 +3124,7 @@ static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
3104 3124 rn = "PageMask";
3105 3125 break;
3106 3126 case 1:
  3127 + check_mips_r2(env, ctx);
3107 3128 gen_op_mfc0_pagegrain();
3108 3129 rn = "PageGrain";
3109 3130 break;
... ... @@ -3144,6 +3165,7 @@ static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
3144 3165 case 7:
3145 3166 switch (sel) {
3146 3167 case 0:
  3168 + check_mips_r2(env, ctx);
3147 3169 gen_op_mfc0_hwrena();
3148 3170 rn = "HWREna";
3149 3171 break;
... ... @@ -3200,14 +3222,17 @@ static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
3200 3222 rn = "Status";
3201 3223 break;
3202 3224 case 1:
  3225 + check_mips_r2(env, ctx);
3203 3226 gen_op_mfc0_intctl();
3204 3227 rn = "IntCtl";
3205 3228 break;
3206 3229 case 2:
  3230 + check_mips_r2(env, ctx);
3207 3231 gen_op_mfc0_srsctl();
3208 3232 rn = "SRSCtl";
3209 3233 break;
3210 3234 case 3:
  3235 + check_mips_r2(env, ctx);
3211 3236 gen_op_mfc0_srsmap(); /* shadow registers */
3212 3237 rn = "SRSMap";
3213 3238 break;
... ... @@ -3242,6 +3267,7 @@ static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
3242 3267 rn = "PRid";
3243 3268 break;
3244 3269 case 1:
  3270 + check_mips_r2(env, ctx);
3245 3271 gen_op_mfc0_ebase();
3246 3272 rn = "EBase";
3247 3273 break;
... ... @@ -3497,7 +3523,7 @@ die:
3497 3523 generate_exception(ctx, EXCP_RI);
3498 3524 }
3499 3525  
3500   -static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
  3526 +static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
3501 3527 {
3502 3528 const char *rn = "invalid";
3503 3529  
... ... @@ -3631,6 +3657,7 @@ static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3631 3657 rn = "PageMask";
3632 3658 break;
3633 3659 case 1:
  3660 + check_mips_r2(env, ctx);
3634 3661 gen_op_mtc0_pagegrain();
3635 3662 rn = "PageGrain";
3636 3663 break;
... ... @@ -3671,6 +3698,7 @@ static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3671 3698 case 7:
3672 3699 switch (sel) {
3673 3700 case 0:
  3701 + check_mips_r2(env, ctx);
3674 3702 gen_op_mtc0_hwrena();
3675 3703 rn = "HWREna";
3676 3704 break;
... ... @@ -3728,18 +3756,21 @@ static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3728 3756 rn = "Status";
3729 3757 break;
3730 3758 case 1:
  3759 + check_mips_r2(env, ctx);
3731 3760 gen_op_mtc0_intctl();
3732 3761 /* Stop translation as we may have switched the execution mode */
3733 3762 ctx->bstate = BS_STOP;
3734 3763 rn = "IntCtl";
3735 3764 break;
3736 3765 case 2:
  3766 + check_mips_r2(env, ctx);
3737 3767 gen_op_mtc0_srsctl();
3738 3768 /* Stop translation as we may have switched the execution mode */
3739 3769 ctx->bstate = BS_STOP;
3740 3770 rn = "SRSCtl";
3741 3771 break;
3742 3772 case 3:
  3773 + check_mips_r2(env, ctx);
3743 3774 gen_op_mtc0_srsmap();
3744 3775 /* Stop translation as we may have switched the execution mode */
3745 3776 ctx->bstate = BS_STOP;
... ... @@ -3778,6 +3809,7 @@ static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3778 3809 rn = "PRid";
3779 3810 break;
3780 3811 case 1:
  3812 + check_mips_r2(env, ctx);
3781 3813 gen_op_mtc0_ebase();
3782 3814 rn = "EBase";
3783 3815 break;
... ... @@ -4064,13 +4096,13 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
4064 4096 /* Treat as NOP */
4065 4097 return;
4066 4098 }
4067   - gen_mfc0(ctx, rd, ctx->opcode & 0x7);
  4099 + gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
4068 4100 gen_op_store_T0_gpr(rt);
4069 4101 opn = "mfc0";
4070 4102 break;
4071 4103 case OPC_MTC0:
4072 4104 GEN_LOAD_REG_TN(T0, rt);
4073   - gen_mtc0(ctx, rd, ctx->opcode & 0x7);
  4105 + gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
4074 4106 opn = "mtc0";
4075 4107 break;
4076 4108 #ifdef TARGET_MIPS64
... ... @@ -4079,13 +4111,13 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
4079 4111 /* Treat as NOP */
4080 4112 return;
4081 4113 }
4082   - gen_dmfc0(ctx, rd, ctx->opcode & 0x7);
  4114 + gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
4083 4115 gen_op_store_T0_gpr(rt);
4084 4116 opn = "dmfc0";
4085 4117 break;
4086 4118 case OPC_DMTC0:
4087 4119 GEN_LOAD_REG_TN(T0, rt);
4088   - gen_dmtc0(ctx, rd, ctx->opcode & 0x7);
  4120 + gen_dmtc0(env,ctx, rd, ctx->opcode & 0x7);
4089 4121 opn = "dmtc0";
4090 4122 break;
4091 4123 #endif
... ... @@ -5501,6 +5533,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5501 5533 }
5502 5534 break;
5503 5535 case OPC_SPECIAL3:
  5536 + check_mips_r2(env, ctx);
5504 5537 op1 = MASK_SPECIAL3(ctx->opcode);
5505 5538 switch (op1) {
5506 5539 case OPC_EXT:
... ... @@ -5604,6 +5637,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5604 5637 gen_trap(ctx, op1, rs, -1, imm);
5605 5638 break;
5606 5639 case OPC_SYNCI:
  5640 + check_mips_r2(env, ctx);
5607 5641 /* treat as noop */
5608 5642 break;
5609 5643 default: /* Invalid */
... ... @@ -5629,6 +5663,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5629 5663 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
5630 5664 break;
5631 5665 case OPC_MFMC0:
  5666 + check_mips_r2(env, ctx);
5632 5667 op2 = MASK_MFMC0(ctx->opcode);
5633 5668 switch (op2) {
5634 5669 case OPC_DI:
... ... @@ -5650,14 +5685,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5650 5685 break;
5651 5686 case OPC_RDPGPR:
5652 5687 case OPC_WRPGPR:
5653   - if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) {
5654   - /* Shadow registers not implemented. */
5655   - GEN_LOAD_REG_TN(T0, rt);
5656   - GEN_STORE_TN_REG(rd, T0);
5657   - } else {
5658   - MIPS_INVAL("shadow register move");
5659   - generate_exception(ctx, EXCP_RI);
5660   - }
  5688 + check_mips_r2(env, ctx);
  5689 + /* Shadow registers not implemented. */
  5690 + GEN_LOAD_REG_TN(T0, rt);
  5691 + GEN_STORE_TN_REG(rd, T0);
5661 5692 break;
5662 5693 default:
5663 5694 MIPS_INVAL("cp0");
... ... @@ -5710,6 +5741,9 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5710 5741 check_cp1_enabled(ctx);
5711 5742 op1 = MASK_CP1(ctx->opcode);
5712 5743 switch (op1) {
  5744 + case OPC_MFHC1:
  5745 + case OPC_MTHC1:
  5746 + check_mips_r2(env, ctx);
5713 5747 case OPC_MFC1:
5714 5748 case OPC_CFC1:
5715 5749 case OPC_MTC1:
... ... @@ -5718,8 +5752,6 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5718 5752 case OPC_DMFC1:
5719 5753 case OPC_DMTC1:
5720 5754 #endif
5721   - case OPC_MFHC1:
5722   - case OPC_MTHC1:
5723 5755 gen_cp1(ctx, op1, rt, rd);
5724 5756 break;
5725 5757 case OPC_BC1:
... ...