/[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 40 - (hide annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 53407 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26