Commit 8c0fdd856c63eb11ec5ef955731b1b0cda51f967
1 parent
873eb012
Dynamically translate MIPS mtc0 instructions.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2223 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
423 additions
and
220 deletions
target-mips/exec.h
| ... | ... | @@ -68,7 +68,8 @@ void do_msubu (void); |
| 68 | 68 | #endif |
| 69 | 69 | void do_mfc0_random(void); |
| 70 | 70 | void do_mfc0_count(void); |
| 71 | -void do_mtc0(int reg, int sel); | |
| 71 | +void do_mtc0_status_debug(uint32_t old, uint32_t val); | |
| 72 | +void do_mtc0_status_irqraise_debug(void); | |
| 72 | 73 | void do_tlbwi (void); |
| 73 | 74 | void do_tlbwr (void); |
| 74 | 75 | void do_tlbp (void); | ... | ... |
target-mips/op.c
| ... | ... | @@ -852,9 +852,185 @@ void op_mfc0_desave (void) |
| 852 | 852 | RETURN(); |
| 853 | 853 | } |
| 854 | 854 | |
| 855 | -void op_mtc0 (void) | |
| 855 | +void op_mtc0_index (void) | |
| 856 | 856 | { |
| 857 | - CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2); | |
| 857 | + env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); | |
| 858 | + RETURN(); | |
| 859 | +} | |
| 860 | + | |
| 861 | +void op_mtc0_entrylo0 (void) | |
| 862 | +{ | |
| 863 | + env->CP0_EntryLo0 = T0 & 0x3FFFFFFF; | |
| 864 | + RETURN(); | |
| 865 | +} | |
| 866 | + | |
| 867 | +void op_mtc0_entrylo1 (void) | |
| 868 | +{ | |
| 869 | + env->CP0_EntryLo1 = T0 & 0x3FFFFFFF; | |
| 870 | + RETURN(); | |
| 871 | +} | |
| 872 | + | |
| 873 | +void op_mtc0_context (void) | |
| 874 | +{ | |
| 875 | + env->CP0_Context = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0); | |
| 876 | + RETURN(); | |
| 877 | +} | |
| 878 | + | |
| 879 | +void op_mtc0_pagemask (void) | |
| 880 | +{ | |
| 881 | + env->CP0_PageMask = T0 & 0x01FFE000; | |
| 882 | + RETURN(); | |
| 883 | +} | |
| 884 | + | |
| 885 | +void op_mtc0_wired (void) | |
| 886 | +{ | |
| 887 | + env->CP0_Wired = T0 & 0x0000000F; | |
| 888 | + RETURN(); | |
| 889 | +} | |
| 890 | + | |
| 891 | +void op_mtc0_count (void) | |
| 892 | +{ | |
| 893 | + CALL_FROM_TB2(cpu_mips_store_count, env, T0); | |
| 894 | + RETURN(); | |
| 895 | +} | |
| 896 | + | |
| 897 | +void op_mtc0_entryhi (void) | |
| 898 | +{ | |
| 899 | + uint32_t old, val; | |
| 900 | + | |
| 901 | + val = T0 & 0xFFFFE0FF; | |
| 902 | + old = env->CP0_EntryHi; | |
| 903 | + env->CP0_EntryHi = val; | |
| 904 | + /* If the ASID changes, flush qemu's TLB. */ | |
| 905 | + if ((old & 0xFF) != (val & 0xFF)) | |
| 906 | + CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1); | |
| 907 | + RETURN(); | |
| 908 | +} | |
| 909 | + | |
| 910 | +void op_mtc0_compare (void) | |
| 911 | +{ | |
| 912 | + CALL_FROM_TB2(cpu_mips_store_compare, env, T0); | |
| 913 | + RETURN(); | |
| 914 | +} | |
| 915 | + | |
| 916 | +void op_mtc0_status (void) | |
| 917 | +{ | |
| 918 | + uint32_t val, old, mask; | |
| 919 | + | |
| 920 | + val = T0 & 0xFA78FF01; | |
| 921 | + old = env->CP0_Status; | |
| 922 | + if (T0 & (1 << CP0St_UM)) | |
| 923 | + env->hflags |= MIPS_HFLAG_UM; | |
| 924 | + else | |
| 925 | + env->hflags &= ~MIPS_HFLAG_UM; | |
| 926 | + if (T0 & (1 << CP0St_ERL)) | |
| 927 | + env->hflags |= MIPS_HFLAG_ERL; | |
| 928 | + else | |
| 929 | + env->hflags &= ~MIPS_HFLAG_ERL; | |
| 930 | + if (T0 & (1 << CP0St_EXL)) | |
| 931 | + env->hflags |= MIPS_HFLAG_EXL; | |
| 932 | + else | |
| 933 | + env->hflags &= ~MIPS_HFLAG_EXL; | |
| 934 | + env->CP0_Status = val; | |
| 935 | + /* If we unmasked an asserted IRQ, raise it */ | |
| 936 | + mask = 0x0000FF00; | |
| 937 | + if (loglevel & CPU_LOG_TB_IN_ASM) | |
| 938 | + CALL_FROM_TB2(do_mtc0_status_debug, old, val); | |
| 939 | + if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) && | |
| 940 | + !(env->hflags & MIPS_HFLAG_EXL) && | |
| 941 | + !(env->hflags & MIPS_HFLAG_ERL) && | |
| 942 | + !(env->hflags & MIPS_HFLAG_DM) && | |
| 943 | + (env->CP0_Status & env->CP0_Cause & mask)) { | |
| 944 | + env->interrupt_request |= CPU_INTERRUPT_HARD; | |
| 945 | + if (logfile) | |
| 946 | + CALL_FROM_TB0(do_mtc0_status_irqraise_debug); | |
| 947 | + } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) { | |
| 948 | + env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
| 949 | + } | |
| 950 | + RETURN(); | |
| 951 | +} | |
| 952 | + | |
| 953 | +void op_mtc0_cause (void) | |
| 954 | +{ | |
| 955 | + uint32_t val, old; | |
| 956 | + | |
| 957 | + val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300); | |
| 958 | + old = env->CP0_Cause; | |
| 959 | + env->CP0_Cause = val; | |
| 960 | +#if 0 | |
| 961 | + { | |
| 962 | + int i, mask; | |
| 963 | + | |
| 964 | + /* Check if we ever asserted a software IRQ */ | |
| 965 | + for (i = 0; i < 2; i++) { | |
| 966 | + mask = 0x100 << i; | |
| 967 | + if ((val & mask) & !(old & mask)) | |
| 968 | + CALL_FROM_TB1(mips_set_irq, i); | |
| 969 | + } | |
| 970 | + } | |
| 971 | +#endif | |
| 972 | + RETURN(); | |
| 973 | +} | |
| 974 | + | |
| 975 | +void op_mtc0_epc (void) | |
| 976 | +{ | |
| 977 | + env->CP0_EPC = T0; | |
| 978 | + RETURN(); | |
| 979 | +} | |
| 980 | + | |
| 981 | +void op_mtc0_config0 (void) | |
| 982 | +{ | |
| 983 | +#if defined(MIPS_USES_R4K_TLB) | |
| 984 | + env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); | |
| 985 | +#else | |
| 986 | + env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); | |
| 987 | +#endif | |
| 988 | + RETURN(); | |
| 989 | +} | |
| 990 | + | |
| 991 | +void op_mtc0_watchlo (void) | |
| 992 | +{ | |
| 993 | + env->CP0_WatchLo = T0; | |
| 994 | + RETURN(); | |
| 995 | +} | |
| 996 | + | |
| 997 | +void op_mtc0_watchhi (void) | |
| 998 | +{ | |
| 999 | + env->CP0_WatchHi = T0 & 0x40FF0FF8; | |
| 1000 | + RETURN(); | |
| 1001 | +} | |
| 1002 | + | |
| 1003 | +void op_mtc0_debug (void) | |
| 1004 | +{ | |
| 1005 | + env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); | |
| 1006 | + if (T0 & (1 << CP0DB_DM)) | |
| 1007 | + env->hflags |= MIPS_HFLAG_DM; | |
| 1008 | + else | |
| 1009 | + env->hflags &= ~MIPS_HFLAG_DM; | |
| 1010 | + RETURN(); | |
| 1011 | +} | |
| 1012 | + | |
| 1013 | +void op_mtc0_depc (void) | |
| 1014 | +{ | |
| 1015 | + env->CP0_DEPC = T0; | |
| 1016 | + RETURN(); | |
| 1017 | +} | |
| 1018 | + | |
| 1019 | +void op_mtc0_taglo (void) | |
| 1020 | +{ | |
| 1021 | + env->CP0_TagLo = T0 & 0xFFFFFCF6; | |
| 1022 | + RETURN(); | |
| 1023 | +} | |
| 1024 | + | |
| 1025 | +void op_mtc0_errorepc (void) | |
| 1026 | +{ | |
| 1027 | + env->CP0_ErrorEPC = T0; | |
| 1028 | + RETURN(); | |
| 1029 | +} | |
| 1030 | + | |
| 1031 | +void op_mtc0_desave (void) | |
| 1032 | +{ | |
| 1033 | + env->CP0_DESAVE = T0; | |
| 858 | 1034 | RETURN(); |
| 859 | 1035 | } |
| 860 | 1036 | ... | ... |
target-mips/op_helper.c
| ... | ... | @@ -141,9 +141,24 @@ void do_mfc0_count (void) |
| 141 | 141 | cpu_abort(env, "mfc0 count\n"); |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | -void do_mtc0 (int reg, int sel) | |
| 144 | +void cpu_mips_store_count(CPUState *env, uint32_t value) | |
| 145 | 145 | { |
| 146 | - cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel); | |
| 146 | + cpu_abort(env, "mtc0 count\n"); | |
| 147 | +} | |
| 148 | + | |
| 149 | +void cpu_mips_store_compare(CPUState *env, uint32_t value) | |
| 150 | +{ | |
| 151 | + cpu_abort(env, "mtc0 compare\n"); | |
| 152 | +} | |
| 153 | + | |
| 154 | +void do_mtc0_status_debug(uint32_t old, uint32_t val) | |
| 155 | +{ | |
| 156 | + cpu_abort(env, "mtc0 status\n"); | |
| 157 | +} | |
| 158 | + | |
| 159 | +void do_mtc0_status_irqraise_debug(void) | |
| 160 | +{ | |
| 161 | + cpu_abort(env, "mtc0 status\n"); | |
| 147 | 162 | } |
| 148 | 163 | |
| 149 | 164 | void do_tlbwi (void) |
| ... | ... | @@ -166,6 +181,11 @@ void do_tlbr (void) |
| 166 | 181 | cpu_abort(env, "tlbr\n"); |
| 167 | 182 | } |
| 168 | 183 | |
| 184 | +void cpu_mips_tlb_flush (CPUState *env, int flush_global) | |
| 185 | +{ | |
| 186 | + cpu_abort(env, "mips_tlb_flush\n"); | |
| 187 | +} | |
| 188 | + | |
| 169 | 189 | #else |
| 170 | 190 | |
| 171 | 191 | /* CP0 helpers */ |
| ... | ... | @@ -179,222 +199,17 @@ void do_mfc0_count (void) |
| 179 | 199 | T0 = cpu_mips_get_count(env); |
| 180 | 200 | } |
| 181 | 201 | |
| 182 | -void do_mtc0 (int reg, int sel) | |
| 202 | +void do_mtc0_status_debug(uint32_t old, uint32_t val) | |
| 183 | 203 | { |
| 184 | - const unsigned char *rn; | |
| 185 | - uint32_t val, old, mask; | |
| 204 | + const uint32_t mask = 0x0000FF00; | |
| 205 | + fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n", | |
| 206 | + old, val, env->CP0_Cause, old & mask, val & mask, | |
| 207 | + env->CP0_Cause & mask); | |
| 208 | +} | |
| 186 | 209 | |
| 187 | - if (sel != 0 && reg != 16 && reg != 28) { | |
| 188 | - val = -1; | |
| 189 | - old = -1; | |
| 190 | - rn = "invalid"; | |
| 191 | - goto print; | |
| 192 | - } | |
| 193 | - switch (reg) { | |
| 194 | - case 0: | |
| 195 | - val = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); | |
| 196 | - old = env->CP0_index; | |
| 197 | - env->CP0_index = val; | |
| 198 | - rn = "Index"; | |
| 199 | - break; | |
| 200 | - case 2: | |
| 201 | - val = T0 & 0x3FFFFFFF; | |
| 202 | - old = env->CP0_EntryLo0; | |
| 203 | - env->CP0_EntryLo0 = val; | |
| 204 | - rn = "EntryLo0"; | |
| 205 | - break; | |
| 206 | - case 3: | |
| 207 | - val = T0 & 0x3FFFFFFF; | |
| 208 | - old = env->CP0_EntryLo1; | |
| 209 | - env->CP0_EntryLo1 = val; | |
| 210 | - rn = "EntryLo1"; | |
| 211 | - break; | |
| 212 | - case 4: | |
| 213 | - val = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0); | |
| 214 | - old = env->CP0_Context; | |
| 215 | - env->CP0_Context = val; | |
| 216 | - rn = "Context"; | |
| 217 | - break; | |
| 218 | - case 5: | |
| 219 | - val = T0 & 0x01FFE000; | |
| 220 | - old = env->CP0_PageMask; | |
| 221 | - env->CP0_PageMask = val; | |
| 222 | - rn = "PageMask"; | |
| 223 | - break; | |
| 224 | - case 6: | |
| 225 | - val = T0 & 0x0000000F; | |
| 226 | - old = env->CP0_Wired; | |
| 227 | - env->CP0_Wired = val; | |
| 228 | - rn = "Wired"; | |
| 229 | - break; | |
| 230 | - case 9: | |
| 231 | - val = T0; | |
| 232 | - old = cpu_mips_get_count(env); | |
| 233 | - cpu_mips_store_count(env, val); | |
| 234 | - rn = "Count"; | |
| 235 | - break; | |
| 236 | - case 10: | |
| 237 | - val = T0 & 0xFFFFE0FF; | |
| 238 | - old = env->CP0_EntryHi; | |
| 239 | - env->CP0_EntryHi = val; | |
| 240 | - /* If the ASID changes, flush qemu's TLB. */ | |
| 241 | - if ((old & 0xFF) != (val & 0xFF)) | |
| 242 | - cpu_mips_tlb_flush (env, 1); | |
| 243 | - rn = "EntryHi"; | |
| 244 | - break; | |
| 245 | - case 11: | |
| 246 | - val = T0; | |
| 247 | - old = env->CP0_Compare; | |
| 248 | - cpu_mips_store_compare(env, val); | |
| 249 | - rn = "Compare"; | |
| 250 | - break; | |
| 251 | - case 12: | |
| 252 | - val = T0 & 0xFA78FF01; | |
| 253 | - if (T0 & (1 << CP0St_UM)) | |
| 254 | - env->hflags |= MIPS_HFLAG_UM; | |
| 255 | - else | |
| 256 | - env->hflags &= ~MIPS_HFLAG_UM; | |
| 257 | - if (T0 & (1 << CP0St_ERL)) | |
| 258 | - env->hflags |= MIPS_HFLAG_ERL; | |
| 259 | - else | |
| 260 | - env->hflags &= ~MIPS_HFLAG_ERL; | |
| 261 | - if (T0 & (1 << CP0St_EXL)) | |
| 262 | - env->hflags |= MIPS_HFLAG_EXL; | |
| 263 | - else | |
| 264 | - env->hflags &= ~MIPS_HFLAG_EXL; | |
| 265 | - old = env->CP0_Status; | |
| 266 | - env->CP0_Status = val; | |
| 267 | - /* If we unmasked an asserted IRQ, raise it */ | |
| 268 | - mask = 0x0000FF00; | |
| 269 | - if (loglevel & CPU_LOG_TB_IN_ASM) { | |
| 270 | - fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n", | |
| 271 | - old, val, env->CP0_Cause, old & mask, val & mask, | |
| 272 | - env->CP0_Cause & mask); | |
| 273 | - } | |
| 274 | - if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) && | |
| 275 | - !(env->hflags & MIPS_HFLAG_EXL) && | |
| 276 | - !(env->hflags & MIPS_HFLAG_ERL) && | |
| 277 | - !(env->hflags & MIPS_HFLAG_DM) && | |
| 278 | - (env->CP0_Status & env->CP0_Cause & mask)) { | |
| 279 | - if (logfile) | |
| 280 | - fprintf(logfile, "Raise pending IRQs\n"); | |
| 281 | - env->interrupt_request |= CPU_INTERRUPT_HARD; | |
| 282 | - } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) { | |
| 283 | - env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
| 284 | - } | |
| 285 | - rn = "Status"; | |
| 286 | - break; | |
| 287 | - case 13: | |
| 288 | - val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300); | |
| 289 | - old = env->CP0_Cause; | |
| 290 | - env->CP0_Cause = val; | |
| 291 | -#if 0 | |
| 292 | - { | |
| 293 | - int i; | |
| 294 | - /* Check if we ever asserted a software IRQ */ | |
| 295 | - for (i = 0; i < 2; i++) { | |
| 296 | - mask = 0x100 << i; | |
| 297 | - if ((val & mask) & !(old & mask)) | |
| 298 | - mips_set_irq(i); | |
| 299 | - } | |
| 300 | - } | |
| 301 | -#endif | |
| 302 | - rn = "Cause"; | |
| 303 | - break; | |
| 304 | - case 14: | |
| 305 | - val = T0; | |
| 306 | - old = env->CP0_EPC; | |
| 307 | - env->CP0_EPC = val; | |
| 308 | - rn = "EPC"; | |
| 309 | - break; | |
| 310 | - case 16: | |
| 311 | - switch (sel) { | |
| 312 | - case 0: | |
| 313 | -#if defined(MIPS_USES_R4K_TLB) | |
| 314 | - val = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); | |
| 315 | -#else | |
| 316 | - val = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); | |
| 317 | -#endif | |
| 318 | - old = env->CP0_Config0; | |
| 319 | - env->CP0_Config0 = val; | |
| 320 | - rn = "Config0"; | |
| 321 | - break; | |
| 322 | - default: | |
| 323 | - val = -1; | |
| 324 | - old = -1; | |
| 325 | - rn = "bad config selector"; | |
| 326 | - break; | |
| 327 | - } | |
| 328 | - break; | |
| 329 | - case 18: | |
| 330 | - val = T0; | |
| 331 | - old = env->CP0_WatchLo; | |
| 332 | - env->CP0_WatchLo = val; | |
| 333 | - rn = "WatchLo"; | |
| 334 | - break; | |
| 335 | - case 19: | |
| 336 | - val = T0 & 0x40FF0FF8; | |
| 337 | - old = env->CP0_WatchHi; | |
| 338 | - env->CP0_WatchHi = val; | |
| 339 | - rn = "WatchHi"; | |
| 340 | - break; | |
| 341 | - case 23: | |
| 342 | - val = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); | |
| 343 | - if (T0 & (1 << CP0DB_DM)) | |
| 344 | - env->hflags |= MIPS_HFLAG_DM; | |
| 345 | - else | |
| 346 | - env->hflags &= ~MIPS_HFLAG_DM; | |
| 347 | - old = env->CP0_Debug; | |
| 348 | - env->CP0_Debug = val; | |
| 349 | - rn = "Debug"; | |
| 350 | - break; | |
| 351 | - case 24: | |
| 352 | - val = T0; | |
| 353 | - old = env->CP0_DEPC; | |
| 354 | - env->CP0_DEPC = val; | |
| 355 | - rn = "DEPC"; | |
| 356 | - break; | |
| 357 | - case 28: | |
| 358 | - switch (sel) { | |
| 359 | - case 0: | |
| 360 | - val = T0 & 0xFFFFFCF6; | |
| 361 | - old = env->CP0_TagLo; | |
| 362 | - env->CP0_TagLo = val; | |
| 363 | - rn = "TagLo"; | |
| 364 | - break; | |
| 365 | - default: | |
| 366 | - val = -1; | |
| 367 | - old = -1; | |
| 368 | - rn = "invalid sel"; | |
| 369 | - break; | |
| 370 | - } | |
| 371 | - break; | |
| 372 | - case 30: | |
| 373 | - val = T0; | |
| 374 | - old = env->CP0_ErrorEPC; | |
| 375 | - env->CP0_ErrorEPC = val; | |
| 376 | - rn = "EPC"; | |
| 377 | - break; | |
| 378 | - case 31: | |
| 379 | - val = T0; | |
| 380 | - old = env->CP0_DESAVE; | |
| 381 | - env->CP0_DESAVE = val; | |
| 382 | - rn = "DESAVE"; | |
| 383 | - break; | |
| 384 | - default: | |
| 385 | - val = -1; | |
| 386 | - old = -1; | |
| 387 | - rn = "unknown"; | |
| 388 | - break; | |
| 389 | - } | |
| 390 | - print: | |
| 391 | -#if defined MIPS_DEBUG_DISAS | |
| 392 | - if (loglevel & CPU_LOG_TB_IN_ASM) { | |
| 393 | - fprintf(logfile, "%08x mtc0 %s %08x => %08x (%d %d %08x)\n", | |
| 394 | - env->PC, rn, T0, val, reg, sel, old); | |
| 395 | - } | |
| 396 | -#endif | |
| 397 | - return; | |
| 210 | +void do_mtc0_status_irqraise_debug(void) | |
| 211 | +{ | |
| 212 | + fprintf(logfile, "Raise pending IRQs\n"); | |
| 398 | 213 | } |
| 399 | 214 | |
| 400 | 215 | #ifdef MIPS_USES_FPU | ... | ... |
target-mips/translate.c
| ... | ... | @@ -1371,6 +1371,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
| 1371 | 1371 | rn = "EntryLo0"; |
| 1372 | 1372 | break; |
| 1373 | 1373 | case 3: |
| 1374 | + /* also CONF */ | |
| 1374 | 1375 | gen_op_mfc0_entrylo1(); |
| 1375 | 1376 | rn = "EntryLo1"; |
| 1376 | 1377 | break; |
| ... | ... | @@ -1386,6 +1387,10 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
| 1386 | 1387 | gen_op_mfc0_wired(); |
| 1387 | 1388 | rn = "Wired"; |
| 1388 | 1389 | break; |
| 1390 | + case 7: | |
| 1391 | +// gen_op_mfc0_info(); | |
| 1392 | + rn = "Info"; | |
| 1393 | + break; | |
| 1389 | 1394 | case 8: |
| 1390 | 1395 | gen_op_mfc0_badvaddr(); |
| 1391 | 1396 | rn = "BadVaddr"; |
| ... | ... | @@ -1445,6 +1450,19 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
| 1445 | 1450 | gen_op_mfc0_watchhi(); |
| 1446 | 1451 | rn = "WatchHi"; |
| 1447 | 1452 | break; |
| 1453 | + case 20: | |
| 1454 | + /* 64 bit only */ | |
| 1455 | +// gen_op_mfc0_xcontext(); | |
| 1456 | + rn = "XContext"; | |
| 1457 | + break; | |
| 1458 | + case 21: | |
| 1459 | +// gen_op_mfc0_framemask(); | |
| 1460 | + rn = "Framemask"; | |
| 1461 | + break; | |
| 1462 | + case 22: | |
| 1463 | +// gen_op_mfc0_diagnostic(); | |
| 1464 | + rn = "'Diagnostic"; | |
| 1465 | + break; | |
| 1448 | 1466 | case 23: |
| 1449 | 1467 | gen_op_mfc0_debug(); |
| 1450 | 1468 | rn = "Debug"; |
| ... | ... | @@ -1453,6 +1471,18 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
| 1453 | 1471 | gen_op_mfc0_depc(); |
| 1454 | 1472 | rn = "DEPC"; |
| 1455 | 1473 | break; |
| 1474 | + case 25: | |
| 1475 | +// gen_op_mfc0_performance(); | |
| 1476 | + rn = "Performance"; | |
| 1477 | + break; | |
| 1478 | + case 26: | |
| 1479 | +// gen_op_mfc0_ecc(); | |
| 1480 | + rn = "ECC"; | |
| 1481 | + break; | |
| 1482 | + case 27: | |
| 1483 | +// gen_op_mfc0_cacheerr(); | |
| 1484 | + rn = "CacheErr"; | |
| 1485 | + break; | |
| 1456 | 1486 | case 28: |
| 1457 | 1487 | switch (sel) { |
| 1458 | 1488 | case 0: |
| ... | ... | @@ -1468,6 +1498,10 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
| 1468 | 1498 | goto die; |
| 1469 | 1499 | } |
| 1470 | 1500 | break; |
| 1501 | + case 29: | |
| 1502 | +// gen_op_mfc0_taghi(); | |
| 1503 | + rn = "TagHi"; | |
| 1504 | + break; | |
| 1471 | 1505 | case 30: |
| 1472 | 1506 | gen_op_mfc0_errorepc(); |
| 1473 | 1507 | rn = "ErrorEPC"; |
| ... | ... | @@ -1498,6 +1532,183 @@ die: |
| 1498 | 1532 | generate_exception(ctx, EXCP_RI); |
| 1499 | 1533 | } |
| 1500 | 1534 | |
| 1535 | +static void gen_mtc0 (DisasContext *ctx, int reg, int sel) | |
| 1536 | +{ | |
| 1537 | + const unsigned char *rn; | |
| 1538 | + uint32_t val, old; | |
| 1539 | + | |
| 1540 | + if (sel != 0 && reg != 16 && reg != 28) { | |
| 1541 | + val = -1; | |
| 1542 | + old = -1; | |
| 1543 | + rn = "invalid"; | |
| 1544 | + goto die; | |
| 1545 | + } | |
| 1546 | + switch (reg) { | |
| 1547 | + case 0: | |
| 1548 | + gen_op_mtc0_index(); | |
| 1549 | + rn = "Index"; | |
| 1550 | + break; | |
| 1551 | + case 1: | |
| 1552 | +// ignore or except? | |
| 1553 | + rn = "Random"; | |
| 1554 | + break; | |
| 1555 | + case 2: | |
| 1556 | + gen_op_mtc0_entrylo0(); | |
| 1557 | + rn = "EntryLo0"; | |
| 1558 | + break; | |
| 1559 | + case 3: | |
| 1560 | + gen_op_mtc0_entrylo1(); | |
| 1561 | + rn = "EntryLo1"; | |
| 1562 | + break; | |
| 1563 | + case 4: | |
| 1564 | + gen_op_mtc0_context(); | |
| 1565 | + rn = "Context"; | |
| 1566 | + break; | |
| 1567 | + case 5: | |
| 1568 | + gen_op_mtc0_pagemask(); | |
| 1569 | + rn = "PageMask"; | |
| 1570 | + break; | |
| 1571 | + case 6: | |
| 1572 | + gen_op_mtc0_wired(); | |
| 1573 | + rn = "Wired"; | |
| 1574 | + break; | |
| 1575 | + case 7: | |
| 1576 | +// ignore or except? | |
| 1577 | + rn = "Info"; | |
| 1578 | + break; | |
| 1579 | + case 8: | |
| 1580 | +// ignore or except? | |
| 1581 | + rn = "BadVaddr"; | |
| 1582 | + break; | |
| 1583 | + case 9: | |
| 1584 | + gen_op_mtc0_count(); | |
| 1585 | + rn = "Count"; | |
| 1586 | + break; | |
| 1587 | + case 10: | |
| 1588 | + gen_op_mtc0_entryhi(); | |
| 1589 | + rn = "EntryHi"; | |
| 1590 | + break; | |
| 1591 | + case 11: | |
| 1592 | + gen_op_mtc0_compare(); | |
| 1593 | + rn = "Compare"; | |
| 1594 | + break; | |
| 1595 | + case 12: | |
| 1596 | + gen_op_mtc0_status(); | |
| 1597 | + rn = "Status"; | |
| 1598 | + break; | |
| 1599 | + case 13: | |
| 1600 | + gen_op_mtc0_cause(); | |
| 1601 | + rn = "Cause"; | |
| 1602 | + break; | |
| 1603 | + case 14: | |
| 1604 | + gen_op_mtc0_epc(); | |
| 1605 | + rn = "EPC"; | |
| 1606 | + break; | |
| 1607 | + case 15: | |
| 1608 | +// ignore or except? | |
| 1609 | + rn = "PRid"; | |
| 1610 | + break; | |
| 1611 | + case 16: | |
| 1612 | + switch (sel) { | |
| 1613 | + case 0: | |
| 1614 | + gen_op_mtc0_config0(); | |
| 1615 | + rn = "Config0"; | |
| 1616 | + break; | |
| 1617 | + default: | |
| 1618 | + rn = "Invalid config selector"; | |
| 1619 | + goto die; | |
| 1620 | + } | |
| 1621 | + break; | |
| 1622 | + case 17: | |
| 1623 | +// ignore or except? | |
| 1624 | + rn = "LLaddr"; | |
| 1625 | + break; | |
| 1626 | + case 18: | |
| 1627 | + gen_op_mtc0_watchlo(); | |
| 1628 | + rn = "WatchLo"; | |
| 1629 | + break; | |
| 1630 | + case 19: | |
| 1631 | + gen_op_mtc0_watchhi(); | |
| 1632 | + rn = "WatchHi"; | |
| 1633 | + break; | |
| 1634 | + case 20: | |
| 1635 | + /* 64 bit only */ | |
| 1636 | +// gen_op_mtc0_xcontext(); | |
| 1637 | + rn = "XContext"; | |
| 1638 | + break; | |
| 1639 | + case 21: | |
| 1640 | +// gen_op_mtc0_framemask(); | |
| 1641 | + rn = "Framemask"; | |
| 1642 | + break; | |
| 1643 | + case 22: | |
| 1644 | +// ignore or except? | |
| 1645 | + rn = "Diagnostic"; | |
| 1646 | + break; | |
| 1647 | + case 23: | |
| 1648 | + gen_op_mtc0_debug(); | |
| 1649 | + rn = "Debug"; | |
| 1650 | + break; | |
| 1651 | + case 24: | |
| 1652 | + gen_op_mtc0_depc(); | |
| 1653 | + rn = "DEPC"; | |
| 1654 | + break; | |
| 1655 | + case 25: | |
| 1656 | +// ignore or except? | |
| 1657 | + rn = "Performance"; | |
| 1658 | + break; | |
| 1659 | + case 26: | |
| 1660 | +// ignore or except? | |
| 1661 | + rn = "ECC"; | |
| 1662 | + break; | |
| 1663 | + case 27: | |
| 1664 | +// ignore or except? | |
| 1665 | + rn = "CacheErr"; | |
| 1666 | + break; | |
| 1667 | + case 28: | |
| 1668 | + switch (sel) { | |
| 1669 | + case 0: | |
| 1670 | + gen_op_mtc0_taglo(); | |
| 1671 | + rn = "TagLo"; | |
| 1672 | + break; | |
| 1673 | + default: | |
| 1674 | + rn = "invalid sel"; | |
| 1675 | + goto die; | |
| 1676 | + } | |
| 1677 | + break; | |
| 1678 | + case 29: | |
| 1679 | +// gen_op_mtc0_taghi(); | |
| 1680 | + rn = "TagHi"; | |
| 1681 | + break; | |
| 1682 | + case 30: | |
| 1683 | + gen_op_mtc0_errorepc(); | |
| 1684 | + rn = "ErrorEPC"; | |
| 1685 | + break; | |
| 1686 | + case 31: | |
| 1687 | + gen_op_mtc0_desave(); | |
| 1688 | + rn = "DESAVE"; | |
| 1689 | + break; | |
| 1690 | + default: | |
| 1691 | + rn = "unknown"; | |
| 1692 | + goto die; | |
| 1693 | + } | |
| 1694 | +#if defined MIPS_DEBUG_DISAS | |
| 1695 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | |
| 1696 | + fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", | |
| 1697 | + env->PC, rn, T0, reg, sel); | |
| 1698 | + } | |
| 1699 | +#endif | |
| 1700 | + return; | |
| 1701 | + | |
| 1702 | +die: | |
| 1703 | +#if defined MIPS_DEBUG_DISAS | |
| 1704 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | |
| 1705 | + fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", | |
| 1706 | + env->PC, rn, T0, reg, sel); | |
| 1707 | + } | |
| 1708 | +#endif | |
| 1709 | + generate_exception(ctx, EXCP_RI); | |
| 1710 | +} | |
| 1711 | + | |
| 1501 | 1712 | static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) |
| 1502 | 1713 | { |
| 1503 | 1714 | const unsigned char *opn = "unk"; |
| ... | ... | @@ -1529,7 +1740,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) |
| 1529 | 1740 | save_cpu_state(ctx, 1); |
| 1530 | 1741 | ctx->pc -= 4; |
| 1531 | 1742 | GEN_LOAD_REG_TN(T0, rt); |
| 1532 | - gen_op_mtc0(rd, ctx->opcode & 0x7); | |
| 1743 | + gen_mtc0(ctx, rd, ctx->opcode & 0x7); | |
| 1533 | 1744 | /* Stop translation as we may have switched the execution mode */ |
| 1534 | 1745 | ctx->bstate = BS_STOP; |
| 1535 | 1746 | opn = "mtc0"; | ... | ... |