Commit 3a95e3a7d9a6fd7610fe483778ff7016d23be5ec
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: | ... | ... |