/[gxemul]/trunk/src/cpus/cpu_mips.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/cpu_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 51501 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

1 /*
2 * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_mips.c,v 1.84 2007/06/28 13:36:46 debug Exp $
29 *
30 * MIPS core CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <ctype.h>
38 #include <unistd.h>
39
40 #include "../../config.h"
41
42 #include "arcbios.h"
43 #include "cop0.h"
44 #include "cpu.h"
45 #include "cpu_mips.h"
46 #include "debugger.h"
47 #include "devices.h"
48 #include "emul.h"
49 #include "machine.h"
50 #include "memory.h"
51 #include "mips_cpu_types.h"
52 #include "opcodes_mips.h"
53 #include "settings.h"
54 #include "symbol.h"
55
56
57 static char *exception_names[] = EXCEPTION_NAMES;
58
59 static char *hi6_names[] = HI6_NAMES;
60 static char *regimm_names[] = REGIMM_NAMES;
61 static char *special_names[] = SPECIAL_NAMES;
62 static char *special_rot_names[] = SPECIAL_ROT_NAMES;
63 static char *special2_names[] = SPECIAL2_NAMES;
64 static char *mmi_names[] = MMI_NAMES;
65 static char *mmi0_names[] = MMI0_NAMES;
66 static char *mmi1_names[] = MMI1_NAMES;
67 static char *mmi2_names[] = MMI2_NAMES;
68 static char *mmi3_names[] = MMI3_NAMES;
69 static char *special3_names[] = SPECIAL3_NAMES;
70
71 static char *regnames[] = MIPS_REGISTER_NAMES;
72 static char *cop0_names[] = COP0_NAMES;
73
74
75 #define DYNTRANS_DUALMODE_32
76 #define DYNTRANS_DELAYSLOT
77 #include "tmp_mips_head.c"
78
79 void mips_pc_to_pointers(struct cpu *);
80 void mips32_pc_to_pointers(struct cpu *);
81
82
83 /*
84 * mips_cpu_new():
85 *
86 * Create a new MIPS cpu object.
87 *
88 * Returns 1 on success, 0 if there was no valid MIPS processor with
89 * a matching name.
90 */
91 int mips_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
92 int cpu_id, char *cpu_type_name)
93 {
94 int i, found, j, tags_size, n_cache_lines, size_per_cache_line;
95 struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
96 int64_t secondary_cache_size;
97 int x, linesize;
98
99 /* Scan the cpu_type_defs list for this cpu type: */
100 i = 0;
101 found = -1;
102 while (i >= 0 && cpu_type_defs[i].name != NULL) {
103 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
104 found = i;
105 break;
106 }
107 i++;
108 }
109
110 if (found == -1)
111 return 0;
112
113 cpu->memory_rw = mips_memory_rw;
114 cpu->cd.mips.cpu_type = cpu_type_defs[found];
115 cpu->name = cpu->cd.mips.cpu_type.name;
116 cpu->byte_order = EMUL_LITTLE_ENDIAN;
117 cpu->cd.mips.gpr[MIPS_GPR_SP] = INITIAL_STACK_POINTER;
118
119 if (cpu->cd.mips.cpu_type.isa_level <= 2 ||
120 cpu->cd.mips.cpu_type.isa_level == 32)
121 cpu->is_32bit = 1;
122
123 if (cpu->is_32bit) {
124 cpu->run_instr = mips32_run_instr;
125 cpu->update_translation_table = mips32_update_translation_table;
126 cpu->invalidate_translation_caches =
127 mips32_invalidate_translation_caches;
128 cpu->invalidate_code_translation =
129 mips32_invalidate_code_translation;
130 } else {
131 cpu->run_instr = mips_run_instr;
132 cpu->update_translation_table = mips_update_translation_table;
133 cpu->invalidate_translation_caches =
134 mips_invalidate_translation_caches;
135 cpu->invalidate_code_translation =
136 mips_invalidate_code_translation;
137 }
138
139 cpu->instruction_has_delayslot = mips_cpu_instruction_has_delayslot;
140
141 if (cpu_id == 0)
142 debug("%s", cpu->cd.mips.cpu_type.name);
143
144 /*
145 * CACHES:
146 *
147 * 1) Use DEFAULT_PCACHE_SIZE and DEFAULT_PCACHE_LINESIZE etc.
148 * 2) If there are specific values defined for this type of cpu,
149 * in its cpu_type substruct, then let's use those.
150 * 3) Values in the emul struct override both of the above.
151 *
152 * Once we've decided which values to use, they are stored in
153 * the emul struct so they can be used from src/machine.c etc.
154 */
155
156 x = DEFAULT_PCACHE_SIZE;
157 if (cpu->cd.mips.cpu_type.pdcache)
158 x = cpu->cd.mips.cpu_type.pdcache;
159 if (cpu->cd.mips.cache_pdcache == 0)
160 cpu->cd.mips.cache_pdcache = x;
161
162 x = DEFAULT_PCACHE_SIZE;
163 if (cpu->cd.mips.cpu_type.picache)
164 x = cpu->cd.mips.cpu_type.picache;
165 if (cpu->cd.mips.cache_picache == 0)
166 cpu->cd.mips.cache_picache = x;
167
168 if (cpu->cd.mips.cache_secondary == 0)
169 cpu->cd.mips.cache_secondary = cpu->cd.mips.cpu_type.scache;
170
171 linesize = DEFAULT_PCACHE_LINESIZE;
172 if (cpu->cd.mips.cpu_type.pdlinesize)
173 linesize = cpu->cd.mips.cpu_type.pdlinesize;
174 if (cpu->cd.mips.cache_pdcache_linesize == 0)
175 cpu->cd.mips.cache_pdcache_linesize = linesize;
176
177 linesize = DEFAULT_PCACHE_LINESIZE;
178 if (cpu->cd.mips.cpu_type.pilinesize)
179 linesize = cpu->cd.mips.cpu_type.pilinesize;
180 if (cpu->cd.mips.cache_picache_linesize == 0)
181 cpu->cd.mips.cache_picache_linesize = linesize;
182
183 linesize = 0;
184 if (cpu->cd.mips.cpu_type.slinesize)
185 linesize = cpu->cd.mips.cpu_type.slinesize;
186 if (cpu->cd.mips.cache_secondary_linesize == 0)
187 cpu->cd.mips.cache_secondary_linesize = linesize;
188
189
190 /*
191 * Primary Data and Instruction caches:
192 */
193 for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {
194 switch (i) {
195 case CACHE_DATA:
196 x = 1 << cpu->cd.mips.cache_pdcache;
197 linesize = 1 << cpu->cd.mips.cache_pdcache_linesize;
198 break;
199 case CACHE_INSTRUCTION:
200 x = 1 << cpu->cd.mips.cache_picache;
201 linesize = 1 << cpu->cd.mips.cache_picache_linesize;
202 break;
203 }
204
205 /* Primary cache size and linesize: */
206 cpu->cd.mips.cache_size[i] = x;
207 cpu->cd.mips.cache_linesize[i] = linesize;
208
209 switch (cpu->cd.mips.cpu_type.rev) {
210 case MIPS_R2000:
211 case MIPS_R3000:
212 size_per_cache_line = sizeof(struct r3000_cache_line);
213 break;
214 default:
215 size_per_cache_line = 32; /* TODO */
216 }
217
218 cpu->cd.mips.cache_mask[i] = cpu->cd.mips.cache_size[i] - 1;
219
220 CHECK_ALLOCATION(cpu->cd.mips.cache[i] =
221 malloc(cpu->cd.mips.cache_size[i]));
222
223 n_cache_lines = cpu->cd.mips.cache_size[i] /
224 cpu->cd.mips.cache_linesize[i];
225 tags_size = n_cache_lines * size_per_cache_line;
226
227 CHECK_ALLOCATION(cpu->cd.mips.cache_tags[i] =
228 malloc(tags_size));
229
230 /* Initialize the cache tags: */
231 switch (cpu->cd.mips.cpu_type.rev) {
232 case MIPS_R2000:
233 case MIPS_R3000:
234 for (j=0; j<n_cache_lines; j++) {
235 struct r3000_cache_line *rp;
236 rp = (struct r3000_cache_line *)
237 cpu->cd.mips.cache_tags[i];
238 rp[j].tag_paddr = 0;
239 rp[j].tag_valid = 0;
240 }
241 break;
242 default:
243 ;
244 }
245
246 /* Set cache_last_paddr to something "impossible": */
247 cpu->cd.mips.cache_last_paddr[i] = IMPOSSIBLE_PADDR;
248 }
249
250 /*
251 * Secondary cache:
252 */
253 secondary_cache_size = 0;
254 if (cpu->cd.mips.cache_secondary)
255 secondary_cache_size = 1 << cpu->cd.mips.cache_secondary;
256 /* TODO: linesize... */
257
258 if (cpu_id == 0) {
259 debug(" (I+D = %i+%i KB",
260 (int)(cpu->cd.mips.cache_size[CACHE_INSTRUCTION] / 1024),
261 (int)(cpu->cd.mips.cache_size[CACHE_DATA] / 1024));
262
263 if (secondary_cache_size != 0) {
264 debug(", L2 = ");
265 if (secondary_cache_size >= 1048576)
266 debug("%i MB", (int)
267 (secondary_cache_size / 1048576));
268 else
269 debug("%i KB", (int)
270 (secondary_cache_size / 1024));
271 }
272
273 debug(")");
274 }
275
276 /* Register the CPU's interrupts: */
277 for (i=2; i<8; i++) {
278 struct interrupt template;
279 char name[50];
280 snprintf(name, sizeof(name), "%s.%i", cpu->path, i);
281 memset(&template, 0, sizeof(template));
282 template.line = 1 << (STATUS_IM_SHIFT + i);
283 template.name = name;
284 template.extra = cpu;
285 template.interrupt_assert = mips_cpu_interrupt_assert;
286 template.interrupt_deassert = mips_cpu_interrupt_deassert;
287 interrupt_handler_register(&template);
288
289 if (i == 7)
290 INTERRUPT_CONNECT(name, cpu->cd.mips.irq_compare);
291 }
292
293 /* System coprocessor (0), and FPU (1): */
294 cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);
295 cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);
296
297 switch (cpu->cd.mips.cpu_type.mmu_model) {
298 case MMU3K:
299 cpu->translate_v2p = translate_v2p_mmu3k;
300 break;
301 case MMU8K:
302 cpu->translate_v2p = translate_v2p_mmu8k;
303 break;
304 case MMU10K:
305 cpu->translate_v2p = translate_v2p_mmu10k;
306 break;
307 default:
308 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
309 cpu->translate_v2p = translate_v2p_mmu4100;
310 else
311 cpu->translate_v2p = translate_v2p_generic;
312 }
313
314 if (cpu->machine->prom_emulation) {
315 /*
316 * Default behaviour of jumping to 0xbfc00000 should be
317 * a reboot, unless machine-specific initialization code
318 * overrides this.
319 *
320 * Note: Specifically big-endian machines should override
321 * this, since the default MIPS CPU is little-endian!
322 */
323 store_32bit_word(cpu, 0xffffffff9fc00000ULL, 0x00c0de0d);
324 }
325
326 /* Add all register names to the settings: */
327 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
328 CPU_SETTINGS_ADD_REGISTER64("hi", cpu->cd.mips.hi);
329 CPU_SETTINGS_ADD_REGISTER64("lo", cpu->cd.mips.lo);
330 for (i=0; i<N_MIPS_GPRS; i++)
331 CPU_SETTINGS_ADD_REGISTER64(regnames[i], cpu->cd.mips.gpr[i]);
332 /* TODO: Write via special handler function! */
333 for (i=0; i<N_MIPS_COPROC_REGS; i++)
334 CPU_SETTINGS_ADD_REGISTER64(cop0_names[i],
335 cpu->cd.mips.coproc[0]->reg[i]);
336
337 return 1;
338 }
339
340
341 /*
342 * mips_cpu_dumpinfo():
343 *
344 * Debug dump of MIPS-specific CPU data for specific CPU.
345 */
346 void mips_cpu_dumpinfo(struct cpu *cpu)
347 {
348 int iadd = DEBUG_INDENTATION;
349 struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type;
350
351 debug_indentation(iadd);
352
353 debug("\n%i-bit %s-endian (MIPS",
354 cpu->is_32bit? 32 : 64,
355 cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
356
357 switch (ct->isa_level) {
358 case 1: debug(" ISA I"); break;
359 case 2: debug(" ISA II"); break;
360 case 3: debug(" ISA III"); break;
361 case 4: debug(" ISA IV"); break;
362 case 5: debug(" ISA V"); break;
363 case 32:
364 case 64:debug("%i, revision %i", ct->isa_level, ct->isa_revision);
365 break;
366 default:debug(" ISA level %i", ct->isa_level);
367 }
368
369 debug("), ");
370 if (ct->nr_of_tlb_entries)
371 debug("%i TLB entries", ct->nr_of_tlb_entries);
372 else
373 debug("no TLB");
374 debug("\n");
375
376 if (ct->picache) {
377 debug("L1 I-cache: %i KB", (1 << ct->picache) / 1024);
378 if (ct->pilinesize)
379 debug(", %i bytes per line", 1 << ct->pilinesize);
380 if (ct->piways > 1)
381 debug(", %i-way", ct->piways);
382 else
383 debug(", direct-mapped");
384 debug("\n");
385 }
386
387 if (ct->pdcache) {
388 debug("L1 D-cache: %i KB", (1 << ct->pdcache) / 1024);
389 if (ct->pdlinesize)
390 debug(", %i bytes per line", 1 << ct->pdlinesize);
391 if (ct->pdways > 1)
392 debug(", %i-way", ct->pdways);
393 else
394 debug(", direct-mapped");
395 debug("\n");
396 }
397
398 if (ct->scache) {
399 int kb = (1 << ct->scache) / 1024;
400 debug("L2 cache: %i %s",
401 kb >= 1024? kb / 1024 : kb, kb >= 1024? "MB":"KB");
402 if (ct->slinesize)
403 debug(", %i bytes per line", 1 << ct->slinesize);
404 if (ct->sways > 1)
405 debug(", %i-way", ct->sways);
406 else
407 debug(", direct-mapped");
408 debug("\n");
409 }
410
411 debug_indentation(-iadd);
412 }
413
414
415 /*
416 * mips_cpu_list_available_types():
417 *
418 * Print a list of available MIPS CPU types.
419 */
420 void mips_cpu_list_available_types(void)
421 {
422 int i, j;
423 struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
424
425 i = 0;
426 while (cpu_type_defs[i].name != NULL) {
427 debug("%s", cpu_type_defs[i].name);
428 for (j=10 - strlen(cpu_type_defs[i].name); j>0; j--)
429 debug(" ");
430 i++;
431 if ((i % 6) == 0 || cpu_type_defs[i].name == NULL)
432 debug("\n");
433 }
434 }
435
436
437 /*
438 * mips_cpu_instruction_has_delayslot():
439 *
440 * Return 1 if an opcode is a branch, 0 otherwise.
441 */
442 int mips_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
443 {
444 uint32_t iword = *((uint32_t *)&ib[0]);
445
446 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
447 iword = LE32_TO_HOST(iword);
448 else
449 iword = BE32_TO_HOST(iword);
450
451 switch (iword >> 26) {
452 case HI6_SPECIAL:
453 switch (iword & 0x3f) {
454 case SPECIAL_JR:
455 case SPECIAL_JALR:
456 return 1;
457 }
458 break;
459 case HI6_REGIMM:
460 switch ((iword >> 16) & 0x1f) {
461 case REGIMM_BLTZ:
462 case REGIMM_BGEZ:
463 case REGIMM_BLTZL:
464 case REGIMM_BGEZL:
465 case REGIMM_BLTZAL:
466 case REGIMM_BLTZALL:
467 case REGIMM_BGEZAL:
468 case REGIMM_BGEZALL:
469 return 1;
470 }
471 break;
472 case HI6_BEQ:
473 case HI6_BEQL:
474 case HI6_BNE:
475 case HI6_BNEL:
476 case HI6_BGTZ:
477 case HI6_BGTZL:
478 case HI6_BLEZ:
479 case HI6_BLEZL:
480 case HI6_J:
481 case HI6_JAL:
482 return 1;
483 }
484
485 return 0;
486 }
487
488
489 /*
490 * mips_cpu_tlbdump():
491 *
492 * Called from the debugger to dump the TLB in a readable format.
493 * x is the cpu number to dump, or -1 to dump all CPUs.
494 *
495 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
496 * just dumped.
497 */
498 void mips_cpu_tlbdump(struct machine *m, int x, int rawflag)
499 {
500 int i, j;
501
502 /* Raw output: */
503 if (rawflag) {
504 for (i=0; i<m->ncpus; i++) {
505 struct mips_coproc *cop0 =
506 m->cpus[i]->cd.mips.coproc[0];
507
508 if (x >= 0 && i != x)
509 continue;
510
511 /* Print index, random, and wired: */
512 printf("cpu%i: (", i);
513
514 if (m->cpus[i]->is_32bit)
515 printf("index=0x%08x random=0x%08x",
516 (int) cop0->reg[COP0_INDEX],
517 (int) cop0->reg[COP0_RANDOM]);
518 else
519 printf("index=0x%016"PRIx64
520 " random=0x%016"PRIx64,
521 (uint64_t) cop0->reg[COP0_INDEX],
522 (uint64_t) cop0->reg[COP0_RANDOM]);
523
524 if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
525 printf(" wired=0x%"PRIx64,
526 (uint64_t) cop0->reg[COP0_WIRED]);
527
528 printf(")\n");
529
530 for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
531 nr_of_tlb_entries; j++) {
532 if (m->cpus[i]->cd.mips.cpu_type.mmu_model ==
533 MMU3K)
534 printf("%3i: hi=0x%08"PRIx32" lo=0x%08"
535 PRIx32"\n", j,
536 (uint32_t) cop0->tlbs[j].hi,
537 (uint32_t) cop0->tlbs[j].lo0);
538 else if (m->cpus[i]->is_32bit)
539 printf("%3i: hi=0x%08"PRIx32" mask=0x"
540 "%08"PRIx32" lo0=0x%08"PRIx32
541 " lo1=0x%08"PRIx32"\n", j,
542 (uint32_t) cop0->tlbs[j].hi,
543 (uint32_t) cop0->tlbs[j].mask,
544 (uint32_t) cop0->tlbs[j].lo0,
545 (uint32_t) cop0->tlbs[j].lo1);
546 else
547 printf("%3i: hi=0x%016"PRIx64" mask="
548 "0x%016"PRIx64" lo0=0x%016"PRIx64
549 " lo1=0x%016"PRIx64"\n", j,
550 (uint64_t) cop0->tlbs[j].hi,
551 (uint64_t) cop0->tlbs[j].mask,
552 (uint64_t) cop0->tlbs[j].lo0,
553 (uint64_t) cop0->tlbs[j].lo1);
554 }
555 }
556
557 return;
558 }
559
560 /* Nicely formatted output: */
561 for (i=0; i<m->ncpus; i++) {
562 int pageshift = 12;
563 struct mips_coproc *cop0 = m->cpus[i]->cd.mips.coproc[0];
564
565 if (x >= 0 && i != x)
566 continue;
567
568 if (m->cpus[i]->cd.mips.cpu_type.rev == MIPS_R4100)
569 pageshift = 10;
570
571 /* Print index, random, and wired: */
572 printf("cpu%i: (", i);
573 switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {
574 case 1:
575 case 2: printf("index=0x%x random=0x%x",
576 (int) ((cop0->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
577 >> R2K3K_INDEX_SHIFT),
578 (int) ((cop0->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
579 >> R2K3K_RANDOM_SHIFT));
580 break;
581 default:printf("index=0x%x random=0x%x",
582 (int) (cop0->reg[COP0_INDEX] & INDEX_MASK),
583 (int) (cop0->reg[COP0_RANDOM] & RANDOM_MASK));
584 printf(" wired=0x%"PRIx64,
585 (uint64_t) cop0->reg[COP0_WIRED]);
586 }
587
588 printf(")\n");
589
590 for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
591 nr_of_tlb_entries; j++) {
592 uint64_t hi = cop0->tlbs[j].hi;
593 uint64_t lo0 = cop0->tlbs[j].lo0;
594 uint64_t lo1 = cop0->tlbs[j].lo1;
595 uint64_t mask = cop0->tlbs[j].mask;
596 uint64_t psize;
597
598 mask |= (1 << (pageshift+1)) - 1;
599 /* here mask = e.g. 0x1fff for 4KB pages */
600
601 printf("%3i: ", j);
602
603 switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
604 case MMU3K:
605 if (!(lo0 & R2K3K_ENTRYLO_V)) {
606 printf("(invalid)\n");
607 continue;
608 }
609 printf("vaddr=0x%08x ",
610 (int) (hi&R2K3K_ENTRYHI_VPN_MASK));
611 if (lo0 & R2K3K_ENTRYLO_G)
612 printf("(global), ");
613 else
614 printf("(asid %02x),", (int) ((hi &
615 R2K3K_ENTRYHI_ASID_MASK)
616 >> R2K3K_ENTRYHI_ASID_SHIFT));
617 printf(" paddr=0x%08x ",
618 (int) (lo0&R2K3K_ENTRYLO_PFN_MASK));
619 if (lo0 & R2K3K_ENTRYLO_N)
620 printf("N");
621 if (lo0 & R2K3K_ENTRYLO_D)
622 printf("D");
623 printf("\n");
624 break;
625 default:switch (m->cpus[i]->cd.mips.cpu_type.mmu_model){
626 case MMU32:
627 printf("vaddr=0x%08"PRIx32" ",
628 (uint32_t) (hi & ~mask));
629 break;
630 default:/* R4x00, R1x000, MIPS64, etc. */
631 printf("vaddr=%016"PRIx64" ",
632 (uint64_t) (hi & ~mask));
633 }
634 if (hi & TLB_G)
635 printf("(global): ");
636 else
637 printf("(asid %02x):",
638 (int) (hi & ENTRYHI_ASID));
639
640 /* TODO: Coherency bits */
641
642 if (!(lo0 & ENTRYLO_V))
643 printf(" p0=(invalid) ");
644 else {
645 uint64_t paddr = lo0 & ENTRYLO_PFN_MASK;
646 paddr >>= ENTRYLO_PFN_SHIFT;
647 paddr <<= pageshift;
648 paddr &= ~(mask >> 1);
649 printf(" p0=0x%09"PRIx64" ",
650 (uint64_t) paddr);
651 }
652 printf(lo0 & ENTRYLO_D? "D" : " ");
653
654 if (!(lo1 & ENTRYLO_V))
655 printf(" p1=(invalid) ");
656 else {
657 uint64_t paddr = lo1 & ENTRYLO_PFN_MASK;
658 paddr >>= ENTRYLO_PFN_SHIFT;
659 paddr <<= pageshift;
660 paddr &= ~(mask >> 1);
661 printf(" p1=0x%09"PRIx64" ",
662 (uint64_t) paddr);
663 }
664 printf(lo1 & ENTRYLO_D? "D" : " ");
665
666 /* convert e.g. 0x1fff to 4096 */
667 psize = (mask + 1) >> 1;
668
669 if (psize >= 1024 && psize <= 256*1024)
670 printf(" (%iKB)", (int) (psize >> 10));
671 else if (psize >= 1024*1024 && psize <=
672 64*1024*1024)
673 printf(" (%iMB)", (int) (psize >> 20));
674 else
675 printf(" (?)");
676
677 printf("\n");
678 }
679 }
680 }
681 }
682
683
684 /*
685 * mips_cpu_disassemble_instr():
686 *
687 * Convert an instruction word into human readable format, for instruction
688 * tracing.
689 *
690 * If running is 1, cpu->pc should be the address of the instruction.
691 *
692 * If running is 0, things that depend on the runtime environment (eg.
693 * register contents) will not be shown, and addr will be used instead of
694 * cpu->pc for relative addresses.
695 *
696 * NOTE 2: coprocessor instructions are not decoded nicely yet (TODO)
697 */
698 int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,
699 int running, uint64_t dumpaddr)
700 {
701 int hi6, special6, regimm5, sub;
702 int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;
703 uint64_t addr, offset;
704 uint32_t instrword;
705 unsigned char instr[4];
706 char *symbol;
707
708 if (running)
709 dumpaddr = cpu->pc;
710
711 if ((dumpaddr & 3) != 0)
712 printf("WARNING: Unaligned address!\n");
713
714 symbol = get_symbol_name(&cpu->machine->symbol_context,
715 dumpaddr, &offset);
716 if (symbol != NULL && offset==0)
717 debug("<%s>\n", symbol);
718
719 if (cpu->machine->ncpus > 1 && running)
720 debug("cpu%i: ", cpu->cpu_id);
721
722 if (cpu->is_32bit)
723 debug("%08"PRIx32, (uint32_t)dumpaddr);
724 else
725 debug("%016"PRIx64, (uint64_t)dumpaddr);
726
727 *((uint32_t *)&instr[0]) = *((uint32_t *)&originstr[0]);
728
729 /*
730 * The rest of the code is written for little endian,
731 * so swap if necessary:
732 */
733 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
734 int tmp = instr[0]; instr[0] = instr[3];
735 instr[3] = tmp;
736 tmp = instr[1]; instr[1] = instr[2];
737 instr[2] = tmp;
738 }
739
740 debug(": %02x%02x%02x%02x",
741 instr[3], instr[2], instr[1], instr[0]);
742
743 if (running && cpu->delay_slot)
744 debug(" (d)");
745
746 debug("\t");
747
748 /*
749 * Decode the instruction:
750 */
751
752 hi6 = (instr[3] >> 2) & 0x3f;
753
754 switch (hi6) {
755 case HI6_SPECIAL:
756 special6 = instr[0] & 0x3f;
757 switch (special6) {
758 case SPECIAL_SLL:
759 case SPECIAL_SRL:
760 case SPECIAL_SRA:
761 case SPECIAL_DSLL:
762 case SPECIAL_DSRL:
763 case SPECIAL_DSRA:
764 case SPECIAL_DSLL32:
765 case SPECIAL_DSRL32:
766 case SPECIAL_DSRA32:
767 sub = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
768 rt = instr[2] & 31;
769 rd = (instr[1] >> 3) & 31;
770 sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
771
772 if (rd == 0 && special6 == SPECIAL_SLL) {
773 if (sa == 0)
774 debug("nop");
775 else if (sa == 1)
776 debug("ssnop");
777 else if (sa == 3)
778 debug("ehb");
779 else
780 debug("nop (weird, sa=%i)", sa);
781 break;
782 }
783
784 switch (sub) {
785 case 0x00:
786 debug("%s\t%s,", special_names[special6],
787 regnames[rd]);
788 debug("%s,%i", regnames[rt], sa);
789 break;
790 case 0x01:
791 debug("%s\t%s,",
792 special_rot_names[special6],
793 regnames[rd]);
794 debug("%s,%i", regnames[rt], sa);
795 break;
796 default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
797 sub);
798 }
799 break;
800 case SPECIAL_DSRLV:
801 case SPECIAL_DSRAV:
802 case SPECIAL_DSLLV:
803 case SPECIAL_SLLV:
804 case SPECIAL_SRAV:
805 case SPECIAL_SRLV:
806 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
807 rt = instr[2] & 31;
808 rd = (instr[1] >> 3) & 31;
809 sub = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
810
811 switch (sub) {
812 case 0x00:
813 debug("%s\t%s", special_names[special6],
814 regnames[rd]);
815 debug(",%s", regnames[rt]);
816 debug(",%s", regnames[rs]);
817 break;
818 case 0x01:
819 debug("%s\t%s", special_rot_names[special6],
820 regnames[rd]);
821 debug(",%s", regnames[rt]);
822 debug(",%s", regnames[rs]);
823 break;
824 default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
825 sub);
826 }
827 break;
828 case SPECIAL_JR:
829 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
830 symbol = get_symbol_name(&cpu->machine->symbol_context,
831 cpu->cd.mips.gpr[rs], &offset);
832 /* .hb = hazard barrier hint on MIPS32/64 rev 2 */
833 debug("jr%s\t%s",
834 (instr[1] & 0x04) ? ".hb" : "",
835 regnames[rs]);
836 if (running && symbol != NULL)
837 debug("\t<%s>", symbol);
838 break;
839 case SPECIAL_JALR:
840 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
841 rd = (instr[1] >> 3) & 31;
842 symbol = get_symbol_name(&cpu->machine->symbol_context,
843 cpu->cd.mips.gpr[rs], &offset);
844 /* .hb = hazard barrier hint on MIPS32/64 rev 2 */
845 debug("jalr%s\t%s",
846 (instr[1] & 0x04) ? ".hb" : "",
847 regnames[rd]);
848 debug(",%s", regnames[rs]);
849 if (running && symbol != NULL)
850 debug("\t<%s>", symbol);
851 break;
852 case SPECIAL_MFHI:
853 case SPECIAL_MFLO:
854 rd = (instr[1] >> 3) & 31;
855 debug("%s\t%s", special_names[special6], regnames[rd]);
856 break;
857 case SPECIAL_MTLO:
858 case SPECIAL_MTHI:
859 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
860 debug("%s\t%s", special_names[special6], regnames[rs]);
861 break;
862 case SPECIAL_ADD:
863 case SPECIAL_ADDU:
864 case SPECIAL_SUB:
865 case SPECIAL_SUBU:
866 case SPECIAL_AND:
867 case SPECIAL_OR:
868 case SPECIAL_XOR:
869 case SPECIAL_NOR:
870 case SPECIAL_SLT:
871 case SPECIAL_SLTU:
872 case SPECIAL_DADD:
873 case SPECIAL_DADDU:
874 case SPECIAL_DSUB:
875 case SPECIAL_DSUBU:
876 case SPECIAL_MOVZ:
877 case SPECIAL_MOVN:
878 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
879 rt = instr[2] & 31;
880 rd = (instr[1] >> 3) & 31;
881 if (cpu->is_32bit && (special6 == SPECIAL_ADDU ||
882 special6 == SPECIAL_SUBU) && rt == 0) {
883 /* Special case 1: addu/subu with
884 rt = the zero register ==> move */
885 debug("move\t%s", regnames[rd]);
886 debug(",%s", regnames[rs]);
887 } else if (special6 == SPECIAL_ADDU && cpu->is_32bit
888 && rs == 0) {
889 /* Special case 2: addu with
890 rs = the zero register ==> move */
891 debug("move\t%s", regnames[rd]);
892 debug(",%s", regnames[rt]);
893 } else {
894 debug("%s\t%s", special_names[special6],
895 regnames[rd]);
896 debug(",%s", regnames[rs]);
897 debug(",%s", regnames[rt]);
898 }
899 break;
900 case SPECIAL_MULT:
901 case SPECIAL_MULTU:
902 case SPECIAL_DMULT:
903 case SPECIAL_DMULTU:
904 case SPECIAL_DIV:
905 case SPECIAL_DIVU:
906 case SPECIAL_DDIV:
907 case SPECIAL_DDIVU:
908 case SPECIAL_TGE:
909 case SPECIAL_TGEU:
910 case SPECIAL_TLT:
911 case SPECIAL_TLTU:
912 case SPECIAL_TEQ:
913 case SPECIAL_TNE:
914 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
915 rt = instr[2] & 31;
916 rd = (instr[1] >> 3) & 31;
917 debug("%s\t", special_names[special6]);
918 if (rd != 0) {
919 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
920 if (special6 == SPECIAL_MULT ||
921 special6 == SPECIAL_MULTU)
922 debug("%s,", regnames[rd]);
923 else
924 debug("WEIRD_R5900_RD,");
925 } else {
926 debug("WEIRD_RD_NONZERO,");
927 }
928 }
929 debug("%s", regnames[rs]);
930 debug(",%s", regnames[rt]);
931 break;
932 case SPECIAL_SYNC:
933 imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
934 debug("sync\t0x%02x", imm);
935 break;
936 case SPECIAL_SYSCALL:
937 imm = (((instr[3] << 24) + (instr[2] << 16) +
938 (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
939 if (imm != 0)
940 debug("syscall\t0x%05x", imm);
941 else
942 debug("syscall");
943 break;
944 case SPECIAL_BREAK:
945 imm = (((instr[3] << 24) + (instr[2] << 16) +
946 (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
947 if (imm != 0)
948 debug("break\t0x%05x", imm);
949 else
950 debug("break");
951 break;
952 case SPECIAL_MFSA:
953 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
954 rd = (instr[1] >> 3) & 31;
955 debug("mfsa\t%s", regnames[rd]);
956 } else {
957 debug("unimplemented special 0x28");
958 }
959 break;
960 case SPECIAL_MTSA:
961 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
962 rs = ((instr[3] & 3) << 3) +
963 ((instr[2] >> 5) & 7);
964 debug("mtsa\t%s", regnames[rs]);
965 } else {
966 debug("unimplemented special 0x29");
967 }
968 break;
969 default:
970 debug("%s\t= UNIMPLEMENTED", special_names[special6]);
971 }
972 break;
973 case HI6_BEQ:
974 case HI6_BEQL:
975 case HI6_BNE:
976 case HI6_BNEL:
977 case HI6_BGTZ:
978 case HI6_BGTZL:
979 case HI6_BLEZ:
980 case HI6_BLEZL:
981 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
982 rt = instr[2] & 31;
983 imm = (instr[1] << 8) + instr[0];
984 if (imm >= 32768)
985 imm -= 65536;
986 addr = (dumpaddr + 4) + (imm << 2);
987
988 if (hi6 == HI6_BEQ && rt == MIPS_GPR_ZERO &&
989 rs == MIPS_GPR_ZERO)
990 debug("b\t");
991 else {
992 debug("%s\t", hi6_names[hi6]);
993 switch (hi6) {
994 case HI6_BEQ:
995 case HI6_BEQL:
996 case HI6_BNE:
997 case HI6_BNEL:
998 debug("%s,", regnames[rt]);
999 }
1000 debug("%s,", regnames[rs]);
1001 }
1002
1003 if (cpu->is_32bit)
1004 debug("0x%08"PRIx32, (uint32_t)addr);
1005 else
1006 debug("0x%016"PRIx64, (uint64_t)addr);
1007
1008 symbol = get_symbol_name(&cpu->machine->symbol_context,
1009 addr, &offset);
1010 if (symbol != NULL && offset != addr)
1011 debug("\t<%s>", symbol);
1012 break;
1013 case HI6_ADDI:
1014 case HI6_ADDIU:
1015 case HI6_DADDI:
1016 case HI6_DADDIU:
1017 case HI6_SLTI:
1018 case HI6_SLTIU:
1019 case HI6_ANDI:
1020 case HI6_ORI:
1021 case HI6_XORI:
1022 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1023 rt = instr[2] & 31;
1024 imm = (instr[1] << 8) + instr[0];
1025 if (imm >= 32768)
1026 imm -= 65536;
1027 debug("%s\t%s,", hi6_names[hi6], regnames[rt]);
1028 debug("%s,", regnames[rs]);
1029 if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)
1030 debug("0x%04x", imm & 0xffff);
1031 else
1032 debug("%i", imm);
1033 break;
1034 case HI6_LUI:
1035 rt = instr[2] & 31;
1036 imm = (instr[1] << 8) + instr[0];
1037 debug("lui\t%s,0x%x", regnames[rt], imm);
1038 break;
1039 case HI6_LB:
1040 case HI6_LBU:
1041 case HI6_LH:
1042 case HI6_LHU:
1043 case HI6_LW:
1044 case HI6_LWU:
1045 case HI6_LD:
1046 case HI6_LQ_MDMX:
1047 case HI6_LWC1:
1048 case HI6_LWC2:
1049 case HI6_LWC3:
1050 case HI6_LDC1:
1051 case HI6_LDC2:
1052 case HI6_LL:
1053 case HI6_LLD:
1054 case HI6_SB:
1055 case HI6_SH:
1056 case HI6_SW:
1057 case HI6_SD:
1058 case HI6_SQ_SPECIAL3:
1059 case HI6_SC:
1060 case HI6_SCD:
1061 case HI6_SWC1:
1062 case HI6_SWC2:
1063 case HI6_SWC3:
1064 case HI6_SDC1:
1065 case HI6_SDC2:
1066 case HI6_LWL:
1067 case HI6_LWR:
1068 case HI6_LDL:
1069 case HI6_LDR:
1070 case HI6_SWL:
1071 case HI6_SWR:
1072 case HI6_SDL:
1073 case HI6_SDR:
1074 if (hi6 == HI6_LQ_MDMX &&
1075 cpu->cd.mips.cpu_type.rev != MIPS_R5900) {
1076 debug("mdmx\t(UNIMPLEMENTED)");
1077 break;
1078 }
1079 if (hi6 == HI6_SQ_SPECIAL3 &&
1080 cpu->cd.mips.cpu_type.rev != MIPS_R5900) {
1081 int msbd, lsb, sub10;
1082 special6 = instr[0] & 0x3f;
1083 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1084 rt = instr[2] & 31;
1085 rd = msbd = (instr[1] >> 3) & 31;
1086 lsb = ((instr[1] & 7) << 2) | (instr[0] >> 6);
1087 sub10 = (rs << 5) | lsb;
1088
1089 switch (special6) {
1090
1091 case SPECIAL3_EXT:
1092 case SPECIAL3_DEXT:
1093 case SPECIAL3_DEXTM:
1094 case SPECIAL3_DEXTU:
1095 debug("%s", special3_names[special6]);
1096 if (special6 == SPECIAL3_DEXTM)
1097 msbd += 32;
1098 if (special6 == SPECIAL3_DEXTU)
1099 lsb += 32;
1100 debug("\t%s", regnames[rt]);
1101 debug(",%s", regnames[rs]);
1102 debug(",%i,%i", lsb, msbd + 1);
1103 break;
1104
1105 case SPECIAL3_INS:
1106 case SPECIAL3_DINS:
1107 case SPECIAL3_DINSM:
1108 case SPECIAL3_DINSU:
1109 debug("%s", special3_names[special6]);
1110 if (special6 == SPECIAL3_DINSM)
1111 msbd += 32;
1112 if (special6 == SPECIAL3_DINSU) {
1113 lsb += 32;
1114 msbd += 32;
1115 }
1116 msbd -= lsb;
1117 debug("\t%s", regnames[rt]);
1118 debug(",%s", regnames[rs]);
1119 debug(",%i,%i", lsb, msbd + 1);
1120 break;
1121
1122 case SPECIAL3_BSHFL:
1123 switch (sub10) {
1124 case BSHFL_WSBH:
1125 case BSHFL_SEB:
1126 case BSHFL_SEH:
1127 switch (sub10) {
1128 case BSHFL_WSBH: debug("wsbh"); break;
1129 case BSHFL_SEB: debug("seb"); break;
1130 case BSHFL_SEH: debug("seh"); break;
1131 }
1132 debug("\t%s", regnames[rd]);
1133 debug(",%s", regnames[rt]);
1134 break;
1135 default:debug("%s", special3_names[special6]);
1136 debug("\t(UNIMPLEMENTED)");
1137 }
1138 break;
1139
1140 case SPECIAL3_DBSHFL:
1141 switch (sub10) {
1142 case BSHFL_DSBH:
1143 case BSHFL_DSHD:
1144 switch (sub10) {
1145 case BSHFL_DSBH: debug("dsbh"); break;
1146 case BSHFL_DSHD: debug("dshd"); break;
1147 }
1148 debug("\t%s", regnames[rd]);
1149 debug(",%s", regnames[rt]);
1150 break;
1151 default:debug("%s", special3_names[special6]);
1152 debug("\t(UNIMPLEMENTED)");
1153 }
1154 break;
1155
1156 case SPECIAL3_RDHWR:
1157 debug("%s", special3_names[special6]);
1158 debug("\t%s", regnames[rt]);
1159 debug(",hwr%i", rd);
1160 break;
1161
1162 default:debug("%s", special3_names[special6]);
1163 debug("\t(UNIMPLEMENTED)");
1164 }
1165 break;
1166 }
1167
1168 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1169 rt = instr[2] & 31;
1170 imm = (instr[1] << 8) + instr[0];
1171 if (imm >= 32768)
1172 imm -= 65536;
1173 symbol = get_symbol_name(&cpu->machine->symbol_context,
1174 cpu->cd.mips.gpr[rs] + imm, &offset);
1175
1176 /* LWC3 is PREF in the newer ISA levels: */
1177 /* TODO: Which ISAs? IV? V? 32? 64? */
1178 if (cpu->cd.mips.cpu_type.isa_level >= 4 && hi6 == HI6_LWC3) {
1179 debug("pref\t0x%x,%i(%s)",
1180 rt, imm, regnames[rs]);
1181
1182 if (running) {
1183 debug("\t[0x%016"PRIx64" = %s]",
1184 (uint64_t)(cpu->cd.mips.gpr[rs] + imm));
1185 if (symbol != NULL)
1186 debug(" = %s", symbol);
1187 debug("]");
1188 }
1189 goto disasm_ret;
1190 }
1191
1192 debug("%s\t", hi6_names[hi6]);
1193
1194 if (hi6 == HI6_SWC1 || hi6 == HI6_SWC2 || hi6 == HI6_SWC3 ||
1195 hi6 == HI6_SDC1 || hi6 == HI6_SDC2 ||
1196 hi6 == HI6_LWC1 || hi6 == HI6_LWC2 || hi6 == HI6_LWC3 ||
1197 hi6 == HI6_LDC1 || hi6 == HI6_LDC2)
1198 debug("r%i", rt);
1199 else
1200 debug("%s", regnames[rt]);
1201
1202 debug(",%i(%s)", imm, regnames[rs]);
1203
1204 if (running) {
1205 debug("\t[");
1206
1207 if (cpu->is_32bit)
1208 debug("0x%08"PRIx32,
1209 (uint32_t) (cpu->cd.mips.gpr[rs] + imm));
1210 else
1211 debug("0x%016"PRIx64,
1212 (uint64_t) (cpu->cd.mips.gpr[rs] + imm));
1213
1214 if (symbol != NULL)
1215 debug(" = %s", symbol);
1216
1217 /* TODO: In some cases, it is possible to peek into
1218 memory, and display that data here, like for the
1219 other emulation modes. */
1220
1221 debug("]");
1222 }
1223 break;
1224
1225 case HI6_J:
1226 case HI6_JAL:
1227 imm = (((instr[3] & 3) << 24) + (instr[2] << 16) +
1228 (instr[1] << 8) + instr[0]) << 2;
1229 addr = (dumpaddr + 4) & ~((1 << 28) - 1);
1230 addr |= imm;
1231 symbol = get_symbol_name(&cpu->machine->symbol_context,
1232 addr, &offset);
1233 debug("%s\t0x", hi6_names[hi6]);
1234 if (cpu->is_32bit)
1235 debug("%08"PRIx32, (uint32_t) addr);
1236 else
1237 debug("%016"PRIx64, (uint64_t) addr);
1238 if (symbol != NULL)
1239 debug("\t<%s>", symbol);
1240 break;
1241
1242 case HI6_COP0:
1243 case HI6_COP1:
1244 case HI6_COP2:
1245 case HI6_COP3:
1246 imm = (instr[3] << 24) + (instr[2] << 16) +
1247 (instr[1] << 8) + instr[0];
1248 imm &= ((1 << 26) - 1);
1249
1250 /* Call coproc_function(), but ONLY disassembly, no exec: */
1251 coproc_function(cpu, cpu->cd.mips.coproc[hi6 - HI6_COP0],
1252 hi6 - HI6_COP0, imm, 1, running);
1253 return sizeof(instrword);
1254
1255 case HI6_CACHE:
1256 rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
1257 copz = instr[2] & 31;
1258 imm = (instr[1] << 8) + instr[0];
1259 cache_op = copz >> 2;
1260 which_cache = copz & 3;
1261 showtag = 0;
1262 debug("cache\t0x%02x,0x%04x(%s)", copz, imm, regnames[rt]);
1263 if (which_cache==0) debug(" [ primary I-cache");
1264 if (which_cache==1) debug(" [ primary D-cache");
1265 if (which_cache==2) debug(" [ secondary I-cache");
1266 if (which_cache==3) debug(" [ secondary D-cache");
1267 debug(", ");
1268 if (cache_op==0) debug("index invalidate");
1269 if (cache_op==1) debug("index load tag");
1270 if (cache_op==2) debug("index store tag"), showtag=1;
1271 if (cache_op==3) debug("create dirty exclusive");
1272 if (cache_op==4) debug("hit invalidate");
1273 if (cache_op==5) debug("fill OR hit writeback invalidate");
1274 if (cache_op==6) debug("hit writeback");
1275 if (cache_op==7) debug("hit set virtual");
1276 if (running)
1277 debug(", addr 0x%016"PRIx64,
1278 (uint64_t)(cpu->cd.mips.gpr[rt] + imm));
1279 if (showtag)
1280 debug(", taghi=%08lx lo=%08lx",
1281 (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_HI],
1282 (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_LO]);
1283 debug(" ]");
1284 break;
1285
1286 case HI6_SPECIAL2:
1287 special6 = instr[0] & 0x3f;
1288 instrword = (instr[3] << 24) + (instr[2] << 16) +
1289 (instr[1] << 8) + instr[0];
1290 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1291 rt = instr[2] & 31;
1292 rd = (instr[1] >> 3) & 31;
1293
1294 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
1295 int c790mmifunc = (instrword >> 6) & 0x1f;
1296 if (special6 != MMI_MMI0 && special6 != MMI_MMI1 &&
1297 special6 != MMI_MMI2 && special6 != MMI_MMI3)
1298 debug("%s\t", mmi_names[special6]);
1299
1300 switch (special6) {
1301
1302 case MMI_MADD:
1303 case MMI_MADDU:
1304 if (rd != MIPS_GPR_ZERO) {
1305 debug("%s,", regnames[rd]);
1306 }
1307 debug("%s,%s", regnames[rs], regnames[rt]);
1308 break;
1309
1310 case MMI_MMI0:
1311 debug("%s\t", mmi0_names[c790mmifunc]);
1312 switch (c790mmifunc) {
1313
1314 case MMI0_PEXTLB:
1315 case MMI0_PEXTLH:
1316 case MMI0_PEXTLW:
1317 case MMI0_PMAXH:
1318 case MMI0_PMAXW:
1319 case MMI0_PPACB:
1320 case MMI0_PPACH:
1321 case MMI0_PPACW:
1322 debug("%s,%s,%s", regnames[rd],
1323 regnames[rs], regnames[rt]);
1324 break;
1325
1326 default:debug("(UNIMPLEMENTED)");
1327 }
1328 break;
1329
1330 case MMI_MMI1:
1331 debug("%s\t", mmi1_names[c790mmifunc]);
1332 switch (c790mmifunc) {
1333
1334 case MMI1_PEXTUB:
1335 case MMI1_PEXTUH:
1336 case MMI1_PEXTUW:
1337 case MMI1_PMINH:
1338 case MMI1_PMINW:
1339 debug("%s,%s,%s", regnames[rd],
1340 regnames[rs], regnames[rt]);
1341 break;
1342
1343 default:debug("(UNIMPLEMENTED)");
1344 }
1345 break;
1346
1347 case MMI_MMI2:
1348 debug("%s\t", mmi2_names[c790mmifunc]);
1349 switch (c790mmifunc) {
1350
1351 case MMI2_PMFHI:
1352 case MMI2_PMFLO:
1353 debug("%s", regnames[rd]);
1354 break;
1355
1356 case MMI2_PHMADH:
1357 case MMI2_PHMSBH:
1358 case MMI2_PINTH:
1359 case MMI2_PMADDH:
1360 case MMI2_PMADDW:
1361 case MMI2_PMSUBH:
1362 case MMI2_PMSUBW:
1363 case MMI2_PMULTH:
1364 case MMI2_PMULTW:
1365 case MMI2_PSLLVW:
1366 debug("%s,%s,%s", regnames[rd],
1367 regnames[rs], regnames[rt]);
1368 break;
1369
1370 default:debug("(UNIMPLEMENTED)");
1371 }
1372 break;
1373
1374 case MMI_MMI3:
1375 debug("%s\t", mmi3_names[c790mmifunc]);
1376 switch (c790mmifunc) {
1377
1378 case MMI3_PMTHI:
1379 case MMI3_PMTLO:
1380 debug("%s", regnames[rs]);
1381 break;
1382
1383 case MMI3_PINTEH:
1384 case MMI3_PMADDUW:
1385 case MMI3_PMULTUW:
1386 case MMI3_PNOR:
1387 case MMI3_POR:
1388 case MMI3_PSRAVW:
1389 debug("%s,%s,%s", regnames[rd],
1390 regnames[rs], regnames[rt]);
1391 break;
1392
1393 default:debug("(UNIMPLEMENTED)");
1394 }
1395 break;
1396
1397 default:debug("(UNIMPLEMENTED)");
1398 }
1399 break;
1400 }
1401
1402 /* SPECIAL2: */
1403 debug("%s\t", special2_names[special6]);
1404
1405 switch (special6) {
1406
1407 case SPECIAL2_MADD:
1408 case SPECIAL2_MADDU:
1409 case SPECIAL2_MSUB:
1410 case SPECIAL2_MSUBU:
1411 if (rd != MIPS_GPR_ZERO) {
1412 debug("WEIRD_NONZERO_RD(%s),",
1413 regnames[rd]);
1414 }
1415 debug("%s,%s", regnames[rs], regnames[rt]);
1416 break;
1417
1418 case SPECIAL2_MUL:
1419 /* Apparently used both on R5900 and MIPS32: */
1420 debug("%s,%s,%s", regnames[rd],
1421 regnames[rs], regnames[rt]);
1422 break;
1423
1424 case SPECIAL2_CLZ:
1425 case SPECIAL2_CLO:
1426 case SPECIAL2_DCLZ:
1427 case SPECIAL2_DCLO:
1428 debug("%s,%s", regnames[rd], regnames[rs]);
1429 break;
1430
1431 default:
1432 debug("(UNIMPLEMENTED)");
1433 }
1434 break;
1435
1436 case HI6_REGIMM:
1437 regimm5 = instr[2] & 0x1f;
1438 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1439 imm = (instr[1] << 8) + instr[0];
1440 if (imm >= 32768)
1441 imm -= 65536;
1442
1443 switch (regimm5) {
1444
1445 case REGIMM_BLTZ:
1446 case REGIMM_BGEZ:
1447 case REGIMM_BLTZL:
1448 case REGIMM_BGEZL:
1449 case REGIMM_BLTZAL:
1450 case REGIMM_BLTZALL:
1451 case REGIMM_BGEZAL:
1452 case REGIMM_BGEZALL:
1453 debug("%s\t%s,", regimm_names[regimm5], regnames[rs]);
1454
1455 addr = (dumpaddr + 4) + (imm << 2);
1456
1457 if (cpu->is_32bit)
1458 debug("0x%08"PRIx32, (uint32_t) addr);
1459 else
1460 debug("0x%016"PRIx64, (uint64_t) addr);
1461 break;
1462
1463 case REGIMM_SYNCI:
1464 debug("%s\t%i(%s)", regimm_names[regimm5],
1465 imm, regnames[rs]);
1466 break;
1467
1468 default:
1469 debug("unimplemented regimm5 = 0x%02x", regimm5);
1470 }
1471 break;
1472 default:
1473 debug("unimplemented hi6 = 0x%02x", hi6);
1474 }
1475
1476 disasm_ret:
1477 debug("\n");
1478 return sizeof(instrword);
1479 }
1480
1481
1482 /*
1483 * mips_cpu_register_dump():
1484 *
1485 * Dump cpu registers in a relatively readable format.
1486 *
1487 * gprs: set to non-zero to dump GPRs and hi/lo/pc
1488 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
1489 */
1490 void mips_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
1491 {
1492 int coprocnr, i, bits32;
1493 uint64_t offset;
1494 char *symbol;
1495 int bits128 = cpu->cd.mips.cpu_type.rev == MIPS_R5900;
1496
1497 bits32 = cpu->is_32bit;
1498
1499 if (gprs) {
1500 /* Special registers (pc, hi/lo) first: */
1501 symbol = get_symbol_name(&cpu->machine->symbol_context,
1502 cpu->pc, &offset);
1503
1504 if (bits32)
1505 debug("cpu%i: pc = %08"PRIx32,
1506 cpu->cpu_id, (uint32_t) cpu->pc);
1507 else if (bits128)
1508 debug("cpu%i: pc=%016"PRIx64,
1509 cpu->cpu_id, (uint64_t) cpu->pc);
1510 else
1511 debug("cpu%i: pc = 0x%016"PRIx64,
1512 cpu->cpu_id, (uint64_t) cpu->pc);
1513
1514 debug(" <%s>\n", symbol != NULL? symbol :
1515 " no symbol ");
1516
1517 if (bits32)
1518 debug("cpu%i: hi = %08"PRIx32" lo = %08"PRIx32"\n",
1519 cpu->cpu_id, (uint32_t) cpu->cd.mips.hi,
1520 (uint32_t) cpu->cd.mips.lo);
1521 else if (bits128) {
1522 debug("cpu%i: hi=%016"PRIx64"%016"PRIx64" lo="
1523 "%016"PRIx64"%016"PRIx64"\n", cpu->cpu_id,
1524 cpu->cd.mips.hi1, cpu->cd.mips.hi,
1525 cpu->cd.mips.lo1, cpu->cd.mips.lo);
1526 } else {
1527 debug("cpu%i: hi = 0x%016"PRIx64" lo = 0x%016"
1528 PRIx64"\n", cpu->cpu_id,
1529 (uint64_t) cpu->cd.mips.hi,
1530 (uint64_t) cpu->cd.mips.lo);
1531 }
1532
1533 /* General registers: */
1534 if (bits128) {
1535 /* 128-bit: */
1536 for (i=0; i<32; i++) {
1537 int r = (i >> 1) + ((i & 1) << 4);
1538 if ((i & 1) == 0)
1539 debug("cpu%i:", cpu->cpu_id);
1540 if (r == MIPS_GPR_ZERO)
1541 debug(" "
1542 " ");
1543 else
1544 debug(" %3s=%016"PRIx64"%016"PRIx64,
1545 regnames[r], (uint64_t)
1546 cpu->cd.mips.gpr_quadhi[r],
1547 (uint64_t)cpu->cd.mips.gpr[r]);
1548 if ((i & 1) == 1)
1549 debug("\n");
1550 }
1551 } else if (bits32) {
1552 /* 32-bit: */
1553 for (i=0; i<32; i++) {
1554 if ((i & 3) == 0)
1555 debug("cpu%i:", cpu->cpu_id);
1556 if (i == MIPS_GPR_ZERO)
1557 debug(" ");
1558 else
1559 debug(" %3s = %08"PRIx32, regnames[i],
1560 (uint32_t)cpu->cd.mips.gpr[i]);
1561 if ((i & 3) == 3)
1562 debug("\n");
1563 }
1564 } else {
1565 /* 64-bit: */
1566 for (i=0; i<32; i++) {
1567 int r = (i >> 1) + ((i & 1) << 4);
1568 if ((i & 1) == 0)
1569 debug("cpu%i:", cpu->cpu_id);
1570 if (r == MIPS_GPR_ZERO)
1571 debug(" ");
1572 else
1573 debug(" %3s = 0x%016"PRIx64,
1574 regnames[r],
1575 (uint64_t)cpu->cd.mips.gpr[r]);
1576 if ((i & 1) == 1)
1577 debug("\n");
1578 }
1579 }
1580 }
1581
1582 for (coprocnr=0; coprocnr<4; coprocnr++) {
1583 int nm1 = 1;
1584
1585 if (bits32)
1586 nm1 = 3;
1587
1588 if (!(coprocs & (1<<coprocnr)))
1589 continue;
1590 if (cpu->cd.mips.coproc[coprocnr] == NULL) {
1591 debug("cpu%i: no coprocessor %i\n",
1592 cpu->cpu_id, coprocnr);
1593 continue;
1594 }
1595
1596 /* Coprocessor registers: */
1597 for (i=0; i<32; i++) {
1598 /* 32-bit: */
1599 if ((i & nm1) == 0)
1600 debug("cpu%i:", cpu->cpu_id);
1601
1602 if (coprocnr == 0)
1603 debug(" %8s", cop0_names[i]);
1604 else
1605 debug(" c%i,%02i", coprocnr, i);
1606
1607 if (bits32)
1608 debug("=%08x", (int)cpu->cd.mips.
1609 coproc[coprocnr]->reg[i]);
1610 else {
1611 if (coprocnr == 0 && (i == COP0_COUNT
1612 || i == COP0_COMPARE || i == COP0_INDEX
1613 || i == COP0_RANDOM || i == COP0_WIRED))
1614 debug(" = 0x%08x",
1615 (int) cpu->cd.mips.coproc[
1616 coprocnr]->reg[i]);
1617 else
1618 debug(" = 0x%016"PRIx64, (uint64_t)
1619 cpu->cd.mips.coproc[
1620 coprocnr]->reg[i]);
1621 }
1622
1623 if ((i & nm1) == nm1)
1624 debug("\n");
1625
1626 /* Skip the last 16 cop0 registers on R3000 etc. */
1627 if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level < 3
1628 && i == 15)
1629 i = 31;
1630 }
1631
1632 if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level >= 32) {
1633 debug("cpu%i: ", cpu->cpu_id);
1634 debug("config_select1 = 0x");
1635 if (cpu->is_32bit)
1636 debug("%08"PRIx32,
1637 (uint32_t)cpu->cd.mips.cop0_config_select1);
1638 else
1639 debug("%016"PRIx64,
1640 (uint64_t)cpu->cd.mips.cop0_config_select1);
1641 debug("\n");
1642 }
1643
1644 /* Floating point control registers: */
1645 if (coprocnr == 1) {
1646 for (i=0; i<32; i++)
1647 switch (i) {
1648 case MIPS_FPU_FCIR:
1649 printf("cpu%i: fcr0 (fcir) = 0x%08x\n",
1650 cpu->cpu_id, (int)cpu->cd.mips.
1651 coproc[coprocnr]->fcr[i]);
1652 break;
1653 case MIPS_FPU_FCCR:
1654 printf("cpu%i: fcr25 (fccr) = 0x%08x\n",
1655 cpu->cpu_id, (int)cpu->cd.mips.
1656 coproc[coprocnr]->fcr[i]);
1657 break;
1658 case MIPS_FPU_FCSR:
1659 printf("cpu%i: fcr31 (fcsr) = 0x%08x\n",
1660 cpu->cpu_id, (int)cpu->cd.mips.
1661 coproc[coprocnr]->fcr[i]);
1662 break;
1663 }
1664 }
1665 }
1666
1667 if (cpu->cd.mips.rmw) {
1668 printf("cpu%i: Read-Modify-Write in progress, address "
1669 "0x%016"PRIx64"\n", cpu->cpu_id, cpu->cd.mips.rmw_addr);
1670 }
1671 }
1672
1673
1674 /*
1675 * mips_cpu_interrupt_assert(), mips_cpu_interrupt_deassert():
1676 *
1677 * Assert or deassert a MIPS CPU interrupt by masking in or out bits
1678 * in the CAUSE register of coprocessor 0.
1679 */
1680 void mips_cpu_interrupt_assert(struct interrupt *interrupt)
1681 {
1682 struct cpu *cpu = interrupt->extra;
1683 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |= interrupt->line;
1684 }
1685 void mips_cpu_interrupt_deassert(struct interrupt *interrupt)
1686 {
1687 struct cpu *cpu = interrupt->extra;
1688 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &= ~interrupt->line;
1689 }
1690
1691
1692 /*
1693 * mips_cpu_exception():
1694 *
1695 * Cause an exception in a CPU. This sets a couple of coprocessor 0
1696 * registers, and the program counter.
1697 *
1698 * exccode the exception code
1699 * tlb set to non-zero if the exception handler at
1700 * 0x80000000 should be used. (normal = 0x80000180)
1701 * vaddr virtual address (for some exceptions)
1702 * coproc_nr coprocessor number (for some exceptions)
1703 * vaddr_vpn2 vpn2 (for some exceptions)
1704 * vaddr_asid asid (for some exceptions)
1705 * x_64 non-zero for 64-bit mode for R4000-style tlb misses
1706 */
1707 void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr,
1708 int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64)
1709 {
1710 uint64_t base;
1711 uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];
1712 int exc_model = cpu->cd.mips.cpu_type.exc_model;
1713
1714 if (cpu->is_halted) {
1715 /*
1716 * If the exception occurred on a 'wait' instruction, then let
1717 * the instruction following the wait instruction be the one
1718 * we continue at when the interrupt service routine returns.
1719 */
1720 cpu->is_halted = 0;
1721 cpu->pc += sizeof(uint32_t);
1722 }
1723
1724 if (!quiet_mode) {
1725 uint64_t offset;
1726 int x;
1727 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1728 cpu->pc, &offset);
1729
1730 debug("[ ");
1731 if (cpu->machine->ncpus > 1)
1732 debug("cpu%i: ", cpu->cpu_id);
1733
1734 debug("exception %s%s",
1735 exception_names[exccode], tlb? " <tlb>" : "");
1736
1737 switch (exccode) {
1738
1739 case EXCEPTION_INT:
1740 debug(" cause_im=0x%02x", (int)
1741 ((reg[COP0_CAUSE] & CAUSE_IP_MASK)
1742 >> CAUSE_IP_SHIFT));
1743 break;
1744
1745 case EXCEPTION_SYS:
1746 debug(" v0=%i", (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1747 for (x=0; x<4; x++) {
1748 int64_t d = cpu->cd.mips.gpr[MIPS_GPR_A0 + x];
1749 char strbuf[30];
1750
1751 if (d > -256 && d < 256) {
1752 debug(" a%i=%i", x, (int)d);
1753 } else if (memory_points_to_string(cpu,
1754 cpu->mem, d, 1)) {
1755 debug(" a%i=\"%s\"", x,
1756 memory_conv_to_string(cpu, cpu->mem,
1757 d, strbuf, sizeof(strbuf)));
1758 } else {
1759 if (cpu->is_32bit)
1760 debug(" a%i=0x%"PRIx32, x,
1761 (uint32_t)d);
1762 else
1763 debug(" a%i=0x%"PRIx64, x,
1764 (uint64_t)d);
1765 }
1766 }
1767 break;
1768
1769 case EXCEPTION_CPU:
1770 debug(" coproc_nr=%i", coproc_nr);
1771 break;
1772
1773 default:
1774 if (cpu->is_32bit)
1775 debug(" vaddr=0x%08x", (int)vaddr);
1776 else
1777 debug(" vaddr=0x%016"PRIx64, (uint64_t)vaddr);
1778 }
1779
1780 if (cpu->is_32bit)
1781 debug(" pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
1782 else
1783 debug(" pc=0x%016"PRIx64" ", (uint64_t)cpu->pc);
1784
1785 if (symbol != NULL)
1786 debug("<%s> ]\n", symbol);
1787 else
1788 debug("]\n");
1789 }
1790
1791 if (tlb && vaddr < 0x1000) {
1792 uint64_t offset;
1793 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1794 cpu->pc, &offset);
1795 fatal("[ ");
1796 if (cpu->machine->ncpus > 1)
1797 fatal("cpu%i: ", cpu->cpu_id);
1798 fatal("warning: LOW reference: vaddr=");
1799 if (cpu->is_32bit)
1800 fatal("0x%08"PRIx32, (uint32_t) vaddr);
1801 else
1802 fatal("0x%016"PRIx64, (uint64_t) vaddr);
1803 fatal(", exception %s, pc=", exception_names[exccode]);
1804 if (cpu->is_32bit)
1805 fatal("0x%08"PRIx32, (uint32_t) cpu->pc);
1806 else
1807 fatal("0x%016"PRIx64, (uint64_t)cpu->pc);
1808 fatal(" <%s> ]\n", symbol? symbol : "(no symbol)");
1809 }
1810
1811 /* Clear the exception code bits of the cause register... */
1812 if (exc_model == EXC3K)
1813 reg[COP0_CAUSE] &= ~R2K3K_CAUSE_EXCCODE_MASK;
1814 else
1815 reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
1816
1817 /* ... and OR in the exception code: */
1818 reg[COP0_CAUSE] |= (exccode << CAUSE_EXCCODE_SHIFT);
1819
1820 /* Always set CE (according to the R5000 manual): */
1821 reg[COP0_CAUSE] &= ~CAUSE_CE_MASK;
1822 reg[COP0_CAUSE] |= (coproc_nr << CAUSE_CE_SHIFT);
1823
1824 if (tlb || (exccode >= EXCEPTION_MOD && exccode <= EXCEPTION_ADES) ||
1825 exccode == EXCEPTION_VCEI || exccode == EXCEPTION_VCED) {
1826 reg[COP0_BADVADDR] = vaddr;
1827 if (cpu->is_32bit)
1828 reg[COP0_BADVADDR] = (int32_t)reg[COP0_BADVADDR];
1829
1830 if (exc_model == EXC3K) {
1831 reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
1832 reg[COP0_CONTEXT] |= ((vaddr_vpn2 <<
1833 R2K3K_CONTEXT_BADVPN_SHIFT) &
1834 R2K3K_CONTEXT_BADVPN_MASK);
1835
1836 reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)
1837 | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);
1838
1839 /* Sign-extend: */
1840 reg[COP0_CONTEXT] = (int64_t)(int32_t)reg[COP0_CONTEXT];
1841 reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];
1842 } else {
1843 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1844 reg[COP0_CONTEXT] &=
1845 ~CONTEXT_BADVPN2_MASK_R4100;
1846 reg[COP0_CONTEXT] |= ((vaddr_vpn2 <<
1847 CONTEXT_BADVPN2_SHIFT) &
1848 CONTEXT_BADVPN2_MASK_R4100);
1849
1850 /* TODO: fix these */
1851 reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1852 reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1853 reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1854 reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1855
1856 /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1857
1858 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800)) | vaddr_asid;
1859 } else {
1860 reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK;
1861 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK);
1862
1863 reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1864 reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1865 reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1866 reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1867
1868 /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1869
1870 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1871 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K)) | vaddr_asid;
1872 else
1873 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK)) | vaddr_asid;
1874 }
1875 }
1876 }
1877
1878 if (exc_model != EXC3K && reg[COP0_STATUS] & STATUS_EXL) {
1879 /*
1880 * Don't set EPC if STATUS_EXL is set, for R4000 and up.
1881 * This actually happens when running IRIX and Ultrix, when
1882 * they handle interrupts and/or tlb updates, I think, so
1883 * printing this with debug() looks better than with fatal().
1884 */
1885 /* debug("[ warning: cpu%i exception while EXL is set,"
1886 " not setting EPC ]\n", cpu->cpu_id); */
1887 } else {
1888 if (cpu->delay_slot) {
1889 reg[COP0_EPC] = cpu->pc - 4;
1890 reg[COP0_CAUSE] |= CAUSE_BD;
1891 } else {
1892 reg[COP0_EPC] = cpu->pc;
1893 reg[COP0_CAUSE] &= ~CAUSE_BD;
1894 }
1895 }
1896
1897 if (cpu->delay_slot)
1898 cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
1899 else
1900 cpu->delay_slot = NOT_DELAYED;
1901
1902 /* TODO: This is true for MIPS64, but how about others? */
1903 if (reg[COP0_STATUS] & STATUS_BEV)
1904 base = 0xffffffffbfc00200ULL;
1905 else
1906 base = 0xffffffff80000000ULL;
1907
1908 switch (exc_model) {
1909 case EXC3K:
1910 /* Userspace tlb, vs others: */
1911 if (tlb && !(vaddr & 0x80000000ULL) &&
1912 (exccode == EXCEPTION_TLBL || exccode == EXCEPTION_TLBS) )
1913 cpu->pc = base + 0x000;
1914 else
1915 cpu->pc = base + 0x080;
1916 break;
1917 default:
1918 /*
1919 * These offsets are according to the MIPS64 manual, but
1920 * should work with R4000 and the rest too (I hope).
1921 *
1922 * 0x000 TLB refill, if EXL=0
1923 * 0x080 64-bit XTLB refill, if EXL=0
1924 * 0x100 cache error (not implemented yet)
1925 * 0x180 general exception
1926 * 0x200 interrupt (if CAUSE_IV is set)
1927 */
1928 if (tlb && (exccode == EXCEPTION_TLBL ||
1929 exccode == EXCEPTION_TLBS) &&
1930 !(reg[COP0_STATUS] & STATUS_EXL)) {
1931 if (x_64)
1932 cpu->pc = base + 0x080;
1933 else
1934 cpu->pc = base + 0x000;
1935 } else {
1936 if (exccode == EXCEPTION_INT &&
1937 (reg[COP0_CAUSE] & CAUSE_IV))
1938 cpu->pc = base + 0x200;
1939 else
1940 cpu->pc = base + 0x180;
1941 }
1942 }
1943
1944 if (exc_model == EXC3K) {
1945 /* R{2,3}000: Shift the lowest 6 bits to the left two steps:*/
1946 reg[COP0_STATUS] = (reg[COP0_STATUS] & ~0x3f) +
1947 ((reg[COP0_STATUS] & 0xf) << 2);
1948 } else {
1949 /* R4000: */
1950 reg[COP0_STATUS] |= STATUS_EXL;
1951 }
1952
1953 /* Sign-extend: */
1954 reg[COP0_CAUSE] = (int64_t)(int32_t)reg[COP0_CAUSE];
1955 reg[COP0_STATUS] = (int64_t)(int32_t)reg[COP0_STATUS];
1956
1957 if (cpu->is_32bit) {
1958 reg[COP0_EPC] = (int64_t)(int32_t)reg[COP0_EPC];
1959 mips32_pc_to_pointers(cpu);
1960 } else {
1961 mips_pc_to_pointers(cpu);
1962 }
1963 }
1964
1965
1966 #include "memory_mips.c"
1967
1968
1969 #include "tmp_mips_tail.c"
1970

  ViewVC Help
Powered by ViewVC 1.1.26