Commit e189e7486867e36c35f99cbac27d503ce4e7c71d
1 parent
92a34c10
Per-CPU instruction decoding implementation, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3228 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
230 additions
and
103 deletions
target-mips/cpu.h
... | ... | @@ -441,6 +441,7 @@ struct CPUMIPSState { |
441 | 441 | int CCRes; /* Cycle count resolution/divisor */ |
442 | 442 | uint32_t CP0_Status_rw_bitmask; /* Read/write bits in CP0_Status */ |
443 | 443 | uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */ |
444 | + int insn_flags; /* Supported instruction set */ | |
444 | 445 | |
445 | 446 | #ifdef CONFIG_USER_ONLY |
446 | 447 | target_ulong tls_value; | ... | ... |
target-mips/helper.c
... | ... | @@ -369,8 +369,7 @@ void do_interrupt (CPUState *env) |
369 | 369 | } |
370 | 370 | enter_debug_mode: |
371 | 371 | env->hflags |= MIPS_HFLAG_DM; |
372 | - if ((env->CP0_Config0 & (0x3 << CP0C0_AT))) | |
373 | - env->hflags |= MIPS_HFLAG_64; | |
372 | + env->hflags |= MIPS_HFLAG_64; | |
374 | 373 | env->hflags &= ~MIPS_HFLAG_UM; |
375 | 374 | /* EJTAG probe trap enable is not implemented... */ |
376 | 375 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
... | ... | @@ -396,8 +395,7 @@ void do_interrupt (CPUState *env) |
396 | 395 | env->CP0_ErrorEPC = env->PC[env->current_tc]; |
397 | 396 | } |
398 | 397 | env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); |
399 | - if ((env->CP0_Config0 & (0x3 << CP0C0_AT))) | |
400 | - env->hflags |= MIPS_HFLAG_64; | |
398 | + env->hflags |= MIPS_HFLAG_64; | |
401 | 399 | env->hflags &= ~MIPS_HFLAG_UM; |
402 | 400 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
403 | 401 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
... | ... | @@ -499,8 +497,7 @@ void do_interrupt (CPUState *env) |
499 | 497 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
500 | 498 | } |
501 | 499 | env->CP0_Status |= (1 << CP0St_EXL); |
502 | - if ((env->CP0_Config0 & (0x3 << CP0C0_AT))) | |
503 | - env->hflags |= MIPS_HFLAG_64; | |
500 | + env->hflags |= MIPS_HFLAG_64; | |
504 | 501 | env->hflags &= ~MIPS_HFLAG_UM; |
505 | 502 | } |
506 | 503 | env->hflags &= ~MIPS_HFLAG_BMASK; | ... | ... |
target-mips/mips-defs.h
... | ... | @@ -14,6 +14,41 @@ |
14 | 14 | #define TARGET_LONG_BITS 32 |
15 | 15 | #endif |
16 | 16 | |
17 | +/* Masks used to mark instructions to indicate which ISA level they | |
18 | + were introduced in. */ | |
19 | +#define ISA_MIPS1 0x00000001 | |
20 | +#define ISA_MIPS2 0x00000002 | |
21 | +#define ISA_MIPS3 0x00000004 | |
22 | +#define ISA_MIPS4 0x00000008 | |
23 | +#define ISA_MIPS5 0x00000010 | |
24 | +#define ISA_MIPS32 0x00000020 | |
25 | +#define ISA_MIPS32R2 0x00000040 | |
26 | +#define ISA_MIPS64 0x00000080 | |
27 | +#define ISA_MIPS64R2 0x00000100 | |
28 | + | |
29 | +/* MIPS ASE */ | |
30 | +#define ASE_MIPS16 0x00001000 | |
31 | +#define ASE_MIPS3D 0x00002000 | |
32 | +#define ASE_MDMX 0x00004000 | |
33 | +#define ASE_DSP 0x00008000 | |
34 | +#define ASE_DSPR2 0x00010000 | |
35 | + | |
36 | +/* Chip specific instructions. */ | |
37 | +/* Currently void */ | |
38 | + | |
39 | +/* MIPS CPU defines. */ | |
40 | +#define CPU_MIPS1 (ISA_MIPS1) | |
41 | +#define CPU_MIPS2 (CPU_MIPS1 | ISA_MIPS2) | |
42 | +#define CPU_MIPS3 (CPU_MIPS2 | ISA_MIPS3) | |
43 | +#define CPU_MIPS4 (CPU_MIPS3 | ISA_MIPS4) | |
44 | +#define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5) | |
45 | + | |
46 | +#define CPU_MIPS32 (CPU_MIPS2 | ISA_MIPS32) | |
47 | +#define CPU_MIPS64 (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64) | |
48 | + | |
49 | +#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2) | |
50 | +#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2) | |
51 | + | |
17 | 52 | /* Strictly follow the architecture standard: |
18 | 53 | - Disallow "special" instruction handling for PMON/SPIM. |
19 | 54 | Note that we still maintain Count/Compare to match the host clock. */ | ... | ... |
target-mips/op.c
... | ... | @@ -1847,10 +1847,9 @@ void op_mtc0_status (void) |
1847 | 1847 | (val & (1 << CP0St_UM))) |
1848 | 1848 | env->hflags |= MIPS_HFLAG_UM; |
1849 | 1849 | #ifdef TARGET_MIPS64 |
1850 | - if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) || | |
1851 | - ((env->hflags & MIPS_HFLAG_UM) && | |
1850 | + if ((env->hflags & MIPS_HFLAG_UM) && | |
1852 | 1851 | !(val & (1 << CP0St_PX)) && |
1853 | - !(val & (1 << CP0St_UX)))) | |
1852 | + !(val & (1 << CP0St_UX))) | |
1854 | 1853 | env->hflags &= ~MIPS_HFLAG_64; |
1855 | 1854 | #endif |
1856 | 1855 | if (val & (1 << CP0St_CU1)) |
... | ... | @@ -1906,7 +1905,7 @@ void op_mtc0_cause (void) |
1906 | 1905 | { |
1907 | 1906 | uint32_t mask = 0x00C00300; |
1908 | 1907 | |
1909 | - if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) | |
1908 | + if (env->insn_flags & ISA_MIPS32R2) | |
1910 | 1909 | mask |= 1 << CP0Ca_DC; |
1911 | 1910 | |
1912 | 1911 | env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask); |
... | ... | @@ -3014,10 +3013,9 @@ void op_eret (void) |
3014 | 3013 | (env->CP0_Status & (1 << CP0St_UM))) |
3015 | 3014 | env->hflags |= MIPS_HFLAG_UM; |
3016 | 3015 | #ifdef TARGET_MIPS64 |
3017 | - if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) || | |
3018 | - ((env->hflags & MIPS_HFLAG_UM) && | |
3016 | + if ((env->hflags & MIPS_HFLAG_UM) && | |
3019 | 3017 | !(env->CP0_Status & (1 << CP0St_PX)) && |
3020 | - !(env->CP0_Status & (1 << CP0St_UX)))) | |
3018 | + !(env->CP0_Status & (1 << CP0St_UX))) | |
3021 | 3019 | env->hflags &= ~MIPS_HFLAG_64; |
3022 | 3020 | #endif |
3023 | 3021 | if (loglevel & CPU_LOG_EXEC) |
... | ... | @@ -3038,10 +3036,9 @@ void op_deret (void) |
3038 | 3036 | (env->CP0_Status & (1 << CP0St_UM))) |
3039 | 3037 | env->hflags |= MIPS_HFLAG_UM; |
3040 | 3038 | #ifdef TARGET_MIPS64 |
3041 | - if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) || | |
3042 | - ((env->hflags & MIPS_HFLAG_UM) && | |
3039 | + if ((env->hflags & MIPS_HFLAG_UM) && | |
3043 | 3040 | !(env->CP0_Status & (1 << CP0St_PX)) && |
3044 | - !(env->CP0_Status & (1 << CP0St_UX)))) | |
3041 | + !(env->CP0_Status & (1 << CP0St_UX))) | |
3045 | 3042 | env->hflags &= ~MIPS_HFLAG_64; |
3046 | 3043 | #endif |
3047 | 3044 | if (loglevel & CPU_LOG_EXEC) | ... | ... |
target-mips/translate.c
... | ... | @@ -142,7 +142,7 @@ enum { |
142 | 142 | OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */ |
143 | 143 | OPC_SRA = 0x03 | OPC_SPECIAL, |
144 | 144 | OPC_SLLV = 0x04 | OPC_SPECIAL, |
145 | - OPC_SRLV = 0x06 | OPC_SPECIAL, | |
145 | + OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */ | |
146 | 146 | OPC_SRAV = 0x07 | OPC_SPECIAL, |
147 | 147 | OPC_DSLLV = 0x14 | OPC_SPECIAL, |
148 | 148 | OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */ |
... | ... | @@ -761,10 +761,10 @@ void check_cp1_registers(DisasContext *ctx, int regs) |
761 | 761 | } |
762 | 762 | |
763 | 763 | /* This code generates a "reserved instruction" exception if the |
764 | - CPU is not a MIPS R2 (or higher) CPU. */ | |
765 | -static inline void check_mips_r2(CPUState *env, DisasContext *ctx) | |
764 | + CPU does not support the instruction set corresponding to flags. */ | |
765 | +static inline void check_insn(CPUState *env, DisasContext *ctx, int flags) | |
766 | 766 | { |
767 | - if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) < (1 << CP0C0_AR)) | |
767 | + if (unlikely(!(env->insn_flags & flags))) | |
768 | 768 | generate_exception(ctx, EXCP_RI); |
769 | 769 | } |
770 | 770 | |
... | ... | @@ -776,6 +776,14 @@ static inline void check_mips_mt(CPUState *env, DisasContext *ctx) |
776 | 776 | generate_exception(ctx, EXCP_RI); |
777 | 777 | } |
778 | 778 | |
779 | +/* This code generates a "reserved instruction" exception if 64-bit | |
780 | + instructions are not enabled. */ | |
781 | +static inline void check_mips_64(DisasContext *ctx) | |
782 | +{ | |
783 | + if (!(ctx->hflags & MIPS_HFLAG_64)) | |
784 | + generate_exception(ctx, EXCP_RI); | |
785 | +} | |
786 | + | |
779 | 787 | #if defined(CONFIG_USER_ONLY) |
780 | 788 | #define op_ldst(name) gen_op_##name##_raw() |
781 | 789 | #define OP_LD_TABLE(width) |
... | ... | @@ -1024,8 +1032,8 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, |
1024 | 1032 | } |
1025 | 1033 | |
1026 | 1034 | /* Arithmetic with immediate operand */ |
1027 | -static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, | |
1028 | - int rs, int16_t imm) | |
1035 | +static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | |
1036 | + int rt, int rs, int16_t imm) | |
1029 | 1037 | { |
1030 | 1038 | target_ulong uimm; |
1031 | 1039 | const char *opn = "imm arith"; |
... | ... | @@ -1132,8 +1140,14 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
1132 | 1140 | opn = "srl"; |
1133 | 1141 | break; |
1134 | 1142 | case 1: |
1135 | - gen_op_rotr(); | |
1136 | - opn = "rotr"; | |
1143 | + /* rotr is decoded as srl on non-R2 CPUs */ | |
1144 | + if (env->insn_flags & ISA_MIPS32R2) { | |
1145 | + gen_op_rotr(); | |
1146 | + opn = "rotr"; | |
1147 | + } else { | |
1148 | + gen_op_srl(); | |
1149 | + opn = "srl"; | |
1150 | + } | |
1137 | 1151 | break; |
1138 | 1152 | default: |
1139 | 1153 | MIPS_INVAL("invalid srl flag"); |
... | ... | @@ -1157,8 +1171,14 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
1157 | 1171 | opn = "dsrl"; |
1158 | 1172 | break; |
1159 | 1173 | case 1: |
1160 | - gen_op_drotr(); | |
1161 | - opn = "drotr"; | |
1174 | + /* drotr is decoded as dsrl on non-R2 CPUs */ | |
1175 | + if (env->insn_flags & ISA_MIPS32R2) { | |
1176 | + gen_op_drotr(); | |
1177 | + opn = "drotr"; | |
1178 | + } else { | |
1179 | + gen_op_dsrl(); | |
1180 | + opn = "dsrl"; | |
1181 | + } | |
1162 | 1182 | break; |
1163 | 1183 | default: |
1164 | 1184 | MIPS_INVAL("invalid dsrl flag"); |
... | ... | @@ -1181,8 +1201,14 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
1181 | 1201 | opn = "dsrl32"; |
1182 | 1202 | break; |
1183 | 1203 | case 1: |
1184 | - gen_op_drotr32(); | |
1185 | - opn = "drotr32"; | |
1204 | + /* drotr32 is decoded as dsrl32 on non-R2 CPUs */ | |
1205 | + if (env->insn_flags & ISA_MIPS32R2) { | |
1206 | + gen_op_drotr32(); | |
1207 | + opn = "drotr32"; | |
1208 | + } else { | |
1209 | + gen_op_dsrl32(); | |
1210 | + opn = "dsrl32"; | |
1211 | + } | |
1186 | 1212 | break; |
1187 | 1213 | default: |
1188 | 1214 | MIPS_INVAL("invalid dsrl32 flag"); |
... | ... | @@ -1201,7 +1227,7 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
1201 | 1227 | } |
1202 | 1228 | |
1203 | 1229 | /* Arithmetic */ |
1204 | -static void gen_arith (DisasContext *ctx, uint32_t opc, | |
1230 | +static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, | |
1205 | 1231 | int rd, int rs, int rt) |
1206 | 1232 | { |
1207 | 1233 | const char *opn = "arith"; |
... | ... | @@ -1305,8 +1331,14 @@ static void gen_arith (DisasContext *ctx, uint32_t opc, |
1305 | 1331 | opn = "srlv"; |
1306 | 1332 | break; |
1307 | 1333 | case 1: |
1308 | - gen_op_rotrv(); | |
1309 | - opn = "rotrv"; | |
1334 | + /* rotrv is decoded as srlv on non-R2 CPUs */ | |
1335 | + if (env->insn_flags & ISA_MIPS32R2) { | |
1336 | + gen_op_rotrv(); | |
1337 | + opn = "rotrv"; | |
1338 | + } else { | |
1339 | + gen_op_srlv(); | |
1340 | + opn = "srlv"; | |
1341 | + } | |
1310 | 1342 | break; |
1311 | 1343 | default: |
1312 | 1344 | MIPS_INVAL("invalid srlv flag"); |
... | ... | @@ -1330,8 +1362,14 @@ static void gen_arith (DisasContext *ctx, uint32_t opc, |
1330 | 1362 | opn = "dsrlv"; |
1331 | 1363 | break; |
1332 | 1364 | case 1: |
1333 | - gen_op_drotrv(); | |
1334 | - opn = "drotrv"; | |
1365 | + /* drotrv is decoded as dsrlv on non-R2 CPUs */ | |
1366 | + if (env->insn_flags & ISA_MIPS32R2) { | |
1367 | + gen_op_drotrv(); | |
1368 | + opn = "drotrv"; | |
1369 | + } else { | |
1370 | + gen_op_dsrlv(); | |
1371 | + opn = "dsrlv"; | |
1372 | + } | |
1335 | 1373 | break; |
1336 | 1374 | default: |
1337 | 1375 | MIPS_INVAL("invalid dsrlv flag"); |
... | ... | @@ -1910,6 +1948,9 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
1910 | 1948 | { |
1911 | 1949 | const char *rn = "invalid"; |
1912 | 1950 | |
1951 | + if (sel != 0) | |
1952 | + check_insn(env, ctx, ISA_MIPS32); | |
1953 | + | |
1913 | 1954 | switch (reg) { |
1914 | 1955 | case 0: |
1915 | 1956 | switch (sel) { |
... | ... | @@ -2057,7 +2098,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2057 | 2098 | rn = "PageMask"; |
2058 | 2099 | break; |
2059 | 2100 | case 1: |
2060 | - check_mips_r2(env, ctx); | |
2101 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2061 | 2102 | gen_op_mfc0_pagegrain(); |
2062 | 2103 | rn = "PageGrain"; |
2063 | 2104 | break; |
... | ... | @@ -2072,22 +2113,27 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2072 | 2113 | rn = "Wired"; |
2073 | 2114 | break; |
2074 | 2115 | case 1: |
2116 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2075 | 2117 | gen_op_mfc0_srsconf0(); |
2076 | 2118 | rn = "SRSConf0"; |
2077 | 2119 | break; |
2078 | 2120 | case 2: |
2121 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2079 | 2122 | gen_op_mfc0_srsconf1(); |
2080 | 2123 | rn = "SRSConf1"; |
2081 | 2124 | break; |
2082 | 2125 | case 3: |
2126 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2083 | 2127 | gen_op_mfc0_srsconf2(); |
2084 | 2128 | rn = "SRSConf2"; |
2085 | 2129 | break; |
2086 | 2130 | case 4: |
2131 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2087 | 2132 | gen_op_mfc0_srsconf3(); |
2088 | 2133 | rn = "SRSConf3"; |
2089 | 2134 | break; |
2090 | 2135 | case 5: |
2136 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2091 | 2137 | gen_op_mfc0_srsconf4(); |
2092 | 2138 | rn = "SRSConf4"; |
2093 | 2139 | break; |
... | ... | @@ -2098,7 +2144,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2098 | 2144 | case 7: |
2099 | 2145 | switch (sel) { |
2100 | 2146 | case 0: |
2101 | - check_mips_r2(env, ctx); | |
2147 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2102 | 2148 | gen_op_mfc0_hwrena(); |
2103 | 2149 | rn = "HWREna"; |
2104 | 2150 | break; |
... | ... | @@ -2155,17 +2201,17 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2155 | 2201 | rn = "Status"; |
2156 | 2202 | break; |
2157 | 2203 | case 1: |
2158 | - check_mips_r2(env, ctx); | |
2204 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2159 | 2205 | gen_op_mfc0_intctl(); |
2160 | 2206 | rn = "IntCtl"; |
2161 | 2207 | break; |
2162 | 2208 | case 2: |
2163 | - check_mips_r2(env, ctx); | |
2209 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2164 | 2210 | gen_op_mfc0_srsctl(); |
2165 | 2211 | rn = "SRSCtl"; |
2166 | 2212 | break; |
2167 | 2213 | case 3: |
2168 | - check_mips_r2(env, ctx); | |
2214 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2169 | 2215 | gen_op_mfc0_srsmap(); |
2170 | 2216 | rn = "SRSMap"; |
2171 | 2217 | break; |
... | ... | @@ -2200,7 +2246,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2200 | 2246 | rn = "PRid"; |
2201 | 2247 | break; |
2202 | 2248 | case 1: |
2203 | - check_mips_r2(env, ctx); | |
2249 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2204 | 2250 | gen_op_mfc0_ebase(); |
2205 | 2251 | rn = "EBase"; |
2206 | 2252 | break; |
... | ... | @@ -2274,8 +2320,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2274 | 2320 | switch (sel) { |
2275 | 2321 | case 0: |
2276 | 2322 | #ifdef TARGET_MIPS64 |
2277 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
2278 | - goto die; | |
2323 | + check_insn(env, ctx, ISA_MIPS3); | |
2279 | 2324 | gen_op_mfc0_xcontext(); |
2280 | 2325 | rn = "XContext"; |
2281 | 2326 | break; |
... | ... | @@ -2471,6 +2516,9 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2471 | 2516 | { |
2472 | 2517 | const char *rn = "invalid"; |
2473 | 2518 | |
2519 | + if (sel != 0) | |
2520 | + check_insn(env, ctx, ISA_MIPS32); | |
2521 | + | |
2474 | 2522 | switch (reg) { |
2475 | 2523 | case 0: |
2476 | 2524 | switch (sel) { |
... | ... | @@ -2618,7 +2666,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2618 | 2666 | rn = "PageMask"; |
2619 | 2667 | break; |
2620 | 2668 | case 1: |
2621 | - check_mips_r2(env, ctx); | |
2669 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2622 | 2670 | gen_op_mtc0_pagegrain(); |
2623 | 2671 | rn = "PageGrain"; |
2624 | 2672 | break; |
... | ... | @@ -2633,22 +2681,27 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2633 | 2681 | rn = "Wired"; |
2634 | 2682 | break; |
2635 | 2683 | case 1: |
2684 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2636 | 2685 | gen_op_mtc0_srsconf0(); |
2637 | 2686 | rn = "SRSConf0"; |
2638 | 2687 | break; |
2639 | 2688 | case 2: |
2689 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2640 | 2690 | gen_op_mtc0_srsconf1(); |
2641 | 2691 | rn = "SRSConf1"; |
2642 | 2692 | break; |
2643 | 2693 | case 3: |
2694 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2644 | 2695 | gen_op_mtc0_srsconf2(); |
2645 | 2696 | rn = "SRSConf2"; |
2646 | 2697 | break; |
2647 | 2698 | case 4: |
2699 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2648 | 2700 | gen_op_mtc0_srsconf3(); |
2649 | 2701 | rn = "SRSConf3"; |
2650 | 2702 | break; |
2651 | 2703 | case 5: |
2704 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2652 | 2705 | gen_op_mtc0_srsconf4(); |
2653 | 2706 | rn = "SRSConf4"; |
2654 | 2707 | break; |
... | ... | @@ -2659,7 +2712,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2659 | 2712 | case 7: |
2660 | 2713 | switch (sel) { |
2661 | 2714 | case 0: |
2662 | - check_mips_r2(env, ctx); | |
2715 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2663 | 2716 | gen_op_mtc0_hwrena(); |
2664 | 2717 | rn = "HWREna"; |
2665 | 2718 | break; |
... | ... | @@ -2717,21 +2770,21 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2717 | 2770 | rn = "Status"; |
2718 | 2771 | break; |
2719 | 2772 | case 1: |
2720 | - check_mips_r2(env, ctx); | |
2773 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2721 | 2774 | gen_op_mtc0_intctl(); |
2722 | 2775 | /* Stop translation as we may have switched the execution mode */ |
2723 | 2776 | ctx->bstate = BS_STOP; |
2724 | 2777 | rn = "IntCtl"; |
2725 | 2778 | break; |
2726 | 2779 | case 2: |
2727 | - check_mips_r2(env, ctx); | |
2780 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2728 | 2781 | gen_op_mtc0_srsctl(); |
2729 | 2782 | /* Stop translation as we may have switched the execution mode */ |
2730 | 2783 | ctx->bstate = BS_STOP; |
2731 | 2784 | rn = "SRSCtl"; |
2732 | 2785 | break; |
2733 | 2786 | case 3: |
2734 | - check_mips_r2(env, ctx); | |
2787 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2735 | 2788 | gen_op_mtc0_srsmap(); |
2736 | 2789 | /* Stop translation as we may have switched the execution mode */ |
2737 | 2790 | ctx->bstate = BS_STOP; |
... | ... | @@ -2770,7 +2823,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2770 | 2823 | rn = "PRid"; |
2771 | 2824 | break; |
2772 | 2825 | case 1: |
2773 | - check_mips_r2(env, ctx); | |
2826 | + check_insn(env, ctx, ISA_MIPS32R2); | |
2774 | 2827 | gen_op_mtc0_ebase(); |
2775 | 2828 | rn = "EBase"; |
2776 | 2829 | break; |
... | ... | @@ -2849,8 +2902,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
2849 | 2902 | switch (sel) { |
2850 | 2903 | case 0: |
2851 | 2904 | #ifdef TARGET_MIPS64 |
2852 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
2853 | - goto die; | |
2905 | + check_insn(env, ctx, ISA_MIPS3); | |
2854 | 2906 | gen_op_mtc0_xcontext(); |
2855 | 2907 | rn = "XContext"; |
2856 | 2908 | break; |
... | ... | @@ -3064,6 +3116,9 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3064 | 3116 | { |
3065 | 3117 | const char *rn = "invalid"; |
3066 | 3118 | |
3119 | + if (sel != 0) | |
3120 | + check_insn(env, ctx, ISA_MIPS64); | |
3121 | + | |
3067 | 3122 | switch (reg) { |
3068 | 3123 | case 0: |
3069 | 3124 | switch (sel) { |
... | ... | @@ -3211,7 +3266,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3211 | 3266 | rn = "PageMask"; |
3212 | 3267 | break; |
3213 | 3268 | case 1: |
3214 | - check_mips_r2(env, ctx); | |
3269 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3215 | 3270 | gen_op_mfc0_pagegrain(); |
3216 | 3271 | rn = "PageGrain"; |
3217 | 3272 | break; |
... | ... | @@ -3226,22 +3281,27 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3226 | 3281 | rn = "Wired"; |
3227 | 3282 | break; |
3228 | 3283 | case 1: |
3284 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3229 | 3285 | gen_op_mfc0_srsconf0(); |
3230 | 3286 | rn = "SRSConf0"; |
3231 | 3287 | break; |
3232 | 3288 | case 2: |
3289 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3233 | 3290 | gen_op_mfc0_srsconf1(); |
3234 | 3291 | rn = "SRSConf1"; |
3235 | 3292 | break; |
3236 | 3293 | case 3: |
3294 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3237 | 3295 | gen_op_mfc0_srsconf2(); |
3238 | 3296 | rn = "SRSConf2"; |
3239 | 3297 | break; |
3240 | 3298 | case 4: |
3299 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3241 | 3300 | gen_op_mfc0_srsconf3(); |
3242 | 3301 | rn = "SRSConf3"; |
3243 | 3302 | break; |
3244 | 3303 | case 5: |
3304 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3245 | 3305 | gen_op_mfc0_srsconf4(); |
3246 | 3306 | rn = "SRSConf4"; |
3247 | 3307 | break; |
... | ... | @@ -3252,7 +3312,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3252 | 3312 | case 7: |
3253 | 3313 | switch (sel) { |
3254 | 3314 | case 0: |
3255 | - check_mips_r2(env, ctx); | |
3315 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3256 | 3316 | gen_op_mfc0_hwrena(); |
3257 | 3317 | rn = "HWREna"; |
3258 | 3318 | break; |
... | ... | @@ -3309,17 +3369,17 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3309 | 3369 | rn = "Status"; |
3310 | 3370 | break; |
3311 | 3371 | case 1: |
3312 | - check_mips_r2(env, ctx); | |
3372 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3313 | 3373 | gen_op_mfc0_intctl(); |
3314 | 3374 | rn = "IntCtl"; |
3315 | 3375 | break; |
3316 | 3376 | case 2: |
3317 | - check_mips_r2(env, ctx); | |
3377 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3318 | 3378 | gen_op_mfc0_srsctl(); |
3319 | 3379 | rn = "SRSCtl"; |
3320 | 3380 | break; |
3321 | 3381 | case 3: |
3322 | - check_mips_r2(env, ctx); | |
3382 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3323 | 3383 | gen_op_mfc0_srsmap(); |
3324 | 3384 | rn = "SRSMap"; |
3325 | 3385 | break; |
... | ... | @@ -3354,7 +3414,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3354 | 3414 | rn = "PRid"; |
3355 | 3415 | break; |
3356 | 3416 | case 1: |
3357 | - check_mips_r2(env, ctx); | |
3417 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3358 | 3418 | gen_op_mfc0_ebase(); |
3359 | 3419 | rn = "EBase"; |
3360 | 3420 | break; |
... | ... | @@ -3418,6 +3478,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3418 | 3478 | case 20: |
3419 | 3479 | switch (sel) { |
3420 | 3480 | case 0: |
3481 | + check_insn(env, ctx, ISA_MIPS3); | |
3421 | 3482 | gen_op_dmfc0_xcontext(); |
3422 | 3483 | rn = "XContext"; |
3423 | 3484 | break; |
... | ... | @@ -3612,6 +3673,9 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3612 | 3673 | { |
3613 | 3674 | const char *rn = "invalid"; |
3614 | 3675 | |
3676 | + if (sel != 0) | |
3677 | + check_insn(env, ctx, ISA_MIPS64); | |
3678 | + | |
3615 | 3679 | switch (reg) { |
3616 | 3680 | case 0: |
3617 | 3681 | switch (sel) { |
... | ... | @@ -3759,7 +3823,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3759 | 3823 | rn = "PageMask"; |
3760 | 3824 | break; |
3761 | 3825 | case 1: |
3762 | - check_mips_r2(env, ctx); | |
3826 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3763 | 3827 | gen_op_mtc0_pagegrain(); |
3764 | 3828 | rn = "PageGrain"; |
3765 | 3829 | break; |
... | ... | @@ -3774,22 +3838,27 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3774 | 3838 | rn = "Wired"; |
3775 | 3839 | break; |
3776 | 3840 | case 1: |
3841 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3777 | 3842 | gen_op_mtc0_srsconf0(); |
3778 | 3843 | rn = "SRSConf0"; |
3779 | 3844 | break; |
3780 | 3845 | case 2: |
3846 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3781 | 3847 | gen_op_mtc0_srsconf1(); |
3782 | 3848 | rn = "SRSConf1"; |
3783 | 3849 | break; |
3784 | 3850 | case 3: |
3851 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3785 | 3852 | gen_op_mtc0_srsconf2(); |
3786 | 3853 | rn = "SRSConf2"; |
3787 | 3854 | break; |
3788 | 3855 | case 4: |
3856 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3789 | 3857 | gen_op_mtc0_srsconf3(); |
3790 | 3858 | rn = "SRSConf3"; |
3791 | 3859 | break; |
3792 | 3860 | case 5: |
3861 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3793 | 3862 | gen_op_mtc0_srsconf4(); |
3794 | 3863 | rn = "SRSConf4"; |
3795 | 3864 | break; |
... | ... | @@ -3800,7 +3869,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3800 | 3869 | case 7: |
3801 | 3870 | switch (sel) { |
3802 | 3871 | case 0: |
3803 | - check_mips_r2(env, ctx); | |
3872 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3804 | 3873 | gen_op_mtc0_hwrena(); |
3805 | 3874 | rn = "HWREna"; |
3806 | 3875 | break; |
... | ... | @@ -3858,21 +3927,21 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3858 | 3927 | rn = "Status"; |
3859 | 3928 | break; |
3860 | 3929 | case 1: |
3861 | - check_mips_r2(env, ctx); | |
3930 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3862 | 3931 | gen_op_mtc0_intctl(); |
3863 | 3932 | /* Stop translation as we may have switched the execution mode */ |
3864 | 3933 | ctx->bstate = BS_STOP; |
3865 | 3934 | rn = "IntCtl"; |
3866 | 3935 | break; |
3867 | 3936 | case 2: |
3868 | - check_mips_r2(env, ctx); | |
3937 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3869 | 3938 | gen_op_mtc0_srsctl(); |
3870 | 3939 | /* Stop translation as we may have switched the execution mode */ |
3871 | 3940 | ctx->bstate = BS_STOP; |
3872 | 3941 | rn = "SRSCtl"; |
3873 | 3942 | break; |
3874 | 3943 | case 3: |
3875 | - check_mips_r2(env, ctx); | |
3944 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3876 | 3945 | gen_op_mtc0_srsmap(); |
3877 | 3946 | /* Stop translation as we may have switched the execution mode */ |
3878 | 3947 | ctx->bstate = BS_STOP; |
... | ... | @@ -3911,7 +3980,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3911 | 3980 | rn = "PRid"; |
3912 | 3981 | break; |
3913 | 3982 | case 1: |
3914 | - check_mips_r2(env, ctx); | |
3983 | + check_insn(env, ctx, ISA_MIPS32R2); | |
3915 | 3984 | gen_op_mtc0_ebase(); |
3916 | 3985 | rn = "EBase"; |
3917 | 3986 | break; |
... | ... | @@ -3980,6 +4049,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
3980 | 4049 | case 20: |
3981 | 4050 | switch (sel) { |
3982 | 4051 | case 0: |
4052 | + check_insn(env, ctx, ISA_MIPS3); | |
3983 | 4053 | gen_op_mtc0_xcontext(); |
3984 | 4054 | rn = "XContext"; |
3985 | 4055 | break; |
... | ... | @@ -4535,8 +4605,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
4535 | 4605 | break; |
4536 | 4606 | #ifdef TARGET_MIPS64 |
4537 | 4607 | case OPC_DMFC0: |
4538 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
4539 | - generate_exception(ctx, EXCP_RI); | |
4608 | + check_insn(env, ctx, ISA_MIPS3); | |
4540 | 4609 | if (rt == 0) { |
4541 | 4610 | /* Treat as NOP. */ |
4542 | 4611 | return; |
... | ... | @@ -4546,8 +4615,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
4546 | 4615 | opn = "dmfc0"; |
4547 | 4616 | break; |
4548 | 4617 | case OPC_DMTC0: |
4549 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
4550 | - generate_exception(ctx, EXCP_RI); | |
4618 | + check_insn(env, ctx, ISA_MIPS3); | |
4551 | 4619 | GEN_LOAD_REG_TN(T0, rt); |
4552 | 4620 | gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7); |
4553 | 4621 | opn = "dmtc0"; |
... | ... | @@ -4597,11 +4665,13 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
4597 | 4665 | break; |
4598 | 4666 | case OPC_ERET: |
4599 | 4667 | opn = "eret"; |
4668 | + check_insn(env, ctx, ISA_MIPS2); | |
4600 | 4669 | gen_op_eret(); |
4601 | 4670 | ctx->bstate = BS_EXCP; |
4602 | 4671 | break; |
4603 | 4672 | case OPC_DERET: |
4604 | 4673 | opn = "deret"; |
4674 | + check_insn(env, ctx, ISA_MIPS32); | |
4605 | 4675 | if (!(ctx->hflags & MIPS_HFLAG_DM)) { |
4606 | 4676 | MIPS_INVAL(opn); |
4607 | 4677 | generate_exception(ctx, EXCP_RI); |
... | ... | @@ -4612,6 +4682,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
4612 | 4682 | break; |
4613 | 4683 | case OPC_WAIT: |
4614 | 4684 | opn = "wait"; |
4685 | + check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32); | |
4615 | 4686 | /* If we get an exception, we want to restart at next instruction */ |
4616 | 4687 | ctx->pc += 4; |
4617 | 4688 | save_cpu_state(ctx, 1); |
... | ... | @@ -4629,12 +4700,15 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
4629 | 4700 | } |
4630 | 4701 | |
4631 | 4702 | /* CP1 Branches (before delay slot) */ |
4632 | -static void gen_compute_branch1 (DisasContext *ctx, uint32_t op, | |
4703 | +static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op, | |
4633 | 4704 | int32_t cc, int32_t offset) |
4634 | 4705 | { |
4635 | 4706 | target_ulong btarget; |
4636 | 4707 | const char *opn = "cp1 cond branch"; |
4637 | 4708 | |
4709 | + if (cc != 0) | |
4710 | + check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); | |
4711 | + | |
4638 | 4712 | btarget = ctx->pc + 4 + offset; |
4639 | 4713 | |
4640 | 4714 | switch (op) { |
... | ... | @@ -5843,14 +5917,15 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
5843 | 5917 | switch (op1) { |
5844 | 5918 | case OPC_SLL: /* Arithmetic with immediate */ |
5845 | 5919 | case OPC_SRL ... OPC_SRA: |
5846 | - gen_arith_imm(ctx, op1, rd, rt, sa); | |
5920 | + gen_arith_imm(env, ctx, op1, rd, rt, sa); | |
5847 | 5921 | break; |
5922 | + case OPC_MOVZ ... OPC_MOVN: | |
5923 | + check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); | |
5848 | 5924 | case OPC_SLLV: /* Arithmetic */ |
5849 | 5925 | case OPC_SRLV ... OPC_SRAV: |
5850 | - case OPC_MOVZ ... OPC_MOVN: | |
5851 | 5926 | case OPC_ADD ... OPC_NOR: |
5852 | 5927 | case OPC_SLT ... OPC_SLTU: |
5853 | - gen_arith(ctx, op1, rd, rs, rt); | |
5928 | + gen_arith(env, ctx, op1, rd, rs, rt); | |
5854 | 5929 | break; |
5855 | 5930 | case OPC_MULT ... OPC_DIVU: |
5856 | 5931 | gen_muldiv(ctx, op1, rs, rt); |
... | ... | @@ -5899,6 +5974,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
5899 | 5974 | break; |
5900 | 5975 | |
5901 | 5976 | case OPC_MOVCI: |
5977 | + check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); | |
5902 | 5978 | if (env->CP0_Config1 & (1 << CP0C1_FP)) { |
5903 | 5979 | save_cpu_state(ctx, 1); |
5904 | 5980 | check_cp1_enabled(ctx); |
... | ... | @@ -5915,20 +5991,20 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
5915 | 5991 | case OPC_DSRL ... OPC_DSRA: |
5916 | 5992 | case OPC_DSLL32: |
5917 | 5993 | case OPC_DSRL32 ... OPC_DSRA32: |
5918 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
5919 | - generate_exception(ctx, EXCP_RI); | |
5920 | - gen_arith_imm(ctx, op1, rd, rt, sa); | |
5994 | + check_insn(env, ctx, ISA_MIPS3); | |
5995 | + check_mips_64(ctx); | |
5996 | + gen_arith_imm(env, ctx, op1, rd, rt, sa); | |
5921 | 5997 | break; |
5922 | 5998 | case OPC_DSLLV: |
5923 | 5999 | case OPC_DSRLV ... OPC_DSRAV: |
5924 | 6000 | case OPC_DADD ... OPC_DSUBU: |
5925 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
5926 | - generate_exception(ctx, EXCP_RI); | |
5927 | - gen_arith(ctx, op1, rd, rs, rt); | |
6001 | + check_insn(env, ctx, ISA_MIPS3); | |
6002 | + check_mips_64(ctx); | |
6003 | + gen_arith(env, ctx, op1, rd, rs, rt); | |
5928 | 6004 | break; |
5929 | 6005 | case OPC_DMULT ... OPC_DDIVU: |
5930 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
5931 | - generate_exception(ctx, EXCP_RI); | |
6006 | + check_insn(env, ctx, ISA_MIPS3); | |
6007 | + check_mips_64(ctx); | |
5932 | 6008 | gen_muldiv(ctx, op1, rs, rt); |
5933 | 6009 | break; |
5934 | 6010 | #endif |
... | ... | @@ -5943,18 +6019,21 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
5943 | 6019 | switch (op1) { |
5944 | 6020 | case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */ |
5945 | 6021 | case OPC_MSUB ... OPC_MSUBU: |
6022 | + check_insn(env, ctx, ISA_MIPS32); | |
5946 | 6023 | gen_muldiv(ctx, op1, rs, rt); |
5947 | 6024 | break; |
5948 | 6025 | case OPC_MUL: |
5949 | - gen_arith(ctx, op1, rd, rs, rt); | |
6026 | + gen_arith(env, ctx, op1, rd, rs, rt); | |
5950 | 6027 | break; |
5951 | 6028 | case OPC_CLZ ... OPC_CLO: |
6029 | + check_insn(env, ctx, ISA_MIPS32); | |
5952 | 6030 | gen_cl(ctx, op1, rd, rs); |
5953 | 6031 | break; |
5954 | 6032 | case OPC_SDBBP: |
5955 | 6033 | /* XXX: not clear which exception should be raised |
5956 | 6034 | * when in debug mode... |
5957 | 6035 | */ |
6036 | + check_insn(env, ctx, ISA_MIPS32); | |
5958 | 6037 | if (!(ctx->hflags & MIPS_HFLAG_DM)) { |
5959 | 6038 | generate_exception(ctx, EXCP_DBp); |
5960 | 6039 | } else { |
... | ... | @@ -5964,8 +6043,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
5964 | 6043 | break; |
5965 | 6044 | #ifdef TARGET_MIPS64 |
5966 | 6045 | case OPC_DCLZ ... OPC_DCLO: |
5967 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
5968 | - generate_exception(ctx, EXCP_RI); | |
6046 | + check_insn(env, ctx, ISA_MIPS64); | |
6047 | + check_mips_64(ctx); | |
5969 | 6048 | gen_cl(ctx, op1, rd, rs); |
5970 | 6049 | break; |
5971 | 6050 | #endif |
... | ... | @@ -5976,14 +6055,15 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
5976 | 6055 | } |
5977 | 6056 | break; |
5978 | 6057 | case OPC_SPECIAL3: |
5979 | - check_mips_r2(env, ctx); | |
5980 | 6058 | op1 = MASK_SPECIAL3(ctx->opcode); |
5981 | 6059 | switch (op1) { |
5982 | 6060 | case OPC_EXT: |
5983 | 6061 | case OPC_INS: |
6062 | + check_insn(env, ctx, ISA_MIPS32R2); | |
5984 | 6063 | gen_bitops(ctx, op1, rt, rs, sa, rd); |
5985 | 6064 | break; |
5986 | 6065 | case OPC_BSHFL: |
6066 | + check_insn(env, ctx, ISA_MIPS32R2); | |
5987 | 6067 | op2 = MASK_BSHFL(ctx->opcode); |
5988 | 6068 | switch (op2) { |
5989 | 6069 | case OPC_WSBH: |
... | ... | @@ -6006,6 +6086,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6006 | 6086 | GEN_STORE_TN_REG(rd, T0); |
6007 | 6087 | break; |
6008 | 6088 | case OPC_RDHWR: |
6089 | + check_insn(env, ctx, ISA_MIPS32R2); | |
6009 | 6090 | switch (rd) { |
6010 | 6091 | case 0: |
6011 | 6092 | save_cpu_state(ctx, 1); |
... | ... | @@ -6050,13 +6131,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6050 | 6131 | #ifdef TARGET_MIPS64 |
6051 | 6132 | case OPC_DEXTM ... OPC_DEXT: |
6052 | 6133 | case OPC_DINSM ... OPC_DINS: |
6053 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
6054 | - generate_exception(ctx, EXCP_RI); | |
6134 | + check_insn(env, ctx, ISA_MIPS64R2); | |
6135 | + check_mips_64(ctx); | |
6055 | 6136 | gen_bitops(ctx, op1, rt, rs, sa, rd); |
6056 | 6137 | break; |
6057 | 6138 | case OPC_DBSHFL: |
6058 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
6059 | - generate_exception(ctx, EXCP_RI); | |
6139 | + check_insn(env, ctx, ISA_MIPS64R2); | |
6140 | + check_mips_64(ctx); | |
6060 | 6141 | op2 = MASK_DBSHFL(ctx->opcode); |
6061 | 6142 | switch (op2) { |
6062 | 6143 | case OPC_DSBH: |
... | ... | @@ -6092,7 +6173,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6092 | 6173 | gen_trap(ctx, op1, rs, -1, imm); |
6093 | 6174 | break; |
6094 | 6175 | case OPC_SYNCI: |
6095 | - check_mips_r2(env, ctx); | |
6176 | + check_insn(env, ctx, ISA_MIPS32R2); | |
6096 | 6177 | /* Treat as NOP. */ |
6097 | 6178 | break; |
6098 | 6179 | default: /* Invalid */ |
... | ... | @@ -6120,7 +6201,6 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6120 | 6201 | gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd); |
6121 | 6202 | break; |
6122 | 6203 | case OPC_MFMC0: |
6123 | - check_mips_r2(env, ctx); | |
6124 | 6204 | op2 = MASK_MFMC0(ctx->opcode); |
6125 | 6205 | switch (op2) { |
6126 | 6206 | case OPC_DMT: |
... | ... | @@ -6140,11 +6220,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6140 | 6220 | gen_op_evpe(); |
6141 | 6221 | break; |
6142 | 6222 | case OPC_DI: |
6223 | + check_insn(env, ctx, ISA_MIPS32R2); | |
6143 | 6224 | gen_op_di(); |
6144 | 6225 | /* Stop translation as we may have switched the execution mode */ |
6145 | 6226 | ctx->bstate = BS_STOP; |
6146 | 6227 | break; |
6147 | 6228 | case OPC_EI: |
6229 | + check_insn(env, ctx, ISA_MIPS32R2); | |
6148 | 6230 | gen_op_ei(); |
6149 | 6231 | /* Stop translation as we may have switched the execution mode */ |
6150 | 6232 | ctx->bstate = BS_STOP; |
... | ... | @@ -6157,12 +6239,12 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6157 | 6239 | GEN_STORE_TN_REG(rt, T0); |
6158 | 6240 | break; |
6159 | 6241 | case OPC_RDPGPR: |
6160 | - check_mips_r2(env, ctx); | |
6242 | + check_insn(env, ctx, ISA_MIPS32R2); | |
6161 | 6243 | GEN_LOAD_SRSREG_TN(T0, rt); |
6162 | 6244 | GEN_STORE_TN_REG(rd, T0); |
6163 | 6245 | break; |
6164 | 6246 | case OPC_WRPGPR: |
6165 | - check_mips_r2(env, ctx); | |
6247 | + check_insn(env, ctx, ISA_MIPS32R2); | |
6166 | 6248 | GEN_LOAD_REG_TN(T0, rt); |
6167 | 6249 | GEN_STORE_TN_SRSREG(rd, T0); |
6168 | 6250 | break; |
... | ... | @@ -6173,7 +6255,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6173 | 6255 | } |
6174 | 6256 | break; |
6175 | 6257 | case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */ |
6176 | - gen_arith_imm(ctx, op, rt, rs, imm); | |
6258 | + gen_arith_imm(env, ctx, op, rt, rs, imm); | |
6177 | 6259 | break; |
6178 | 6260 | case OPC_J ... OPC_JAL: /* Jump */ |
6179 | 6261 | offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; |
... | ... | @@ -6191,9 +6273,11 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6191 | 6273 | gen_ldst(ctx, op, rt, rs, imm); |
6192 | 6274 | break; |
6193 | 6275 | case OPC_CACHE: |
6276 | + check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32); | |
6194 | 6277 | /* Treat as NOP. */ |
6195 | 6278 | break; |
6196 | 6279 | case OPC_PREF: |
6280 | + check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); | |
6197 | 6281 | /* Treat as NOP. */ |
6198 | 6282 | break; |
6199 | 6283 | |
... | ... | @@ -6219,21 +6303,24 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6219 | 6303 | switch (op1) { |
6220 | 6304 | case OPC_MFHC1: |
6221 | 6305 | case OPC_MTHC1: |
6222 | - check_mips_r2(env, ctx); | |
6306 | + check_insn(env, ctx, ISA_MIPS32R2); | |
6223 | 6307 | case OPC_MFC1: |
6224 | 6308 | case OPC_CFC1: |
6225 | 6309 | case OPC_MTC1: |
6226 | 6310 | case OPC_CTC1: |
6311 | + gen_cp1(ctx, op1, rt, rd); | |
6312 | + break; | |
6227 | 6313 | #ifdef TARGET_MIPS64 |
6228 | 6314 | case OPC_DMFC1: |
6229 | 6315 | case OPC_DMTC1: |
6230 | -#endif | |
6316 | + check_insn(env, ctx, ISA_MIPS3); | |
6231 | 6317 | gen_cp1(ctx, op1, rt, rd); |
6232 | 6318 | break; |
6319 | +#endif | |
6233 | 6320 | case OPC_BC1: |
6234 | 6321 | case OPC_BC1ANY2: |
6235 | 6322 | case OPC_BC1ANY4: |
6236 | - gen_compute_branch1(ctx, MASK_BC1(ctx->opcode), | |
6323 | + gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode), | |
6237 | 6324 | (rt >> 2) & 0x7, imm << 2); |
6238 | 6325 | return; |
6239 | 6326 | case OPC_S_FMT: |
... | ... | @@ -6315,24 +6402,22 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6315 | 6402 | case OPC_LD: |
6316 | 6403 | case OPC_SCD: |
6317 | 6404 | case OPC_SD: |
6318 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
6319 | - generate_exception(ctx, EXCP_RI); | |
6405 | + check_insn(env, ctx, ISA_MIPS3); | |
6406 | + check_mips_64(ctx); | |
6320 | 6407 | gen_ldst(ctx, op, rt, rs, imm); |
6321 | 6408 | break; |
6322 | 6409 | case OPC_DADDI ... OPC_DADDIU: |
6323 | - if (!(ctx->hflags & MIPS_HFLAG_64)) | |
6324 | - generate_exception(ctx, EXCP_RI); | |
6325 | - gen_arith_imm(ctx, op, rt, rs, imm); | |
6410 | + check_insn(env, ctx, ISA_MIPS3); | |
6411 | + check_mips_64(ctx); | |
6412 | + gen_arith_imm(env, ctx, op, rt, rs, imm); | |
6326 | 6413 | break; |
6327 | 6414 | #endif |
6328 | -#ifdef MIPS_HAS_MIPS16 | |
6329 | 6415 | case OPC_JALX: |
6416 | + check_insn(env, ctx, ASE_MIPS16); | |
6330 | 6417 | /* MIPS16: Not implemented. */ |
6331 | -#endif | |
6332 | -#ifdef MIPS_HAS_MDMX | |
6333 | 6418 | case OPC_MDMX: |
6419 | + check_insn(env, ctx, ASE_MDMX); | |
6334 | 6420 | /* MDMX: Not implemented. */ |
6335 | -#endif | |
6336 | 6421 | default: /* Invalid */ |
6337 | 6422 | MIPS_INVAL("major opcode"); |
6338 | 6423 | generate_exception(ctx, EXCP_RI); | ... | ... |
target-mips/translate_init.c
... | ... | @@ -80,6 +80,7 @@ struct mips_def_t { |
80 | 80 | int32_t CP0_SRSConf3; |
81 | 81 | int32_t CP0_SRSConf4_rw_bitmask; |
82 | 82 | int32_t CP0_SRSConf4; |
83 | + int insn_flags; | |
83 | 84 | }; |
84 | 85 | |
85 | 86 | /*****************************************************************************/ |
... | ... | @@ -98,6 +99,7 @@ static mips_def_t mips_defs[] = |
98 | 99 | .SYNCI_Step = 32, |
99 | 100 | .CCRes = 2, |
100 | 101 | .CP0_Status_rw_bitmask = 0x1278FF17, |
102 | + .insn_flags = CPU_MIPS32 | ASE_MIPS16, | |
101 | 103 | }, |
102 | 104 | { |
103 | 105 | .name = "4KEcR1", |
... | ... | @@ -111,6 +113,7 @@ static mips_def_t mips_defs[] = |
111 | 113 | .SYNCI_Step = 32, |
112 | 114 | .CCRes = 2, |
113 | 115 | .CP0_Status_rw_bitmask = 0x1278FF17, |
116 | + .insn_flags = CPU_MIPS32 | ASE_MIPS16, | |
114 | 117 | }, |
115 | 118 | { |
116 | 119 | .name = "4KEc", |
... | ... | @@ -124,6 +127,7 @@ static mips_def_t mips_defs[] = |
124 | 127 | .SYNCI_Step = 32, |
125 | 128 | .CCRes = 2, |
126 | 129 | .CP0_Status_rw_bitmask = 0x1278FF17, |
130 | + .insn_flags = CPU_MIPS32R2 | ASE_MIPS16, | |
127 | 131 | }, |
128 | 132 | { |
129 | 133 | .name = "24Kc", |
... | ... | @@ -138,6 +142,7 @@ static mips_def_t mips_defs[] = |
138 | 142 | .CCRes = 2, |
139 | 143 | /* No DSP implemented. */ |
140 | 144 | .CP0_Status_rw_bitmask = 0x1278FF17, |
145 | + .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, | |
141 | 146 | }, |
142 | 147 | { |
143 | 148 | .name = "24Kf", |
... | ... | @@ -154,6 +159,7 @@ static mips_def_t mips_defs[] = |
154 | 159 | .CP0_Status_rw_bitmask = 0x3678FF17, |
155 | 160 | .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | |
156 | 161 | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), |
162 | + .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, | |
157 | 163 | }, |
158 | 164 | { |
159 | 165 | .name = "34Kf", |
... | ... | @@ -193,6 +199,7 @@ static mips_def_t mips_defs[] = |
193 | 199 | .CP0_SRSConf4_rw_bitmask = 0x3fffffff, |
194 | 200 | .CP0_SRSConf4 = (0x3fe << CP0SRSC4_SRS15) | |
195 | 201 | (0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13), |
202 | + .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, | |
196 | 203 | }, |
197 | 204 | #ifdef TARGET_MIPS64 |
198 | 205 | { |
... | ... | @@ -210,6 +217,7 @@ static mips_def_t mips_defs[] = |
210 | 217 | /* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */ |
211 | 218 | .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), |
212 | 219 | .SEGBITS = 40, |
220 | + .insn_flags = CPU_MIPS3, | |
213 | 221 | }, |
214 | 222 | { |
215 | 223 | .name = "5Kc", |
... | ... | @@ -225,6 +233,7 @@ static mips_def_t mips_defs[] = |
225 | 233 | .CCRes = 2, |
226 | 234 | .CP0_Status_rw_bitmask = 0x32F8FFFF, |
227 | 235 | .SEGBITS = 42, |
236 | + .insn_flags = CPU_MIPS64, | |
228 | 237 | }, |
229 | 238 | { |
230 | 239 | .name = "5Kf", |
... | ... | @@ -243,6 +252,7 @@ static mips_def_t mips_defs[] = |
243 | 252 | .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) | |
244 | 253 | (0x81 << FCR0_PRID) | (0x0 << FCR0_REV), |
245 | 254 | .SEGBITS = 42, |
255 | + .insn_flags = CPU_MIPS64, | |
246 | 256 | }, |
247 | 257 | { |
248 | 258 | .name = "20Kc", |
... | ... | @@ -264,6 +274,7 @@ static mips_def_t mips_defs[] = |
264 | 274 | (1 << FCR0_D) | (1 << FCR0_S) | |
265 | 275 | (0x82 << FCR0_PRID) | (0x0 << FCR0_REV), |
266 | 276 | .SEGBITS = 40, |
277 | + .insn_flags = CPU_MIPS64 | ASE_MIPS3D, | |
267 | 278 | }, |
268 | 279 | #endif |
269 | 280 | }; |
... | ... | @@ -406,7 +417,7 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) |
406 | 417 | env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask; |
407 | 418 | env->CP0_SRSCtl = def->CP0_SRSCtl; |
408 | 419 | #ifdef TARGET_MIPS64 |
409 | - if ((env->CP0_Config0 & (0x3 << CP0C0_AT))) | |
420 | + if (def->insn_flags & ISA_MIPS3) | |
410 | 421 | { |
411 | 422 | env->hflags |= MIPS_HFLAG_64; |
412 | 423 | env->SEGBITS = def->SEGBITS; |
... | ... | @@ -426,6 +437,7 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) |
426 | 437 | env->CP0_SRSConf3 = def->CP0_SRSConf3; |
427 | 438 | env->CP0_SRSConf4_rw_bitmask = def->CP0_SRSConf4_rw_bitmask; |
428 | 439 | env->CP0_SRSConf4 = def->CP0_SRSConf4; |
440 | + env->insn_flags = def->insn_flags; | |
429 | 441 | |
430 | 442 | #ifndef CONFIG_USER_ONLY |
431 | 443 | mmu_init(env, def); | ... | ... |