/[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 30 - (hide annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 57221 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26