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,7 +68,8 @@ void do_msubu (void); | ||
| 68 | #endif | 68 | #endif |
| 69 | void do_mfc0_random(void); | 69 | void do_mfc0_random(void); |
| 70 | void do_mfc0_count(void); | 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 | void do_tlbwi (void); | 73 | void do_tlbwi (void); |
| 73 | void do_tlbwr (void); | 74 | void do_tlbwr (void); |
| 74 | void do_tlbp (void); | 75 | void do_tlbp (void); |
target-mips/op.c
| @@ -852,9 +852,185 @@ void op_mfc0_desave (void) | @@ -852,9 +852,185 @@ void op_mfc0_desave (void) | ||
| 852 | RETURN(); | 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 | RETURN(); | 1034 | RETURN(); |
| 859 | } | 1035 | } |
| 860 | 1036 |
target-mips/op_helper.c
| @@ -141,9 +141,24 @@ void do_mfc0_count (void) | @@ -141,9 +141,24 @@ void do_mfc0_count (void) | ||
| 141 | cpu_abort(env, "mfc0 count\n"); | 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 | void do_tlbwi (void) | 164 | void do_tlbwi (void) |
| @@ -166,6 +181,11 @@ void do_tlbr (void) | @@ -166,6 +181,11 @@ void do_tlbr (void) | ||
| 166 | cpu_abort(env, "tlbr\n"); | 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 | #else | 189 | #else |
| 170 | 190 | ||
| 171 | /* CP0 helpers */ | 191 | /* CP0 helpers */ |
| @@ -179,222 +199,17 @@ void do_mfc0_count (void) | @@ -179,222 +199,17 @@ void do_mfc0_count (void) | ||
| 179 | T0 = cpu_mips_get_count(env); | 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 | #ifdef MIPS_USES_FPU | 215 | #ifdef MIPS_USES_FPU |
target-mips/translate.c
| @@ -1371,6 +1371,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | @@ -1371,6 +1371,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | ||
| 1371 | rn = "EntryLo0"; | 1371 | rn = "EntryLo0"; |
| 1372 | break; | 1372 | break; |
| 1373 | case 3: | 1373 | case 3: |
| 1374 | + /* also CONF */ | ||
| 1374 | gen_op_mfc0_entrylo1(); | 1375 | gen_op_mfc0_entrylo1(); |
| 1375 | rn = "EntryLo1"; | 1376 | rn = "EntryLo1"; |
| 1376 | break; | 1377 | break; |
| @@ -1386,6 +1387,10 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | @@ -1386,6 +1387,10 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | ||
| 1386 | gen_op_mfc0_wired(); | 1387 | gen_op_mfc0_wired(); |
| 1387 | rn = "Wired"; | 1388 | rn = "Wired"; |
| 1388 | break; | 1389 | break; |
| 1390 | + case 7: | ||
| 1391 | +// gen_op_mfc0_info(); | ||
| 1392 | + rn = "Info"; | ||
| 1393 | + break; | ||
| 1389 | case 8: | 1394 | case 8: |
| 1390 | gen_op_mfc0_badvaddr(); | 1395 | gen_op_mfc0_badvaddr(); |
| 1391 | rn = "BadVaddr"; | 1396 | rn = "BadVaddr"; |
| @@ -1445,6 +1450,19 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | @@ -1445,6 +1450,19 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | ||
| 1445 | gen_op_mfc0_watchhi(); | 1450 | gen_op_mfc0_watchhi(); |
| 1446 | rn = "WatchHi"; | 1451 | rn = "WatchHi"; |
| 1447 | break; | 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 | case 23: | 1466 | case 23: |
| 1449 | gen_op_mfc0_debug(); | 1467 | gen_op_mfc0_debug(); |
| 1450 | rn = "Debug"; | 1468 | rn = "Debug"; |
| @@ -1453,6 +1471,18 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | @@ -1453,6 +1471,18 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | ||
| 1453 | gen_op_mfc0_depc(); | 1471 | gen_op_mfc0_depc(); |
| 1454 | rn = "DEPC"; | 1472 | rn = "DEPC"; |
| 1455 | break; | 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 | case 28: | 1486 | case 28: |
| 1457 | switch (sel) { | 1487 | switch (sel) { |
| 1458 | case 0: | 1488 | case 0: |
| @@ -1468,6 +1498,10 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | @@ -1468,6 +1498,10 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | ||
| 1468 | goto die; | 1498 | goto die; |
| 1469 | } | 1499 | } |
| 1470 | break; | 1500 | break; |
| 1501 | + case 29: | ||
| 1502 | +// gen_op_mfc0_taghi(); | ||
| 1503 | + rn = "TagHi"; | ||
| 1504 | + break; | ||
| 1471 | case 30: | 1505 | case 30: |
| 1472 | gen_op_mfc0_errorepc(); | 1506 | gen_op_mfc0_errorepc(); |
| 1473 | rn = "ErrorEPC"; | 1507 | rn = "ErrorEPC"; |
| @@ -1498,6 +1532,183 @@ die: | @@ -1498,6 +1532,183 @@ die: | ||
| 1498 | generate_exception(ctx, EXCP_RI); | 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 | static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | 1712 | static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) |
| 1502 | { | 1713 | { |
| 1503 | const unsigned char *opn = "unk"; | 1714 | const unsigned char *opn = "unk"; |
| @@ -1529,7 +1740,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | @@ -1529,7 +1740,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | ||
| 1529 | save_cpu_state(ctx, 1); | 1740 | save_cpu_state(ctx, 1); |
| 1530 | ctx->pc -= 4; | 1741 | ctx->pc -= 4; |
| 1531 | GEN_LOAD_REG_TN(T0, rt); | 1742 | GEN_LOAD_REG_TN(T0, rt); |
| 1532 | - gen_op_mtc0(rd, ctx->opcode & 0x7); | 1743 | + gen_mtc0(ctx, rd, ctx->opcode & 0x7); |
| 1533 | /* Stop translation as we may have switched the execution mode */ | 1744 | /* Stop translation as we may have switched the execution mode */ |
| 1534 | ctx->bstate = BS_STOP; | 1745 | ctx->bstate = BS_STOP; |
| 1535 | opn = "mtc0"; | 1746 | opn = "mtc0"; |