/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 56915 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26