Revision 8c0fdd85 target-mips/op_helper.c
b/target-mips/op_helper.c | ||
---|---|---|
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 | 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 | 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 |
Also available in: Unified diff