| 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
| 2 | * Mupen64plus - interpreter_cop0.def * |
| 3 | * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * |
| 4 | * Copyright (C) 2002 Hacktarux * |
| 5 | * * |
| 6 | * This program is free software; you can redistribute it and/or modify * |
| 7 | * it under the terms of the GNU General Public License as published by * |
| 8 | * the Free Software Foundation; either version 2 of the License, or * |
| 9 | * (at your option) any later version. * |
| 10 | * * |
| 11 | * This program is distributed in the hope that it will be useful, * |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
| 14 | * GNU General Public License for more details. * |
| 15 | * * |
| 16 | * You should have received a copy of the GNU General Public License * |
| 17 | * along with this program; if not, write to the * |
| 18 | * Free Software Foundation, Inc., * |
| 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
| 20 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
| 21 | |
| 22 | DECLARE_INSTRUCTION(MFC0) |
| 23 | { |
| 24 | switch(PC->f.r.nrd) |
| 25 | { |
| 26 | case 1: |
| 27 | DebugMessage(M64MSG_ERROR, "MFC0 instruction reading un-implemented Random register"); |
| 28 | stop=1; |
| 29 | case 9: // Count |
| 30 | update_count(); |
| 31 | default: |
| 32 | rrt32 = reg_cop0[PC->f.r.nrd]; |
| 33 | sign_extended(rrt); |
| 34 | } |
| 35 | ADD_TO_PC(1); |
| 36 | } |
| 37 | |
| 38 | DECLARE_INSTRUCTION(MTC0) |
| 39 | { |
| 40 | switch(PC->f.r.nrd) |
| 41 | { |
| 42 | case 0: // Index |
| 43 | Index = (unsigned int) rrt & 0x8000003F; |
| 44 | if ((Index & 0x3F) > 31) |
| 45 | { |
| 46 | DebugMessage(M64MSG_ERROR, "MTC0 instruction writing Index register with TLB index > 31"); |
| 47 | stop=1; |
| 48 | } |
| 49 | break; |
| 50 | case 1: // Random |
| 51 | break; |
| 52 | case 2: // EntryLo0 |
| 53 | EntryLo0 = (unsigned int) rrt & 0x3FFFFFFF; |
| 54 | break; |
| 55 | case 3: // EntryLo1 |
| 56 | EntryLo1 = (unsigned int) rrt & 0x3FFFFFFF; |
| 57 | break; |
| 58 | case 4: // Context |
| 59 | Context = ((unsigned int) rrt & 0xFF800000) | (Context & 0x007FFFF0); |
| 60 | break; |
| 61 | case 5: // PageMask |
| 62 | PageMask = (unsigned int) rrt & 0x01FFE000; |
| 63 | break; |
| 64 | case 6: // Wired |
| 65 | Wired = (unsigned int) rrt; |
| 66 | Random = 31; |
| 67 | break; |
| 68 | case 8: // BadVAddr |
| 69 | break; |
| 70 | case 9: // Count |
| 71 | update_count(); |
| 72 | interupt_unsafe_state = 1; |
| 73 | if (next_interupt <= Count) gen_interupt(); |
| 74 | interupt_unsafe_state = 0; |
| 75 | translate_event_queue((unsigned int) rrt & 0xFFFFFFFF); |
| 76 | Count = (unsigned int) rrt & 0xFFFFFFFF; |
| 77 | break; |
| 78 | case 10: // EntryHi |
| 79 | EntryHi = (unsigned int) rrt & 0xFFFFE0FF; |
| 80 | break; |
| 81 | case 11: // Compare |
| 82 | update_count(); |
| 83 | remove_event(COMPARE_INT); |
| 84 | add_interupt_event_count(COMPARE_INT, (unsigned int)rrt); |
| 85 | Compare = (unsigned int) rrt; |
| 86 | Cause = Cause & 0xFFFF7FFF; //Timer interupt is clear |
| 87 | break; |
| 88 | case 12: // Status |
| 89 | if((rrt & 0x04000000) != (Status & 0x04000000)) |
| 90 | { |
| 91 | shuffle_fpr_data(Status, (unsigned int) rrt); |
| 92 | set_fpr_pointers((unsigned int) rrt); |
| 93 | } |
| 94 | Status = (unsigned int) rrt; |
| 95 | update_count(); |
| 96 | ADD_TO_PC(1); |
| 97 | check_interupt(); |
| 98 | interupt_unsafe_state = 1; |
| 99 | if (next_interupt <= Count) gen_interupt(); |
| 100 | interupt_unsafe_state = 0; |
| 101 | ADD_TO_PC(-1); |
| 102 | break; |
| 103 | case 13: // Cause |
| 104 | if (rrt!=0) |
| 105 | { |
| 106 | DebugMessage(M64MSG_ERROR, "MTC0 instruction trying to write Cause register with non-0 value"); |
| 107 | stop = 1; |
| 108 | } |
| 109 | else Cause = (unsigned int) rrt; |
| 110 | break; |
| 111 | case 14: // EPC |
| 112 | EPC = (unsigned int) rrt; |
| 113 | break; |
| 114 | case 15: // PRevID |
| 115 | break; |
| 116 | case 16: // Config |
| 117 | Config = (unsigned int) rrt; |
| 118 | break; |
| 119 | case 18: // WatchLo |
| 120 | WatchLo = (unsigned int) rrt & 0xFFFFFFFF; |
| 121 | break; |
| 122 | case 19: // WatchHi |
| 123 | WatchHi = (unsigned int) rrt & 0xFFFFFFFF; |
| 124 | break; |
| 125 | case 27: // CacheErr |
| 126 | break; |
| 127 | case 28: // TagLo |
| 128 | TagLo = (unsigned int) rrt & 0x0FFFFFC0; |
| 129 | break; |
| 130 | case 29: // TagHi |
| 131 | TagHi =0; |
| 132 | break; |
| 133 | default: |
| 134 | DebugMessage(M64MSG_ERROR, "Unknown MTC0 write: %d", PC->f.r.nrd); |
| 135 | stop=1; |
| 136 | } |
| 137 | ADD_TO_PC(1); |
| 138 | } |