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

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

  ViewVC Help
Powered by ViewVC 1.1.26