|
|
1.1 root 1: /*
2: * MIPS emulation helpers for qemu.
3: *
4: * Copyright (c) 2004-2005 Jocelyn Mayer
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library 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 GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
17: * License along with this library; if not, write to the Free Software
18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19: */
20: #include "exec.h"
21:
22: #define MIPS_DEBUG_DISAS
23:
1.1.1.2 root 24: #define GETPC() (__builtin_return_address(0))
25:
1.1 root 26: /*****************************************************************************/
27: /* Exceptions processing helpers */
28: void cpu_loop_exit(void)
29: {
30: longjmp(env->jmp_env, 1);
31: }
32:
33: void do_raise_exception_err (uint32_t exception, int error_code)
34: {
35: #if 1
36: if (logfile && exception < 0x100)
37: fprintf(logfile, "%s: %d %d\n", __func__, exception, error_code);
38: #endif
39: env->exception_index = exception;
40: env->error_code = error_code;
41: T0 = 0;
42: cpu_loop_exit();
43: }
44:
45: void do_raise_exception (uint32_t exception)
46: {
47: do_raise_exception_err(exception, 0);
48: }
49:
1.1.1.2 root 50: void do_restore_state (void *pc_ptr)
51: {
52: TranslationBlock *tb;
53: unsigned long pc = (unsigned long) pc_ptr;
54:
55: tb = tb_find_pc (pc);
56: cpu_restore_state (tb, env, pc, NULL);
57: }
58:
59: void do_raise_exception_direct (uint32_t exception)
60: {
61: do_restore_state (GETPC ());
62: do_raise_exception_err (exception, 0);
63: }
64:
1.1 root 65: #define MEMSUFFIX _raw
66: #include "op_helper_mem.c"
67: #undef MEMSUFFIX
68: #if !defined(CONFIG_USER_ONLY)
69: #define MEMSUFFIX _user
70: #include "op_helper_mem.c"
71: #undef MEMSUFFIX
72: #define MEMSUFFIX _kernel
73: #include "op_helper_mem.c"
74: #undef MEMSUFFIX
75: #endif
76:
77: /* 64 bits arithmetic for 32 bits hosts */
78: #if (HOST_LONG_BITS == 32)
79: static inline uint64_t get_HILO (void)
80: {
81: return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
82: }
83:
84: static inline void set_HILO (uint64_t HILO)
85: {
86: env->LO = HILO & 0xFFFFFFFF;
87: env->HI = HILO >> 32;
88: }
89:
90: void do_mult (void)
91: {
1.1.1.2 root 92: set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1 root 93: }
94:
95: void do_multu (void)
96: {
97: set_HILO((uint64_t)T0 * (uint64_t)T1);
98: }
99:
100: void do_madd (void)
101: {
102: int64_t tmp;
103:
1.1.1.2 root 104: tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1 root 105: set_HILO((int64_t)get_HILO() + tmp);
106: }
107:
108: void do_maddu (void)
109: {
110: uint64_t tmp;
111:
112: tmp = ((uint64_t)T0 * (uint64_t)T1);
113: set_HILO(get_HILO() + tmp);
114: }
115:
116: void do_msub (void)
117: {
118: int64_t tmp;
119:
1.1.1.2 root 120: tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1 root 121: set_HILO((int64_t)get_HILO() - tmp);
122: }
123:
124: void do_msubu (void)
125: {
126: uint64_t tmp;
127:
128: tmp = ((uint64_t)T0 * (uint64_t)T1);
129: set_HILO(get_HILO() - tmp);
130: }
131: #endif
132:
1.1.1.2 root 133: #if defined(CONFIG_USER_ONLY)
134: void do_mfc0 (int reg, int sel)
135: {
136: cpu_abort(env, "mfc0 reg=%d sel=%d\n", reg, sel);
137: }
138: void do_mtc0 (int reg, int sel)
139: {
140: cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel);
141: }
142:
143: void do_tlbwi (void)
144: {
145: cpu_abort(env, "tlbwi\n");
146: }
147:
148: void do_tlbwr (void)
149: {
150: cpu_abort(env, "tlbwr\n");
151: }
152:
153: void do_tlbp (void)
154: {
155: cpu_abort(env, "tlbp\n");
156: }
157:
158: void do_tlbr (void)
159: {
160: cpu_abort(env, "tlbr\n");
161: }
162: #else
163:
1.1 root 164: /* CP0 helpers */
165: void do_mfc0 (int reg, int sel)
166: {
167: const unsigned char *rn;
168:
169: if (sel != 0 && reg != 16 && reg != 28) {
170: rn = "invalid";
171: goto print;
172: }
173: switch (reg) {
174: case 0:
175: T0 = env->CP0_index;
176: rn = "Index";
177: break;
178: case 1:
179: T0 = cpu_mips_get_random(env);
180: rn = "Random";
181: break;
182: case 2:
183: T0 = env->CP0_EntryLo0;
184: rn = "EntryLo0";
185: break;
186: case 3:
187: T0 = env->CP0_EntryLo1;
188: rn = "EntryLo1";
189: break;
190: case 4:
191: T0 = env->CP0_Context;
192: rn = "Context";
193: break;
194: case 5:
195: T0 = env->CP0_PageMask;
196: rn = "PageMask";
197: break;
198: case 6:
199: T0 = env->CP0_Wired;
200: rn = "Wired";
201: break;
202: case 8:
203: T0 = env->CP0_BadVAddr;
204: rn = "BadVaddr";
205: break;
206: case 9:
207: T0 = cpu_mips_get_count(env);
208: rn = "Count";
209: break;
210: case 10:
211: T0 = env->CP0_EntryHi;
212: rn = "EntryHi";
213: break;
214: case 11:
215: T0 = env->CP0_Compare;
216: rn = "Compare";
217: break;
218: case 12:
219: T0 = env->CP0_Status;
220: if (env->hflags & MIPS_HFLAG_UM)
221: T0 |= (1 << CP0St_UM);
222: rn = "Status";
223: break;
224: case 13:
225: T0 = env->CP0_Cause;
226: rn = "Cause";
227: break;
228: case 14:
229: T0 = env->CP0_EPC;
230: rn = "EPC";
231: break;
232: case 15:
233: T0 = env->CP0_PRid;
234: rn = "PRid";
235: break;
236: case 16:
237: switch (sel) {
238: case 0:
239: T0 = env->CP0_Config0;
240: rn = "Config";
241: break;
242: case 1:
243: T0 = env->CP0_Config1;
244: rn = "Config1";
245: break;
246: default:
247: rn = "Unknown config register";
248: break;
249: }
250: break;
251: case 17:
252: T0 = env->CP0_LLAddr >> 4;
253: rn = "LLAddr";
254: break;
255: case 18:
256: T0 = env->CP0_WatchLo;
257: rn = "WatchLo";
258: break;
259: case 19:
260: T0 = env->CP0_WatchHi;
261: rn = "WatchHi";
262: break;
263: case 23:
264: T0 = env->CP0_Debug;
265: if (env->hflags & MIPS_HFLAG_DM)
266: T0 |= 1 << CP0DB_DM;
267: rn = "Debug";
268: break;
269: case 24:
270: T0 = env->CP0_DEPC;
271: rn = "DEPC";
272: break;
273: case 28:
274: switch (sel) {
275: case 0:
276: T0 = env->CP0_TagLo;
277: rn = "TagLo";
278: break;
279: case 1:
280: T0 = env->CP0_DataLo;
281: rn = "DataLo";
282: break;
283: default:
284: rn = "unknown sel";
285: break;
286: }
287: break;
288: case 30:
289: T0 = env->CP0_ErrorEPC;
290: rn = "ErrorEPC";
291: break;
292: case 31:
293: T0 = env->CP0_DESAVE;
294: rn = "DESAVE";
295: break;
296: default:
297: rn = "unknown";
298: break;
299: }
300: print:
301: #if defined MIPS_DEBUG_DISAS
302: if (loglevel & CPU_LOG_TB_IN_ASM) {
303: fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n",
304: env->PC, rn, T0, reg, sel);
305: }
306: #endif
307: return;
308: }
309:
310: void do_mtc0 (int reg, int sel)
311: {
312: const unsigned char *rn;
313: uint32_t val, old, mask;
314:
315: if (sel != 0 && reg != 16 && reg != 28) {
316: val = -1;
317: old = -1;
318: rn = "invalid";
319: goto print;
320: }
321: switch (reg) {
322: case 0:
323: val = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F);
324: old = env->CP0_index;
325: env->CP0_index = val;
326: rn = "Index";
327: break;
328: case 2:
1.1.1.4 ! root 329: val = T0 & 0x3FFFFFFF;
1.1 root 330: old = env->CP0_EntryLo0;
331: env->CP0_EntryLo0 = val;
332: rn = "EntryLo0";
333: break;
334: case 3:
1.1.1.4 ! root 335: val = T0 & 0x3FFFFFFF;
1.1 root 336: old = env->CP0_EntryLo1;
337: env->CP0_EntryLo1 = val;
338: rn = "EntryLo1";
339: break;
340: case 4:
1.1.1.4 ! root 341: val = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0);
1.1 root 342: old = env->CP0_Context;
343: env->CP0_Context = val;
344: rn = "Context";
345: break;
346: case 5:
347: val = T0 & 0x01FFE000;
348: old = env->CP0_PageMask;
349: env->CP0_PageMask = val;
350: rn = "PageMask";
351: break;
352: case 6:
353: val = T0 & 0x0000000F;
354: old = env->CP0_Wired;
355: env->CP0_Wired = val;
356: rn = "Wired";
357: break;
358: case 9:
359: val = T0;
360: old = cpu_mips_get_count(env);
361: cpu_mips_store_count(env, val);
362: rn = "Count";
363: break;
364: case 10:
1.1.1.4 ! root 365: val = T0 & 0xFFFFE0FF;
1.1 root 366: old = env->CP0_EntryHi;
367: env->CP0_EntryHi = val;
1.1.1.2 root 368: /* If the ASID changes, flush qemu's TLB. */
369: if ((old & 0xFF) != (val & 0xFF))
370: tlb_flush (env, 1);
1.1 root 371: rn = "EntryHi";
372: break;
373: case 11:
374: val = T0;
375: old = env->CP0_Compare;
376: cpu_mips_store_compare(env, val);
377: rn = "Compare";
378: break;
379: case 12:
380: val = T0 & 0xFA78FF01;
381: if (T0 & (1 << CP0St_UM))
382: env->hflags |= MIPS_HFLAG_UM;
383: else
384: env->hflags &= ~MIPS_HFLAG_UM;
385: if (T0 & (1 << CP0St_ERL))
386: env->hflags |= MIPS_HFLAG_ERL;
387: else
388: env->hflags &= ~MIPS_HFLAG_ERL;
389: if (T0 & (1 << CP0St_EXL))
390: env->hflags |= MIPS_HFLAG_EXL;
391: else
392: env->hflags &= ~MIPS_HFLAG_EXL;
393: old = env->CP0_Status;
394: env->CP0_Status = val;
395: /* If we unmasked an asserted IRQ, raise it */
396: mask = 0x0000FF00;
397: if (loglevel & CPU_LOG_TB_IN_ASM) {
398: fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n",
399: old, val, env->CP0_Cause, old & mask, val & mask,
400: env->CP0_Cause & mask);
401: }
402: if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
403: !(env->hflags & MIPS_HFLAG_EXL) &&
404: !(env->hflags & MIPS_HFLAG_ERL) &&
1.1.1.4 ! root 405: !(env->hflags & MIPS_HFLAG_DM) &&
1.1 root 406: (env->CP0_Status & env->CP0_Cause & mask)) {
407: if (logfile)
408: fprintf(logfile, "Raise pending IRQs\n");
409: env->interrupt_request |= CPU_INTERRUPT_HARD;
1.1.1.4 ! root 410: } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
1.1 root 411: env->interrupt_request &= ~CPU_INTERRUPT_HARD;
412: }
413: rn = "Status";
414: break;
415: case 13:
416: val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300);
417: old = env->CP0_Cause;
418: env->CP0_Cause = val;
419: #if 0
420: {
421: int i;
422: /* Check if we ever asserted a software IRQ */
423: for (i = 0; i < 2; i++) {
424: mask = 0x100 << i;
425: if ((val & mask) & !(old & mask))
426: mips_set_irq(i);
427: }
428: }
429: #endif
430: rn = "Cause";
431: break;
432: case 14:
433: val = T0;
434: old = env->CP0_EPC;
435: env->CP0_EPC = val;
436: rn = "EPC";
437: break;
438: case 16:
439: switch (sel) {
440: case 0:
441: #if defined(MIPS_USES_R4K_TLB)
442: val = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001);
443: #else
444: val = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001);
445: #endif
446: old = env->CP0_Config0;
447: env->CP0_Config0 = val;
448: rn = "Config0";
449: break;
450: default:
451: val = -1;
452: old = -1;
453: rn = "bad config selector";
454: break;
455: }
456: break;
457: case 18:
458: val = T0;
459: old = env->CP0_WatchLo;
460: env->CP0_WatchLo = val;
461: rn = "WatchLo";
462: break;
463: case 19:
464: val = T0 & 0x40FF0FF8;
465: old = env->CP0_WatchHi;
466: env->CP0_WatchHi = val;
467: rn = "WatchHi";
468: break;
469: case 23:
470: val = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
471: if (T0 & (1 << CP0DB_DM))
472: env->hflags |= MIPS_HFLAG_DM;
473: else
474: env->hflags &= ~MIPS_HFLAG_DM;
475: old = env->CP0_Debug;
476: env->CP0_Debug = val;
477: rn = "Debug";
478: break;
479: case 24:
480: val = T0;
481: old = env->CP0_DEPC;
482: env->CP0_DEPC = val;
483: rn = "DEPC";
484: break;
485: case 28:
486: switch (sel) {
487: case 0:
488: val = T0 & 0xFFFFFCF6;
489: old = env->CP0_TagLo;
490: env->CP0_TagLo = val;
491: rn = "TagLo";
492: break;
493: default:
494: val = -1;
495: old = -1;
496: rn = "invalid sel";
497: break;
498: }
499: break;
500: case 30:
501: val = T0;
502: old = env->CP0_ErrorEPC;
503: env->CP0_ErrorEPC = val;
504: rn = "EPC";
505: break;
506: case 31:
507: val = T0;
508: old = env->CP0_DESAVE;
509: env->CP0_DESAVE = val;
510: rn = "DESAVE";
511: break;
512: default:
513: val = -1;
514: old = -1;
515: rn = "unknown";
516: break;
517: }
518: print:
519: #if defined MIPS_DEBUG_DISAS
520: if (loglevel & CPU_LOG_TB_IN_ASM) {
521: fprintf(logfile, "%08x mtc0 %s %08x => %08x (%d %d %08x)\n",
522: env->PC, rn, T0, val, reg, sel, old);
523: }
524: #endif
525: return;
526: }
527:
1.1.1.4 ! root 528: #ifdef MIPS_USES_FPU
! 529: #include "softfloat.h"
! 530:
! 531: void fpu_handle_exception(void)
! 532: {
! 533: #ifdef CONFIG_SOFTFLOAT
! 534: int flags = get_float_exception_flags(&env->fp_status);
! 535: unsigned int cpuflags = 0, enable, cause = 0;
! 536:
! 537: enable = GET_FP_ENABLE(env->fcr31);
! 538:
! 539: /* determine current flags */
! 540: if (flags & float_flag_invalid) {
! 541: cpuflags |= FP_INVALID;
! 542: cause |= FP_INVALID & enable;
! 543: }
! 544: if (flags & float_flag_divbyzero) {
! 545: cpuflags |= FP_DIV0;
! 546: cause |= FP_DIV0 & enable;
! 547: }
! 548: if (flags & float_flag_overflow) {
! 549: cpuflags |= FP_OVERFLOW;
! 550: cause |= FP_OVERFLOW & enable;
! 551: }
! 552: if (flags & float_flag_underflow) {
! 553: cpuflags |= FP_UNDERFLOW;
! 554: cause |= FP_UNDERFLOW & enable;
! 555: }
! 556: if (flags & float_flag_inexact) {
! 557: cpuflags |= FP_INEXACT;
! 558: cause |= FP_INEXACT & enable;
! 559: }
! 560: SET_FP_FLAGS(env->fcr31, cpuflags);
! 561: SET_FP_CAUSE(env->fcr31, cause);
! 562: #else
! 563: SET_FP_FLAGS(env->fcr31, 0);
! 564: SET_FP_CAUSE(env->fcr31, 0);
! 565: #endif
! 566: }
! 567: #endif /* MIPS_USES_FPU */
! 568:
1.1 root 569: /* TLB management */
570: #if defined(MIPS_USES_R4K_TLB)
1.1.1.3 root 571: static void invalidate_tlb (int idx)
1.1 root 572: {
573: tlb_t *tlb;
1.1.1.3 root 574: target_ulong addr;
1.1 root 575:
576: tlb = &env->tlb[idx];
1.1.1.3 root 577: if (tlb->V0) {
578: tb_invalidate_page_range(tlb->PFN[0], tlb->end - tlb->VPN);
1.1.1.2 root 579: addr = tlb->VPN;
580: while (addr < tlb->end) {
581: tlb_flush_page (env, addr);
582: addr += TARGET_PAGE_SIZE;
583: }
1.1 root 584: }
1.1.1.3 root 585: if (tlb->V1) {
586: tb_invalidate_page_range(tlb->PFN[1], tlb->end2 - tlb->end);
1.1.1.2 root 587: addr = tlb->end;
588: while (addr < tlb->end2) {
589: tlb_flush_page (env, addr);
590: addr += TARGET_PAGE_SIZE;
591: }
1.1 root 592: }
593: }
594:
1.1.1.3 root 595: static void fill_tlb (int idx)
1.1 root 596: {
597: tlb_t *tlb;
598: int size;
599:
600: /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
601: tlb = &env->tlb[idx];
602: tlb->VPN = env->CP0_EntryHi & 0xFFFFE000;
1.1.1.3 root 603: tlb->ASID = env->CP0_EntryHi & 0xFF;
1.1 root 604: size = env->CP0_PageMask >> 13;
605: size = 4 * (size + 1);
606: tlb->end = tlb->VPN + (1 << (8 + size));
1.1.1.2 root 607: tlb->end2 = tlb->end + (1 << (8 + size));
1.1 root 608: tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1.1.1.3 root 609: tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
610: tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
611: tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
1.1 root 612: tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
1.1.1.3 root 613: tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
614: tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
615: tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
1.1 root 616: tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
617: }
618:
619: void do_tlbwi (void)
620: {
621: /* Wildly undefined effects for CP0_index containing a too high value and
622: MIPS_TLB_NB not being a power of two. But so does real silicon. */
1.1.1.3 root 623: invalidate_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
624: fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
1.1 root 625: }
626:
627: void do_tlbwr (void)
628: {
629: int r = cpu_mips_get_random(env);
630:
1.1.1.3 root 631: invalidate_tlb(r);
632: fill_tlb(r);
1.1 root 633: }
634:
635: void do_tlbp (void)
636: {
637: tlb_t *tlb;
638: target_ulong tag;
639: uint8_t ASID;
640: int i;
641:
1.1.1.4 ! root 642: tag = env->CP0_EntryHi & 0xFFFFE000;
! 643: ASID = env->CP0_EntryHi & 0xFF;
! 644: for (i = 0; i < MIPS_TLB_NB; i++) {
1.1 root 645: tlb = &env->tlb[i];
646: /* Check ASID, virtual page number & size */
647: if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
648: /* TLB match */
649: env->CP0_index = i;
650: break;
651: }
652: }
653: if (i == MIPS_TLB_NB) {
654: env->CP0_index |= 0x80000000;
655: }
656: }
657:
658: void do_tlbr (void)
659: {
660: tlb_t *tlb;
1.1.1.3 root 661: uint8_t ASID;
1.1 root 662: int size;
663:
1.1.1.3 root 664: ASID = env->CP0_EntryHi & 0xFF;
1.1 root 665: tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)];
1.1.1.2 root 666:
667: /* If this will change the current ASID, flush qemu's TLB. */
1.1.1.3 root 668: if (ASID != tlb->ASID && tlb->G != 1)
1.1.1.2 root 669: tlb_flush (env, 1);
670:
1.1 root 671: env->CP0_EntryHi = tlb->VPN | tlb->ASID;
672: size = (tlb->end - tlb->VPN) >> 12;
673: env->CP0_PageMask = (size - 1) << 13;
1.1.1.3 root 674: env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2)
675: | (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
676: env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2)
677: | (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1.1 root 678: }
679: #endif
680:
1.1.1.2 root 681: #endif /* !CONFIG_USER_ONLY */
682:
1.1 root 683: void op_dump_ldst (const unsigned char *func)
684: {
685: if (loglevel)
686: fprintf(logfile, "%s => %08x %08x\n", __func__, T0, T1);
687: }
688:
689: void dump_sc (void)
690: {
691: if (loglevel) {
692: fprintf(logfile, "%s %08x at %08x (%08x)\n", __func__,
693: T1, T0, env->CP0_LLAddr);
694: }
695: }
696:
697: void debug_eret (void)
698: {
699: if (loglevel) {
700: fprintf(logfile, "ERET: pc %08x EPC %08x ErrorEPC %08x (%d)\n",
701: env->PC, env->CP0_EPC, env->CP0_ErrorEPC,
702: env->hflags & MIPS_HFLAG_ERL ? 1 : 0);
703: }
704: }
705:
706: void do_pmon (int function)
707: {
708: function /= 2;
709: switch (function) {
710: case 2: /* TODO: char inbyte(int waitflag); */
711: if (env->gpr[4] == 0)
712: env->gpr[2] = -1;
713: /* Fall through */
714: case 11: /* TODO: char inbyte (void); */
715: env->gpr[2] = -1;
716: break;
717: case 3:
718: case 12:
719: printf("%c", env->gpr[4] & 0xFF);
720: break;
721: case 17:
722: break;
723: case 158:
724: {
725: unsigned char *fmt = (void *)env->gpr[4];
726: printf("%s", fmt);
727: }
728: break;
729: }
730: }
731:
732: #if !defined(CONFIG_USER_ONLY)
733:
1.1.1.2 root 734: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
735:
1.1 root 736: #define MMUSUFFIX _mmu
1.1.1.2 root 737: #define ALIGNED_ONLY
1.1 root 738:
739: #define SHIFT 0
740: #include "softmmu_template.h"
741:
742: #define SHIFT 1
743: #include "softmmu_template.h"
744:
745: #define SHIFT 2
746: #include "softmmu_template.h"
747:
748: #define SHIFT 3
749: #include "softmmu_template.h"
750:
1.1.1.2 root 751: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
752: {
753: env->CP0_BadVAddr = addr;
754: do_restore_state (retaddr);
755: do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
756: }
757:
1.1 root 758: void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
759: {
760: TranslationBlock *tb;
761: CPUState *saved_env;
762: unsigned long pc;
763: int ret;
764:
765: /* XXX: hack to restore env in all cases, even if not called from
766: generated code */
767: saved_env = env;
768: env = cpu_single_env;
769: ret = cpu_mips_handle_mmu_fault(env, addr, is_write, is_user, 1);
770: if (ret) {
771: if (retaddr) {
772: /* now we have a real cpu fault */
773: pc = (unsigned long)retaddr;
774: tb = tb_find_pc(pc);
775: if (tb) {
776: /* the PC is inside the translated code. It means that we have
777: a virtual CPU fault */
778: cpu_restore_state(tb, env, pc, NULL);
779: }
780: }
781: do_raise_exception_err(env->exception_index, env->error_code);
782: }
783: env = saved_env;
784: }
785:
786: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.