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); | ... | ... |