451ab91e |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - interpreter_tlb.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 | #include <zlib.h> // For adler32() |
23 | |
24 | DECLARE_INSTRUCTION(TLBR) |
25 | { |
26 | int index; |
27 | index = Index & 0x1F; |
28 | PageMask = tlb_e[index].mask << 13; |
29 | EntryHi = ((tlb_e[index].vpn2 << 13) | tlb_e[index].asid); |
30 | EntryLo0 = (tlb_e[index].pfn_even << 6) | (tlb_e[index].c_even << 3) |
31 | | (tlb_e[index].d_even << 2) | (tlb_e[index].v_even << 1) |
32 | | tlb_e[index].g; |
33 | EntryLo1 = (tlb_e[index].pfn_odd << 6) | (tlb_e[index].c_odd << 3) |
34 | | (tlb_e[index].d_odd << 2) | (tlb_e[index].v_odd << 1) |
35 | | tlb_e[index].g; |
36 | ADD_TO_PC(1); |
37 | } |
38 | |
39 | static void TLBWrite(unsigned int idx) |
40 | { |
41 | if (r4300emu != CORE_PURE_INTERPRETER) |
42 | { |
43 | unsigned int i; |
44 | if (tlb_e[idx].v_even) |
45 | { |
46 | for (i=tlb_e[idx].start_even>>12; i<=tlb_e[idx].end_even>>12; i++) |
47 | { |
48 | if(!invalid_code[i] &&(invalid_code[tlb_LUT_r[i]>>12] || |
49 | invalid_code[(tlb_LUT_r[i]>>12)+0x20000])) |
50 | invalid_code[i] = 1; |
51 | if (!invalid_code[i]) |
52 | { |
53 | /*int j; |
54 | md5_state_t state; |
55 | md5_byte_t digest[16]; |
56 | md5_init(&state); |
57 | md5_append(&state, |
58 | (const md5_byte_t*)&rdram[(tlb_LUT_r[i]&0x7FF000)/4], |
59 | 0x1000); |
60 | md5_finish(&state, digest); |
61 | for (j=0; j<16; j++) blocks[i]->md5[j] = digest[j];*/ |
62 | |
63 | blocks[i]->adler32 = adler32(0, (const unsigned char *)&rdram[(tlb_LUT_r[i]&0x7FF000)/4], 0x1000); |
64 | |
65 | invalid_code[i] = 1; |
66 | } |
67 | else if (blocks[i]) |
68 | { |
69 | /*int j; |
70 | for (j=0; j<16; j++) blocks[i]->md5[j] = 0;*/ |
71 | blocks[i]->adler32 = 0; |
72 | } |
73 | } |
74 | } |
75 | if (tlb_e[idx].v_odd) |
76 | { |
77 | for (i=tlb_e[idx].start_odd>>12; i<=tlb_e[idx].end_odd>>12; i++) |
78 | { |
79 | if(!invalid_code[i] &&(invalid_code[tlb_LUT_r[i]>>12] || |
80 | invalid_code[(tlb_LUT_r[i]>>12)+0x20000])) |
81 | invalid_code[i] = 1; |
82 | if (!invalid_code[i]) |
83 | { |
84 | /*int j; |
85 | md5_state_t state; |
86 | md5_byte_t digest[16]; |
87 | md5_init(&state); |
88 | md5_append(&state, |
89 | (const md5_byte_t*)&rdram[(tlb_LUT_r[i]&0x7FF000)/4], |
90 | 0x1000); |
91 | md5_finish(&state, digest); |
92 | for (j=0; j<16; j++) blocks[i]->md5[j] = digest[j];*/ |
93 | |
94 | blocks[i]->adler32 = adler32(0, (const unsigned char *)&rdram[(tlb_LUT_r[i]&0x7FF000)/4], 0x1000); |
95 | |
96 | invalid_code[i] = 1; |
97 | } |
98 | else if (blocks[i]) |
99 | { |
100 | /*int j; |
101 | for (j=0; j<16; j++) blocks[i]->md5[j] = 0;*/ |
102 | blocks[i]->adler32 = 0; |
103 | } |
104 | } |
105 | } |
106 | } |
107 | |
108 | tlb_unmap(&tlb_e[idx]); |
109 | |
110 | tlb_e[idx].g = (EntryLo0 & EntryLo1 & 1); |
111 | tlb_e[idx].pfn_even = (EntryLo0 & 0x3FFFFFC0) >> 6; |
112 | tlb_e[idx].pfn_odd = (EntryLo1 & 0x3FFFFFC0) >> 6; |
113 | tlb_e[idx].c_even = (EntryLo0 & 0x38) >> 3; |
114 | tlb_e[idx].c_odd = (EntryLo1 & 0x38) >> 3; |
115 | tlb_e[idx].d_even = (EntryLo0 & 0x4) >> 2; |
116 | tlb_e[idx].d_odd = (EntryLo1 & 0x4) >> 2; |
117 | tlb_e[idx].v_even = (EntryLo0 & 0x2) >> 1; |
118 | tlb_e[idx].v_odd = (EntryLo1 & 0x2) >> 1; |
119 | tlb_e[idx].asid = (EntryHi & 0xFF); |
120 | tlb_e[idx].vpn2 = (EntryHi & 0xFFFFE000) >> 13; |
121 | //tlb_e[idx].r = (EntryHi & 0xC000000000000000LL) >> 62; |
122 | tlb_e[idx].mask = (PageMask & 0x1FFE000) >> 13; |
123 | |
124 | tlb_e[idx].start_even = tlb_e[idx].vpn2 << 13; |
125 | tlb_e[idx].end_even = tlb_e[idx].start_even+ |
126 | (tlb_e[idx].mask << 12) + 0xFFF; |
127 | tlb_e[idx].phys_even = tlb_e[idx].pfn_even << 12; |
128 | |
129 | |
130 | tlb_e[idx].start_odd = tlb_e[idx].end_even+1; |
131 | tlb_e[idx].end_odd = tlb_e[idx].start_odd+ |
132 | (tlb_e[idx].mask << 12) + 0xFFF; |
133 | tlb_e[idx].phys_odd = tlb_e[idx].pfn_odd << 12; |
134 | |
135 | tlb_map(&tlb_e[idx]); |
136 | |
137 | if (r4300emu != CORE_PURE_INTERPRETER) |
138 | { |
139 | unsigned int i; |
140 | if (tlb_e[idx].v_even) |
141 | { |
142 | for (i=tlb_e[idx].start_even>>12; i<=tlb_e[idx].end_even>>12; i++) |
143 | { |
144 | /*if (blocks[i] && (blocks[i]->md5[0] || blocks[i]->md5[1] || |
145 | blocks[i]->md5[2] || blocks[i]->md5[3])) |
146 | { |
147 | int j; |
148 | int equal = 1; |
149 | md5_state_t state; |
150 | md5_byte_t digest[16]; |
151 | md5_init(&state); |
152 | md5_append(&state, |
153 | (const md5_byte_t*)&rdram[(tlb_LUT_r[i]&0x7FF000)/4], |
154 | 0x1000); |
155 | md5_finish(&state, digest); |
156 | for (j=0; j<16; j++) |
157 | if (digest[j] != blocks[i]->md5[j]) |
158 | equal = 0; |
159 | if (equal) invalid_code[i] = 0; |
160 | }*/ |
161 | if(blocks[i] && blocks[i]->adler32) |
162 | { |
163 | if(blocks[i]->adler32 == adler32(0,(const unsigned char *)&rdram[(tlb_LUT_r[i]&0x7FF000)/4],0x1000)) |
164 | invalid_code[i] = 0; |
165 | } |
166 | } |
167 | } |
168 | |
169 | if (tlb_e[idx].v_odd) |
170 | { |
171 | for (i=tlb_e[idx].start_odd>>12; i<=tlb_e[idx].end_odd>>12; i++) |
172 | { |
173 | /*if (blocks[i] && (blocks[i]->md5[0] || blocks[i]->md5[1] || |
174 | blocks[i]->md5[2] || blocks[i]->md5[3])) |
175 | { |
176 | int j; |
177 | int equal = 1; |
178 | md5_state_t state; |
179 | md5_byte_t digest[16]; |
180 | md5_init(&state); |
181 | md5_append(&state, |
182 | (const md5_byte_t*)&rdram[(tlb_LUT_r[i]&0x7FF000)/4], |
183 | 0x1000); |
184 | md5_finish(&state, digest); |
185 | for (j=0; j<16; j++) |
186 | if (digest[j] != blocks[i]->md5[j]) |
187 | equal = 0; |
188 | if (equal) invalid_code[i] = 0; |
189 | }*/ |
190 | if(blocks[i] && blocks[i]->adler32) |
191 | { |
192 | if(blocks[i]->adler32 == adler32(0,(const unsigned char *)&rdram[(tlb_LUT_r[i]&0x7FF000)/4],0x1000)) |
193 | invalid_code[i] = 0; |
194 | } |
195 | } |
196 | } |
197 | } |
198 | } |
199 | |
200 | DECLARE_INSTRUCTION(TLBWI) |
201 | { |
202 | TLBWrite(Index&0x3F); |
203 | ADD_TO_PC(1); |
204 | } |
205 | |
206 | DECLARE_INSTRUCTION(TLBWR) |
207 | { |
208 | update_count(); |
209 | Random = (Count/2 % (32 - Wired)) + Wired; |
210 | TLBWrite(Random); |
211 | ADD_TO_PC(1); |
212 | } |
213 | |
214 | DECLARE_INSTRUCTION(TLBP) |
215 | { |
216 | int i; |
217 | Index |= 0x80000000; |
218 | for (i=0; i<32; i++) |
219 | { |
220 | if (((tlb_e[i].vpn2 & (~tlb_e[i].mask)) == |
221 | (((EntryHi & 0xFFFFE000) >> 13) & (~tlb_e[i].mask))) && |
222 | ((tlb_e[i].g) || |
223 | (tlb_e[i].asid == (EntryHi & 0xFF)))) |
224 | { |
225 | Index = i; |
226 | break; |
227 | } |
228 | } |
229 | ADD_TO_PC(1); |
230 | } |
231 | |
232 | DECLARE_INSTRUCTION(ERET) |
233 | { |
234 | update_count(); |
235 | if (Status & 0x4) |
236 | { |
237 | DebugMessage(M64MSG_ERROR, "error in ERET"); |
238 | stop=1; |
239 | } |
240 | else |
241 | { |
242 | Status &= ~0x2; |
243 | generic_jump_to(EPC); |
244 | } |
245 | llbit = 0; |
246 | check_interupt(); |
247 | last_addr = PCADDR; |
248 | if (next_interupt <= Count) gen_interupt(); |
249 | } |