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: | ... | ... |