/[gxemul]/trunk/src/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/cpu_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (hide annotations)
Mon Oct 8 16:18:19 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 120005 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.777 2005/06/12 12:31:52 debug Exp $
==============  RELEASE 0.3.3.1  ==============

20050609	Adding simple MIPS IPIs (to dev_mp).
20050611	Adding an ugly hack to track down low-reference bugs
		(define TRACE_NULL_CRASHES, or configure --tracenull).
		Other minor updates.
20050612	Adding a dummy evbmips mode.

==============  RELEASE 0.3.3.2  ==============


1 dpavlin 2 /*
2     * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 8 * $Id: cpu_mips.c,v 1.42 2005/06/11 20:59:11 debug Exp $
29 dpavlin 2 *
30     * MIPS core CPU emulation.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <sys/types.h>
37     #include <ctype.h>
38    
39     #include "../config.h"
40    
41    
42     #ifndef ENABLE_MIPS
43    
44    
45     #include "cpu_mips.h"
46    
47     /*
48     * mips_cpu_family_init():
49     *
50     * Bogus function.
51     */
52     int mips_cpu_family_init(struct cpu_family *fp)
53     {
54     return 0;
55     }
56    
57    
58     /* TODO: Maybe it isn't very nice to have these global like this... */
59     void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr,
60     int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64) { }
61    
62    
63     #else /* ENABLE_MIPS */
64    
65    
66     #include "arcbios.h"
67     #include "bintrans.h"
68     #include "cop0.h"
69     #include "cpu.h"
70     #include "cpu_mips.h"
71     #include "debugger.h"
72     #include "devices.h"
73     #include "emul.h"
74     #include "machine.h"
75     #include "memory.h"
76     #include "mips_cpu_types.h"
77     #include "opcodes_mips.h"
78     #include "symbol.h"
79    
80    
81     extern volatile int single_step;
82     extern int show_opcode_statistics;
83     extern int old_show_trace_tree;
84     extern int old_instruction_trace;
85     extern int old_quiet_mode;
86     extern int quiet_mode;
87    
88     static char *exception_names[] = EXCEPTION_NAMES;
89    
90     static char *hi6_names[] = HI6_NAMES;
91     static char *regimm_names[] = REGIMM_NAMES;
92     static char *special_names[] = SPECIAL_NAMES;
93     static char *special2_names[] = SPECIAL2_NAMES;
94    
95     static char *regnames[] = MIPS_REGISTER_NAMES;
96     static char *cop0_names[] = COP0_NAMES;
97    
98    
99     #include "cpu_mips16.c"
100    
101    
102     /*
103     * regname():
104     *
105     * Convert a register number into either 'r0', 'r31' etc, or a symbolic
106     * name, depending on machine->show_symbolic_register_names.
107     *
108     * NOTE: _NOT_ reentrant.
109     */
110     static char *regname(struct machine *machine, int r)
111     {
112     static char ch[4];
113     ch[3] = ch[2] = '\0';
114    
115     if (r<0 || r>=32)
116     strcpy(ch, "xx");
117     else if (machine->show_symbolic_register_names)
118     strcpy(ch, regnames[r]);
119     else
120     sprintf(ch, "r%i", r);
121    
122     return ch;
123     }
124    
125    
126     /*
127     * mips_cpu_new():
128     *
129     * Create a new MIPS cpu object.
130     */
131     struct cpu *mips_cpu_new(struct memory *mem, struct machine *machine,
132     int cpu_id, char *cpu_type_name)
133     {
134     struct cpu *cpu;
135     int i, found, j, tags_size, n_cache_lines, size_per_cache_line;
136     struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
137     int64_t secondary_cache_size;
138     int x, linesize;
139    
140     /* Scan the cpu_type_defs list for this cpu type: */
141     i = 0;
142     found = -1;
143     while (i >= 0 && cpu_type_defs[i].name != NULL) {
144     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
145     found = i;
146     break;
147     }
148     i++;
149     }
150    
151     if (found == -1)
152     return NULL;
153    
154     cpu = malloc(sizeof(struct cpu));
155     if (cpu == NULL) {
156     fprintf(stderr, "out of memory\n");
157     exit(1);
158     }
159    
160     memset(cpu, 0, sizeof(struct cpu));
161     cpu->memory_rw = mips_memory_rw;
162     cpu->cd.mips.cpu_type = cpu_type_defs[found];
163     cpu->name = cpu->cd.mips.cpu_type.name;
164     cpu->mem = mem;
165     cpu->machine = machine;
166     cpu->cpu_id = cpu_id;
167     cpu->byte_order = EMUL_LITTLE_ENDIAN;
168     cpu->bootstrap_cpu_flag = 0;
169     cpu->running = 0;
170     cpu->cd.mips.gpr[MIPS_GPR_SP] = INITIAL_STACK_POINTER;
171    
172     if (cpu_id == 0)
173     debug("%s", cpu->cd.mips.cpu_type.name);
174    
175     /*
176     * CACHES:
177     *
178     * 1) Use DEFAULT_PCACHE_SIZE and DEFAULT_PCACHE_LINESIZE etc.
179     * 2) If there are specific values defined for this type of cpu,
180     * in its cpu_type substruct, then let's use those.
181     * 3) Values in the emul struct override both of the above.
182     *
183     * Once we've decided which values to use, they are stored in
184     * the emul struct so they can be used from src/machine.c etc.
185     */
186    
187     x = DEFAULT_PCACHE_SIZE;
188     if (cpu->cd.mips.cpu_type.default_pdcache)
189     x = cpu->cd.mips.cpu_type.default_pdcache;
190     if (machine->cache_pdcache == 0)
191     machine->cache_pdcache = x;
192    
193     x = DEFAULT_PCACHE_SIZE;
194     if (cpu->cd.mips.cpu_type.default_picache)
195     x = cpu->cd.mips.cpu_type.default_picache;
196     if (machine->cache_picache == 0)
197     machine->cache_picache = x;
198    
199     if (machine->cache_secondary == 0)
200     machine->cache_secondary = cpu->cd.mips.cpu_type.default_scache;
201    
202     linesize = DEFAULT_PCACHE_LINESIZE;
203     if (cpu->cd.mips.cpu_type.default_pdlinesize)
204     linesize = cpu->cd.mips.cpu_type.default_pdlinesize;
205     if (machine->cache_pdcache_linesize == 0)
206     machine->cache_pdcache_linesize = linesize;
207    
208     linesize = DEFAULT_PCACHE_LINESIZE;
209     if (cpu->cd.mips.cpu_type.default_pilinesize)
210     linesize = cpu->cd.mips.cpu_type.default_pilinesize;
211     if (machine->cache_picache_linesize == 0)
212     machine->cache_picache_linesize = linesize;
213    
214     linesize = 0;
215     if (cpu->cd.mips.cpu_type.default_slinesize)
216     linesize = cpu->cd.mips.cpu_type.default_slinesize;
217     if (machine->cache_secondary_linesize == 0)
218     machine->cache_secondary_linesize = linesize;
219    
220    
221     /*
222     * Primary Data and Instruction caches:
223     */
224     for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {
225     switch (i) {
226     case CACHE_DATA:
227     x = 1 << machine->cache_pdcache;
228     linesize = 1 << machine->cache_pdcache_linesize;
229     break;
230     case CACHE_INSTRUCTION:
231     x = 1 << machine->cache_picache;
232     linesize = 1 << machine->cache_picache_linesize;
233     break;
234     }
235    
236     /* Primary cache size and linesize: */
237     cpu->cd.mips.cache_size[i] = x;
238     cpu->cd.mips.cache_linesize[i] = linesize;
239    
240     switch (cpu->cd.mips.cpu_type.rev) {
241     case MIPS_R2000:
242     case MIPS_R3000:
243     size_per_cache_line = sizeof(struct r3000_cache_line);
244     break;
245     default:
246     size_per_cache_line = sizeof(struct r4000_cache_line);
247     }
248    
249     cpu->cd.mips.cache_mask[i] = cpu->cd.mips.cache_size[i] - 1;
250     cpu->cd.mips.cache_miss_penalty[i] = 10; /* TODO ? */
251    
252     cpu->cd.mips.cache[i] = malloc(cpu->cd.mips.cache_size[i]);
253     if (cpu->cd.mips.cache[i] == NULL) {
254     fprintf(stderr, "out of memory\n");
255     }
256    
257     n_cache_lines = cpu->cd.mips.cache_size[i] /
258     cpu->cd.mips.cache_linesize[i];
259     tags_size = n_cache_lines * size_per_cache_line;
260    
261     cpu->cd.mips.cache_tags[i] = malloc(tags_size);
262     if (cpu->cd.mips.cache_tags[i] == NULL) {
263     fprintf(stderr, "out of memory\n");
264     }
265    
266     /* Initialize the cache tags: */
267     switch (cpu->cd.mips.cpu_type.rev) {
268     case MIPS_R2000:
269     case MIPS_R3000:
270     for (j=0; j<n_cache_lines; j++) {
271     struct r3000_cache_line *rp;
272     rp = (struct r3000_cache_line *)
273     cpu->cd.mips.cache_tags[i];
274     rp[j].tag_paddr = 0;
275     rp[j].tag_valid = 0;
276     }
277     break;
278     default:
279     ;
280     }
281    
282     /* Set cache_last_paddr to something "impossible": */
283     cpu->cd.mips.cache_last_paddr[i] = IMPOSSIBLE_PADDR;
284     }
285    
286     /*
287     * Secondary cache:
288     */
289     secondary_cache_size = 0;
290     if (machine->cache_secondary)
291     secondary_cache_size = 1 << machine->cache_secondary;
292     /* TODO: linesize... */
293    
294     if (cpu_id == 0) {
295     debug(" (I+D = %i+%i KB",
296     (int)(cpu->cd.mips.cache_size[CACHE_INSTRUCTION] / 1024),
297     (int)(cpu->cd.mips.cache_size[CACHE_DATA] / 1024));
298    
299     if (secondary_cache_size != 0) {
300     debug(", L2 = ");
301     if (secondary_cache_size >= 1048576)
302     debug("%i MB", (int)
303     (secondary_cache_size / 1048576));
304     else
305     debug("%i KB", (int)
306     (secondary_cache_size / 1024));
307     }
308    
309     debug(")");
310     }
311    
312     /* System coprocessor (0), and FPU (1): */
313     cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);
314     cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);
315    
316     /*
317     * Initialize the cpu->cd.mips.pc_last_* cache (a 1-entry cache of the
318     * last program counter value). For pc_last_virtual_page, any
319     * "impossible" value will do. The pc should never ever get this
320     * value. (The other pc_last* variables do not need initialization,
321     * as they are not used before pc_last_virtual_page.)
322     */
323     cpu->cd.mips.pc_last_virtual_page = PC_LAST_PAGE_IMPOSSIBLE_VALUE;
324    
325     switch (cpu->cd.mips.cpu_type.mmu_model) {
326     case MMU3K:
327     cpu->translate_address = translate_address_mmu3k;
328     break;
329     case MMU8K:
330     cpu->translate_address = translate_address_mmu8k;
331     break;
332     case MMU10K:
333     cpu->translate_address = translate_address_mmu10k;
334     break;
335     default:
336     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
337     cpu->translate_address = translate_address_mmu4100;
338     else
339     cpu->translate_address = translate_address_generic;
340     }
341    
342     return cpu;
343     }
344    
345    
346     /*
347     * mips_cpu_show_full_statistics():
348     *
349     * Show detailed statistics on opcode usage on each cpu.
350     */
351     void mips_cpu_show_full_statistics(struct machine *m)
352     {
353     int i, s1, s2, iadd = 4;
354    
355     if (m->bintrans_enable)
356     fatal("NOTE: Dynamic binary translation is used; this list"
357     " of opcode usage\n only includes instructions that"
358     " were interpreted manually!\n");
359    
360     for (i=0; i<m->ncpus; i++) {
361     fatal("cpu%i opcode statistics:\n", i);
362     debug_indentation(iadd);
363    
364     for (s1=0; s1<N_HI6; s1++) {
365     if (m->cpus[i]->cd.mips.stats_opcode[s1] > 0)
366     fatal("opcode %02x (%7s): %li\n", s1,
367     hi6_names[s1],
368     m->cpus[i]->cd.mips.stats_opcode[s1]);
369    
370     debug_indentation(iadd);
371     if (s1 == HI6_SPECIAL)
372     for (s2=0; s2<N_SPECIAL; s2++)
373     if (m->cpus[i]->cd.mips.stats__special[
374     s2] > 0)
375     fatal("special %02x (%7s): "
376     "%li\n", s2, special_names[
377     s2], m->cpus[i]->cd.mips.
378     stats__special[s2]);
379     if (s1 == HI6_REGIMM)
380     for (s2=0; s2<N_REGIMM; s2++)
381     if (m->cpus[i]->cd.mips.stats__regimm[
382     s2] > 0)
383     fatal("regimm %02x (%7s): "
384     "%li\n", s2, regimm_names[
385     s2], m->cpus[i]->cd.mips.
386     stats__regimm[s2]);
387     if (s1 == HI6_SPECIAL2)
388     for (s2=0; s2<N_SPECIAL; s2++)
389     if (m->cpus[i]->cd.mips.stats__special2
390     [s2] > 0)
391     fatal("special2 %02x (%7s): "
392     "%li\n", s2,
393     special2_names[s2], m->
394     cpus[i]->cd.mips.
395     stats__special2[s2]);
396     debug_indentation(-iadd);
397     }
398    
399     debug_indentation(-iadd);
400     }
401     }
402    
403    
404     /*
405     * mips_cpu_tlbdump():
406     *
407     * Called from the debugger to dump the TLB in a readable format.
408     * x is the cpu number to dump, or -1 to dump all CPUs.
409     *
410     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
411     * just dumped.
412     */
413     void mips_cpu_tlbdump(struct machine *m, int x, int rawflag)
414     {
415     int i, j;
416    
417     /* Nicely formatted output: */
418     if (!rawflag) {
419     for (i=0; i<m->ncpus; i++) {
420     int pageshift = 12;
421    
422     if (x >= 0 && i != x)
423     continue;
424    
425     if (m->cpus[i]->cd.mips.cpu_type.rev == MIPS_R4100)
426     pageshift = 10;
427    
428     /* Print index, random, and wired: */
429     printf("cpu%i: (", i);
430     switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {
431     case 1:
432     case 2:
433     printf("index=0x%x random=0x%x",
434     (int) ((m->cpus[i]->cd.mips.coproc[0]->
435     reg[COP0_INDEX] & R2K3K_INDEX_MASK)
436     >> R2K3K_INDEX_SHIFT),
437     (int) ((m->cpus[i]->cd.mips.coproc[0]->
438     reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
439     >> R2K3K_RANDOM_SHIFT));
440     break;
441     default:
442     printf("index=0x%x random=0x%x",
443     (int) (m->cpus[i]->cd.mips.coproc[0]->
444     reg[COP0_INDEX] & INDEX_MASK),
445     (int) (m->cpus[i]->cd.mips.coproc[0]->
446     reg[COP0_RANDOM] & RANDOM_MASK));
447     printf(" wired=0x%llx", (long long)
448     m->cpus[i]->cd.mips.coproc[0]->
449     reg[COP0_WIRED]);
450     }
451    
452     printf(")\n");
453    
454     for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
455     nr_of_tlb_entries; j++) {
456     uint64_t hi,lo0,lo1,mask;
457     hi = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi;
458     lo0 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0;
459     lo1 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1;
460     mask = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask;
461    
462     printf("%3i: ", j);
463     switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
464     case MMU3K:
465     if (!(lo0 & R2K3K_ENTRYLO_V)) {
466     printf("(invalid)\n");
467     continue;
468     }
469     printf("vaddr=0x%08x ",
470     (int) (hi&R2K3K_ENTRYHI_VPN_MASK));
471     if (lo0 & R2K3K_ENTRYLO_G)
472     printf("(global), ");
473     else
474     printf("(asid %02x),",
475     (int) ((hi & R2K3K_ENTRYHI_ASID_MASK)
476     >> R2K3K_ENTRYHI_ASID_SHIFT));
477     printf(" paddr=0x%08x ",
478     (int) (lo0&R2K3K_ENTRYLO_PFN_MASK));
479     if (lo0 & R2K3K_ENTRYLO_N)
480     printf("N");
481     if (lo0 & R2K3K_ENTRYLO_D)
482     printf("D");
483     printf("\n");
484     break;
485     default:
486     /* TODO: MIPS32 doesn't need 0x16llx */
487     if (m->cpus[i]->cd.mips.cpu_type.mmu_model == MMU10K)
488     printf("vaddr=0x%1x..%011llx ",
489     (int) (hi >> 60),
490     (long long) (hi&ENTRYHI_VPN2_MASK_R10K));
491     else
492     printf("vaddr=0x%1x..%010llx ",
493     (int) (hi >> 60),
494     (long long) (hi&ENTRYHI_VPN2_MASK));
495     if (hi & TLB_G)
496     printf("(global): ");
497     else
498     printf("(asid %02x):",
499     (int) (hi & ENTRYHI_ASID));
500    
501     /* TODO: Coherency bits */
502    
503     if (!(lo0 & ENTRYLO_V))
504     printf(" p0=(invalid) ");
505     else
506     printf(" p0=0x%09llx ", (long long)
507     (((lo0&ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << pageshift));
508     printf(lo0 & ENTRYLO_D? "D" : " ");
509    
510     if (!(lo1 & ENTRYLO_V))
511     printf(" p1=(invalid) ");
512     else
513     printf(" p1=0x%09llx ", (long long)
514     (((lo1&ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << pageshift));
515     printf(lo1 & ENTRYLO_D? "D" : " ");
516     mask |= (1 << (pageshift+1)) - 1;
517     switch (mask) {
518     case 0x7ff: printf(" (1KB)"); break;
519     case 0x1fff: printf(" (4KB)"); break;
520     case 0x7fff: printf(" (16KB)"); break;
521     case 0x1ffff: printf(" (64KB)"); break;
522     case 0x7ffff: printf(" (256KB)"); break;
523     case 0x1fffff: printf(" (1MB)"); break;
524     case 0x7fffff: printf(" (4MB)"); break;
525     case 0x1ffffff: printf(" (16MB)"); break;
526     case 0x7ffffff: printf(" (64MB)"); break;
527     default:
528     printf(" (mask=%08x?)", (int)mask);
529     }
530     printf("\n");
531     }
532     }
533     }
534    
535     return;
536     }
537    
538     /* Raw output: */
539     for (i=0; i<m->ncpus; i++) {
540     if (x >= 0 && i != x)
541     continue;
542    
543     /* Print index, random, and wired: */
544     printf("cpu%i: (", i);
545    
546     if (m->cpus[i]->cd.mips.cpu_type.isa_level < 3 ||
547     m->cpus[i]->cd.mips.cpu_type.isa_level == 32)
548     printf("index=0x%08x random=0x%08x",
549     (int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],
550     (int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_RANDOM]);
551     else
552     printf("index=0x%016llx random=0x%016llx", (long long)
553     m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],
554     (long long)m->cpus[i]->cd.mips.coproc[0]->reg
555     [COP0_RANDOM]);
556    
557     if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
558     printf(" wired=0x%llx", (long long)
559     m->cpus[i]->cd.mips.coproc[0]->reg[COP0_WIRED]);
560    
561     printf(")\n");
562    
563     for (j=0; j<m->cpus[i]->cd.mips.cpu_type.nr_of_tlb_entries; j++) {
564     if (m->cpus[i]->cd.mips.cpu_type.mmu_model == MMU3K)
565     printf("%3i: hi=0x%08x lo=0x%08x\n",
566     j,
567     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
568     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0);
569     else if (m->cpus[i]->cd.mips.cpu_type.isa_level < 3 ||
570     m->cpus[i]->cd.mips.cpu_type.isa_level == 32)
571     printf("%3i: hi=0x%08x mask=0x%08x "
572     "lo0=0x%08x lo1=0x%08x\n", j,
573     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
574     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
575     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
576     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
577     else
578     printf("%3i: hi=0x%016llx mask=0x%016llx "
579     "lo0=0x%016llx lo1=0x%016llx\n", j,
580     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
581     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
582     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
583     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
584     }
585     }
586     }
587    
588    
589     /*
590     * mips_cpu_register_match():
591     */
592     void mips_cpu_register_match(struct machine *m, char *name,
593     int writeflag, uint64_t *valuep, int *match_register)
594     {
595     int cpunr = 0;
596    
597     /* CPU number: */
598    
599     /* TODO */
600    
601     /* Register name: */
602     if (strcasecmp(name, "pc") == 0) {
603     if (writeflag) {
604     m->cpus[cpunr]->pc = *valuep;
605     if (m->cpus[cpunr]->cd.mips.delay_slot) {
606     printf("NOTE: Clearing the delay slot"
607     " flag! (It was set before.)\n");
608     m->cpus[cpunr]->cd.mips.delay_slot = 0;
609     }
610     if (m->cpus[cpunr]->cd.mips.nullify_next) {
611     printf("NOTE: Clearing the nullify-ne"
612     "xt flag! (It was set before.)\n");
613     m->cpus[cpunr]->cd.mips.nullify_next = 0;
614     }
615     } else
616     *valuep = m->cpus[cpunr]->pc;
617     *match_register = 1;
618     } else if (strcasecmp(name, "hi") == 0) {
619     if (writeflag)
620     m->cpus[cpunr]->cd.mips.hi = *valuep;
621     else
622     *valuep = m->cpus[cpunr]->cd.mips.hi;
623     *match_register = 1;
624     } else if (strcasecmp(name, "lo") == 0) {
625     if (writeflag)
626     m->cpus[cpunr]->cd.mips.lo = *valuep;
627     else
628     *valuep = m->cpus[cpunr]->cd.mips.lo;
629     *match_register = 1;
630     } else if (name[0] == 'r' && isdigit((int)name[1])) {
631     int nr = atoi(name + 1);
632     if (nr >= 0 && nr < N_MIPS_GPRS) {
633     if (writeflag) {
634     if (nr != 0)
635     m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;
636     else
637     printf("WARNING: Attempt to modify r0.\n");
638     } else
639     *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];
640     *match_register = 1;
641     }
642     } else {
643     /* Check for a symbolic name such as "t6" or "at": */
644     int nr;
645     for (nr=0; nr<N_MIPS_GPRS; nr++)
646     if (strcmp(name, regnames[nr]) == 0) {
647     if (writeflag) {
648     if (nr != 0)
649     m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;
650     else
651     printf("WARNING: Attempt to modify r0.\n");
652     } else
653     *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];
654     *match_register = 1;
655     }
656     }
657    
658     if (!(*match_register)) {
659     /* Check for a symbolic coproc0 name: */
660     int nr;
661     for (nr=0; nr<32; nr++)
662     if (strcmp(name, cop0_names[nr]) == 0) {
663     if (writeflag) {
664     coproc_register_write(m->cpus[cpunr],
665     m->cpus[cpunr]->cd.mips.coproc[0], nr,
666     valuep, 1);
667     } else {
668     /* TODO: Use coproc_register_read instead? */
669     *valuep = m->cpus[cpunr]->cd.mips.coproc[0]->reg[nr];
670     }
671     *match_register = 1;
672     }
673     }
674    
675     /* TODO: Coprocessor 1,2,3 registers. */
676     }
677    
678    
679     /*
680     * cpu_flags():
681     *
682     * Returns a pointer to a string containing "(d)" "(j)" "(dj)" or "",
683     * depending on the cpu's current delay_slot and last_was_jumptoself
684     * flags.
685     */
686     static const char *cpu_flags(struct cpu *cpu)
687     {
688     if (cpu->cd.mips.delay_slot) {
689     if (cpu->cd.mips.last_was_jumptoself)
690     return " (dj)";
691     else
692     return " (d)";
693     } else {
694     if (cpu->cd.mips.last_was_jumptoself)
695     return " (j)";
696     else
697     return "";
698     }
699     }
700    
701    
702     /*
703     * mips_cpu_disassemble_instr():
704     *
705     * Convert an instruction word into human readable format, for instruction
706     * tracing.
707     *
708     * If running is 1, cpu->pc should be the address of the instruction.
709     *
710     * If running is 0, things that depend on the runtime environment (eg.
711     * register contents) will not be shown, and addr will be used instead of
712     * cpu->pc for relative addresses.
713     *
714     * NOTE 2: coprocessor instructions are not decoded nicely yet (TODO)
715     */
716     int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,
717     int running, uint64_t dumpaddr, int bintrans)
718     {
719     int hi6, special6, regimm5;
720     int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;
721     uint64_t addr, offset;
722     uint32_t instrword;
723     unsigned char instr[4];
724     char *symbol;
725    
726     if (running)
727     dumpaddr = cpu->pc;
728    
729 dpavlin 4 if ((dumpaddr & 3) != 0)
730     printf("WARNING: Unaligned address!\n");
731    
732 dpavlin 2 symbol = get_symbol_name(&cpu->machine->symbol_context,
733     dumpaddr, &offset);
734     if (symbol != NULL && offset==0)
735     debug("<%s>\n", symbol);
736    
737     if (cpu->machine->ncpus > 1 && running)
738     debug("cpu%i: ", cpu->cpu_id);
739    
740     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
741     cpu->cd.mips.cpu_type.isa_level == 32)
742     debug("%08x", (int)dumpaddr);
743     else
744     debug("%016llx", (long long)dumpaddr);
745    
746     *((uint32_t *)&instr[0]) = *((uint32_t *)&originstr[0]);
747    
748     /*
749     * The rest of the code is written for little endian,
750     * so swap if necessary:
751     */
752     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
753     int tmp = instr[0]; instr[0] = instr[3];
754     instr[3] = tmp;
755     tmp = instr[1]; instr[1] = instr[2];
756     instr[2] = tmp;
757     }
758    
759     debug(": %02x%02x%02x%02x",
760     instr[3], instr[2], instr[1], instr[0]);
761    
762     if (running)
763     debug("%s", cpu_flags(cpu));
764    
765     debug("\t");
766    
767     if (bintrans && running) {
768     debug("(bintrans)");
769     goto disasm_ret;
770     }
771    
772     /*
773     * Decode the instruction:
774     */
775    
776     if (cpu->cd.mips.nullify_next && running) {
777     debug("(nullified)");
778     goto disasm_ret;
779     }
780    
781     hi6 = (instr[3] >> 2) & 0x3f;
782    
783     switch (hi6) {
784     case HI6_SPECIAL:
785     special6 = instr[0] & 0x3f;
786     switch (special6) {
787     case SPECIAL_SLL:
788     case SPECIAL_SRL:
789     case SPECIAL_SRA:
790     case SPECIAL_DSLL:
791     case SPECIAL_DSRL:
792     case SPECIAL_DSRA:
793     case SPECIAL_DSLL32:
794     case SPECIAL_DSRL32:
795     case SPECIAL_DSRA32:
796     rt = instr[2] & 31;
797     rd = (instr[1] >> 3) & 31;
798     sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
799    
800     if (rd == 0 && special6 == SPECIAL_SLL) {
801     if (sa == 0)
802     debug("nop");
803     else if (sa == 1)
804     debug("ssnop");
805     else
806     debug("nop (weird, sa=%i)", sa);
807     goto disasm_ret;
808     } else
809     debug("%s\t%s,",
810     special_names[special6],
811     regname(cpu->machine, rd));
812     debug("%s,%i", regname(cpu->machine, rt), sa);
813     break;
814     case SPECIAL_DSRLV:
815     case SPECIAL_DSRAV:
816     case SPECIAL_DSLLV:
817     case SPECIAL_SLLV:
818     case SPECIAL_SRAV:
819     case SPECIAL_SRLV:
820     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
821     rt = instr[2] & 31;
822     rd = (instr[1] >> 3) & 31;
823     debug("%s\t%s",
824     special_names[special6], regname(cpu->machine, rd));
825     debug(",%s", regname(cpu->machine, rt));
826     debug(",%s", regname(cpu->machine, rs));
827     break;
828     case SPECIAL_JR:
829     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
830     symbol = get_symbol_name(&cpu->machine->symbol_context,
831     cpu->cd.mips.gpr[rs], &offset);
832     debug("jr\t%s", regname(cpu->machine, rs));
833     if (running && symbol != NULL)
834     debug("\t<%s>", symbol);
835     break;
836     case SPECIAL_JALR:
837     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
838     rd = (instr[1] >> 3) & 31;
839     symbol = get_symbol_name(&cpu->machine->symbol_context,
840     cpu->cd.mips.gpr[rs], &offset);
841     debug("jalr\t%s", regname(cpu->machine, rd));
842     debug(",%s", regname(cpu->machine, rs));
843     if (running && symbol != NULL)
844     debug("\t<%s>", symbol);
845     break;
846     case SPECIAL_MFHI:
847     case SPECIAL_MFLO:
848     rd = (instr[1] >> 3) & 31;
849     debug("%s\t%s", special_names[special6],
850     regname(cpu->machine, rd));
851     break;
852     case SPECIAL_MTLO:
853     case SPECIAL_MTHI:
854     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
855     debug("%s\t%s", special_names[special6],
856     regname(cpu->machine, rs));
857     break;
858     case SPECIAL_ADD:
859     case SPECIAL_ADDU:
860     case SPECIAL_SUB:
861     case SPECIAL_SUBU:
862     case SPECIAL_AND:
863     case SPECIAL_OR:
864     case SPECIAL_XOR:
865     case SPECIAL_NOR:
866     case SPECIAL_SLT:
867     case SPECIAL_SLTU:
868     case SPECIAL_DADD:
869     case SPECIAL_DADDU:
870     case SPECIAL_DSUB:
871     case SPECIAL_DSUBU:
872     case SPECIAL_MOVZ:
873     case SPECIAL_MOVN:
874     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
875     rt = instr[2] & 31;
876     rd = (instr[1] >> 3) & 31;
877     if ((special6 == SPECIAL_ADDU ||
878     special6 == SPECIAL_DADDU ||
879     special6 == SPECIAL_SUBU ||
880     special6 == SPECIAL_DSUBU) && rt == 0) {
881     /* Special case 1: addu/daddu/subu/dsubu with
882     rt = the zero register ==> move */
883     debug("move\t%s", regname(cpu->machine, rd));
884     debug(",%s", regname(cpu->machine, rs));
885     } else if ((special6 == SPECIAL_ADDU ||
886     special6 == SPECIAL_DADDU) && rs == 0) {
887     /* Special case 2: addu/daddu with
888     rs = the zero register ==> move */
889     debug("move\t%s", regname(cpu->machine, rd));
890     debug(",%s", regname(cpu->machine, rt));
891     } else {
892     debug("%s\t%s", special_names[special6],
893     regname(cpu->machine, rd));
894     debug(",%s", regname(cpu->machine, rs));
895     debug(",%s", regname(cpu->machine, rt));
896     }
897     break;
898     case SPECIAL_MULT:
899     case SPECIAL_MULTU:
900     case SPECIAL_DMULT:
901     case SPECIAL_DMULTU:
902     case SPECIAL_DIV:
903     case SPECIAL_DIVU:
904     case SPECIAL_DDIV:
905     case SPECIAL_DDIVU:
906     case SPECIAL_TGE:
907     case SPECIAL_TGEU:
908     case SPECIAL_TLT:
909     case SPECIAL_TLTU:
910     case SPECIAL_TEQ:
911     case SPECIAL_TNE:
912     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
913     rt = instr[2] & 31;
914     rd = (instr[1] >> 3) & 31;
915     if (special6 == SPECIAL_MULT) {
916     if (rd != 0) {
917     debug("mult_xx\t%s",
918     regname(cpu->machine, rd));
919     debug(",%s", regname(cpu->machine, rs));
920     debug(",%s", regname(cpu->machine, rt));
921     goto disasm_ret;
922     }
923     }
924     debug("%s\t%s", special_names[special6],
925     regname(cpu->machine, rs));
926     debug(",%s", regname(cpu->machine, rt));
927     break;
928     case SPECIAL_SYNC:
929     imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
930     debug("sync\t0x%02x", imm);
931     break;
932     case SPECIAL_SYSCALL:
933     imm = (((instr[3] << 24) + (instr[2] << 16) +
934     (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
935     if (imm != 0)
936     debug("syscall\t0x%05x", imm);
937     else
938     debug("syscall");
939     break;
940     case SPECIAL_BREAK:
941     /* TODO: imm, as in 'syscall'? */
942     debug("break");
943     break;
944     case SPECIAL_MFSA:
945     rd = (instr[1] >> 3) & 31;
946     debug("mfsa\t%s", regname(cpu->machine, rd));
947     break;
948     case SPECIAL_MTSA:
949     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
950     debug("mtsa\t%s", regname(cpu->machine, rs));
951     break;
952     default:
953     debug("unimplemented special6 = 0x%02x", special6);
954     }
955     break;
956     case HI6_BEQ:
957     case HI6_BEQL:
958     case HI6_BNE:
959     case HI6_BNEL:
960     case HI6_BGTZ:
961     case HI6_BGTZL:
962     case HI6_BLEZ:
963     case HI6_BLEZL:
964     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
965     rt = instr[2] & 31;
966     imm = (instr[1] << 8) + instr[0];
967     if (imm >= 32768)
968     imm -= 65536;
969     addr = (dumpaddr + 4) + (imm << 2);
970     debug("%s\t", hi6_names[hi6]);
971    
972     switch (hi6) {
973     case HI6_BEQ:
974     case HI6_BEQL:
975     case HI6_BNE:
976     case HI6_BNEL:
977     debug("%s,", regname(cpu->machine, rt));
978     }
979    
980     debug("%s,", regname(cpu->machine, rs));
981    
982     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
983     cpu->cd.mips.cpu_type.isa_level == 32)
984     debug("0x%08x", (int)addr);
985     else
986     debug("0x%016llx", (long long)addr);
987    
988     symbol = get_symbol_name(&cpu->machine->symbol_context,
989     addr, &offset);
990     if (symbol != NULL && offset != addr)
991     debug("\t<%s>", symbol);
992     break;
993     case HI6_ADDI:
994     case HI6_ADDIU:
995     case HI6_DADDI:
996     case HI6_DADDIU:
997     case HI6_SLTI:
998     case HI6_SLTIU:
999     case HI6_ANDI:
1000     case HI6_ORI:
1001     case HI6_XORI:
1002     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1003     rt = instr[2] & 31;
1004     imm = (instr[1] << 8) + instr[0];
1005     if (imm >= 32768)
1006     imm -= 65536;
1007     debug("%s\t%s,", hi6_names[hi6], regname(cpu->machine, rt));
1008     debug("%s,", regname(cpu->machine, rs));
1009     if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)
1010     debug("0x%04x", imm & 0xffff);
1011     else
1012     debug("%i", imm);
1013     break;
1014     case HI6_LUI:
1015     rt = instr[2] & 31;
1016     imm = (instr[1] << 8) + instr[0];
1017     debug("lui\t%s,0x%x", regname(cpu->machine, rt), imm);
1018     break;
1019     case HI6_LB:
1020     case HI6_LBU:
1021     case HI6_LH:
1022     case HI6_LHU:
1023     case HI6_LW:
1024     case HI6_LWU:
1025     case HI6_LD:
1026     case HI6_LQ_MDMX:
1027     case HI6_LWC1:
1028     case HI6_LWC2:
1029     case HI6_LWC3:
1030     case HI6_LDC1:
1031     case HI6_LDC2:
1032     case HI6_LL:
1033     case HI6_LLD:
1034     case HI6_SB:
1035     case HI6_SH:
1036     case HI6_SW:
1037     case HI6_SD:
1038     case HI6_SQ:
1039     case HI6_SC:
1040     case HI6_SCD:
1041     case HI6_SWC1:
1042     case HI6_SWC2:
1043     case HI6_SWC3:
1044     case HI6_SDC1:
1045     case HI6_SDC2:
1046     case HI6_LWL:
1047     case HI6_LWR:
1048     case HI6_LDL:
1049     case HI6_LDR:
1050     case HI6_SWL:
1051     case HI6_SWR:
1052     case HI6_SDL:
1053     case HI6_SDR:
1054     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1055     rt = instr[2] & 31;
1056     imm = (instr[1] << 8) + instr[0];
1057     if (imm >= 32768)
1058     imm -= 65536;
1059     symbol = get_symbol_name(&cpu->machine->symbol_context,
1060     cpu->cd.mips.gpr[rs] + imm, &offset);
1061    
1062     /* LWC3 is PREF in the newer ISA levels: */
1063     /* TODO: Which ISAs? cpu->cd.mips.cpu_type.isa_level >= 4? */
1064     if (hi6 == HI6_LWC3) {
1065     debug("pref\t0x%x,%i(%s)",
1066     rt, imm, regname(cpu->machine, rs));
1067    
1068     if (running) {
1069     debug("\t[0x%016llx = %s]",
1070     (long long)(cpu->cd.mips.gpr[rs] + imm));
1071     if (symbol != NULL)
1072     debug(" = %s", symbol);
1073     debug("]");
1074     }
1075     goto disasm_ret;
1076     }
1077    
1078     debug("%s\t", hi6_names[hi6]);
1079    
1080     if (hi6 == HI6_SWC1 || hi6 == HI6_SWC2 || hi6 == HI6_SWC3 ||
1081     hi6 == HI6_SDC1 || hi6 == HI6_SDC2 ||
1082     hi6 == HI6_LWC1 || hi6 == HI6_LWC2 || hi6 == HI6_LWC3 ||
1083     hi6 == HI6_LDC1 || hi6 == HI6_LDC2)
1084     debug("r%i", rt);
1085     else
1086     debug("%s", regname(cpu->machine, rt));
1087    
1088     debug(",%i(%s)", imm, regname(cpu->machine, rs));
1089    
1090     if (running) {
1091     debug("\t[");
1092    
1093     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1094     cpu->cd.mips.cpu_type.isa_level == 32)
1095     debug("0x%08x", (int)(cpu->cd.mips.gpr[rs] + imm));
1096     else
1097     debug("0x%016llx",
1098     (long long)(cpu->cd.mips.gpr[rs] + imm));
1099    
1100     if (symbol != NULL)
1101     debug(" = %s", symbol);
1102    
1103     debug(", data=");
1104     } else
1105     break;
1106     /* NOTE: No break here (if we are running) as it is up
1107     to the caller to print 'data'. */
1108     return sizeof(instrword);
1109     case HI6_J:
1110     case HI6_JAL:
1111     imm = (((instr[3] & 3) << 24) + (instr[2] << 16) +
1112     (instr[1] << 8) + instr[0]) << 2;
1113     addr = (dumpaddr + 4) & ~((1 << 28) - 1);
1114     addr |= imm;
1115     symbol = get_symbol_name(&cpu->machine->symbol_context,
1116     addr, &offset);
1117     debug("%s\t0x", hi6_names[hi6]);
1118     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1119     cpu->cd.mips.cpu_type.isa_level == 32)
1120     debug("%08x", (int)addr);
1121     else
1122     debug("%016llx", (long long)addr);
1123     if (symbol != NULL)
1124     debug("\t<%s>", symbol);
1125     break;
1126     case HI6_COP0:
1127     case HI6_COP1:
1128     case HI6_COP2:
1129     case HI6_COP3:
1130     imm = (instr[3] << 24) + (instr[2] << 16) +
1131     (instr[1] << 8) + instr[0];
1132     imm &= ((1 << 26) - 1);
1133    
1134     /* Call coproc_function(), but ONLY disassembly, no exec: */
1135     coproc_function(cpu, cpu->cd.mips.coproc[hi6 - HI6_COP0],
1136     hi6 - HI6_COP0, imm, 1, running);
1137     return sizeof(instrword);
1138     case HI6_CACHE:
1139     rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
1140     copz = instr[2] & 31;
1141     imm = (instr[1] << 8) + instr[0];
1142     cache_op = copz >> 2;
1143     which_cache = copz & 3;
1144     showtag = 0;
1145     debug("cache\t0x%02x,0x%04x(%s)", copz, imm,
1146     regname(cpu->machine, rt));
1147     if (which_cache==0) debug(" [ primary I-cache");
1148     if (which_cache==1) debug(" [ primary D-cache");
1149     if (which_cache==2) debug(" [ secondary I-cache");
1150     if (which_cache==3) debug(" [ secondary D-cache");
1151     debug(", ");
1152     if (cache_op==0) debug("index invalidate");
1153     if (cache_op==1) debug("index load tag");
1154     if (cache_op==2) debug("index store tag"), showtag=1;
1155     if (cache_op==3) debug("create dirty exclusive");
1156     if (cache_op==4) debug("hit invalidate");
1157     if (cache_op==5) debug("fill OR hit writeback invalidate");
1158     if (cache_op==6) debug("hit writeback");
1159     if (cache_op==7) debug("hit set virtual");
1160     if (running)
1161     debug(", addr 0x%016llx",
1162     (long long)(cpu->cd.mips.gpr[rt] + imm));
1163     if (showtag)
1164     debug(", taghi=%08lx lo=%08lx",
1165     (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_HI],
1166     (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_LO]);
1167     debug(" ]");
1168     break;
1169     case HI6_SPECIAL2:
1170     special6 = instr[0] & 0x3f;
1171     instrword = (instr[3] << 24) + (instr[2] << 16) +
1172     (instr[1] << 8) + instr[0];
1173     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1174     rt = instr[2] & 31;
1175     rd = (instr[1] >> 3) & 31;
1176     if ((instrword & 0xfc0007ffULL) == 0x70000000) {
1177     debug("madd\t%s", regname(cpu->machine, rd));
1178     debug(",%s", regname(cpu->machine, rs));
1179     debug(",%s", regname(cpu->machine, rt));
1180     } else if (special6 == SPECIAL2_MUL) {
1181     /* TODO: this is just a guess, I don't have the
1182     docs in front of me */
1183     debug("mul\t%s", regname(cpu->machine, rd));
1184     debug(",%s", regname(cpu->machine, rs));
1185     debug(",%s", regname(cpu->machine, rt));
1186     } else if (special6 == SPECIAL2_CLZ) {
1187     debug("clz\t%s", regname(cpu->machine, rd));
1188     debug(",%s", regname(cpu->machine, rs));
1189     } else if (special6 == SPECIAL2_CLO) {
1190     debug("clo\t%s", regname(cpu->machine, rd));
1191     debug(",%s", regname(cpu->machine, rs));
1192     } else if (special6 == SPECIAL2_DCLZ) {
1193     debug("dclz\t%s", regname(cpu->machine, rd));
1194     debug(",%s", regname(cpu->machine, rs));
1195     } else if (special6 == SPECIAL2_DCLO) {
1196     debug("dclo\t%s", regname(cpu->machine, rd));
1197     debug(",%s", regname(cpu->machine, rs));
1198     } else if ((instrword & 0xffff07ffULL) == 0x70000209
1199     || (instrword & 0xffff07ffULL) == 0x70000249) {
1200     if (instr[0] == 0x49) {
1201     debug("pmflo\t%s", regname(cpu->machine, rd));
1202     debug(" (rs=%s)", regname(cpu->machine, rs));
1203     } else {
1204     debug("pmfhi\t%s", regname(cpu->machine, rd));
1205     debug(" (rs=%s)", regname(cpu->machine, rs));
1206     }
1207     } else if ((instrword & 0xfc1fffff) == 0x70000269
1208     || (instrword & 0xfc1fffff) == 0x70000229) {
1209     if (instr[0] == 0x69) {
1210     debug("pmtlo\t%s", regname(cpu->machine, rs));
1211     } else {
1212     debug("pmthi\t%s", regname(cpu->machine, rs));
1213     }
1214     } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
1215     debug("por\t%s", regname(cpu->machine, rd));
1216     debug(",%s", regname(cpu->machine, rs));
1217     debug(",%s", regname(cpu->machine, rt));
1218     } else if ((instrword & 0xfc0007ff) == 0x70000488) {
1219     debug("pextlw\t%s", regname(cpu->machine, rd));
1220     debug(",%s", regname(cpu->machine, rs));
1221     debug(",%s", regname(cpu->machine, rt));
1222     } else {
1223     debug("unimplemented special2 = 0x%02x", special6);
1224     }
1225     break;
1226     case HI6_REGIMM:
1227     regimm5 = instr[2] & 0x1f;
1228     switch (regimm5) {
1229     case REGIMM_BLTZ:
1230     case REGIMM_BGEZ:
1231     case REGIMM_BLTZL:
1232     case REGIMM_BGEZL:
1233     case REGIMM_BLTZAL:
1234     case REGIMM_BLTZALL:
1235     case REGIMM_BGEZAL:
1236     case REGIMM_BGEZALL:
1237     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1238     imm = (instr[1] << 8) + instr[0];
1239     if (imm >= 32768)
1240     imm -= 65536;
1241    
1242     debug("%s\t%s,", regimm_names[regimm5],
1243     regname(cpu->machine, rs));
1244    
1245     addr = (dumpaddr + 4) + (imm << 2);
1246    
1247     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1248     cpu->cd.mips.cpu_type.isa_level == 32)
1249     debug("0x%08x", (int)addr);
1250     else
1251     debug("0x%016llx", (long long)addr);
1252     break;
1253     default:
1254     debug("unimplemented regimm5 = 0x%02x", regimm5);
1255     }
1256     break;
1257     default:
1258     debug("unimplemented hi6 = 0x%02x", hi6);
1259     }
1260    
1261     disasm_ret:
1262     debug("\n");
1263     return sizeof(instrword);
1264     }
1265    
1266    
1267     /*
1268     * mips_cpu_register_dump():
1269     *
1270     * Dump cpu registers in a relatively readable format.
1271     *
1272     * gprs: set to non-zero to dump GPRs and hi/lo/pc
1273     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
1274     */
1275     void mips_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
1276     {
1277     int coprocnr, i, bits32;
1278     uint64_t offset;
1279     char *symbol;
1280    
1281     bits32 = (cpu->cd.mips.cpu_type.isa_level < 3 ||
1282     cpu->cd.mips.cpu_type.isa_level == 32)? 1 : 0;
1283    
1284     if (gprs) {
1285     /* Special registers (pc, hi/lo) first: */
1286     symbol = get_symbol_name(&cpu->machine->symbol_context,
1287     cpu->pc, &offset);
1288    
1289     if (bits32)
1290     debug("cpu%i: pc = %08x", cpu->cpu_id, (int)cpu->pc);
1291     else
1292     debug("cpu%i: pc = %016llx",
1293     cpu->cpu_id, (long long)cpu->pc);
1294    
1295     debug(" <%s>\n", symbol != NULL? symbol :
1296     " no symbol ");
1297    
1298     if (bits32)
1299     debug("cpu%i: hi = %08x lo = %08x\n",
1300     cpu->cpu_id, (int)cpu->cd.mips.hi, (int)cpu->cd.mips.lo);
1301     else
1302     debug("cpu%i: hi = %016llx lo = %016llx\n",
1303     cpu->cpu_id, (long long)cpu->cd.mips.hi,
1304     (long long)cpu->cd.mips.lo);
1305    
1306     /* General registers: */
1307     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
1308     /* 128-bit: */
1309     for (i=0; i<32; i++) {
1310     if ((i & 1) == 0)
1311     debug("cpu%i:", cpu->cpu_id);
1312     debug(" %3s=%016llx%016llx",
1313     regname(cpu->machine, i),
1314     (long long)cpu->cd.mips.gpr_quadhi[i],
1315     (long long)cpu->cd.mips.gpr[i]);
1316     if ((i & 1) == 1)
1317     debug("\n");
1318     }
1319     } else if (bits32) {
1320     /* 32-bit: */
1321     for (i=0; i<32; i++) {
1322     if ((i & 3) == 0)
1323     debug("cpu%i:", cpu->cpu_id);
1324     debug(" %3s = %08x", regname(cpu->machine, i),
1325     (int)cpu->cd.mips.gpr[i]);
1326     if ((i & 3) == 3)
1327     debug("\n");
1328     }
1329     } else {
1330     /* 64-bit: */
1331     for (i=0; i<32; i++) {
1332     if ((i & 1) == 0)
1333     debug("cpu%i:", cpu->cpu_id);
1334     debug(" %3s = %016llx",
1335     regname(cpu->machine, i),
1336     (long long)cpu->cd.mips.gpr[i]);
1337     if ((i & 1) == 1)
1338     debug("\n");
1339     }
1340     }
1341     }
1342    
1343     for (coprocnr=0; coprocnr<4; coprocnr++) {
1344     int nm1 = 1;
1345    
1346     if (bits32)
1347     nm1 = 3;
1348    
1349     if (!(coprocs & (1<<coprocnr)))
1350     continue;
1351     if (cpu->cd.mips.coproc[coprocnr] == NULL) {
1352     debug("cpu%i: no coprocessor %i\n",
1353     cpu->cpu_id, coprocnr);
1354     continue;
1355     }
1356    
1357     /* Coprocessor registers: */
1358     /* TODO: multiple selections per register? */
1359     for (i=0; i<32; i++) {
1360     /* 32-bit: */
1361     if ((i & nm1) == 0)
1362     debug("cpu%i:", cpu->cpu_id);
1363    
1364     if (cpu->machine->show_symbolic_register_names &&
1365     coprocnr == 0)
1366     debug(" %8s", cop0_names[i]);
1367     else
1368     debug(" c%i,%02i", coprocnr, i);
1369    
1370     if (bits32)
1371     debug("=%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);
1372     else
1373     debug(" = 0x%016llx", (long long)
1374     cpu->cd.mips.coproc[coprocnr]->reg[i]);
1375    
1376     if ((i & nm1) == nm1)
1377     debug("\n");
1378    
1379     /* Skip the last 16 cop0 registers on R3000 etc. */
1380     if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level < 3
1381     && i == 15)
1382     i = 31;
1383     }
1384    
1385     /* Floating point control registers: */
1386     if (coprocnr == 1) {
1387     for (i=0; i<32; i++)
1388     switch (i) {
1389     case 0: printf("cpu%i: fcr0 (fcir) = 0x%08x\n",
1390     cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1391     break;
1392     case 25:printf("cpu%i: fcr25 (fccr) = 0x%08x\n",
1393     cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1394     break;
1395     case 31:printf("cpu%i: fcr31 (fcsr) = 0x%08x\n",
1396     cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1397     break;
1398     }
1399     }
1400     }
1401     }
1402    
1403    
1404     /*
1405     * show_trace():
1406     *
1407     * Show trace tree. This function should be called every time
1408     * a function is called. cpu->cd.mips.trace_tree_depth is increased here
1409     * and should not be increased by the caller.
1410     *
1411     * Note: This function should not be called if show_trace_tree == 0.
1412     */
1413     static void show_trace(struct cpu *cpu, uint64_t addr)
1414     {
1415     uint64_t offset;
1416     int x, n_args_to_print;
1417     char strbuf[50];
1418     char *symbol;
1419    
1420     cpu->cd.mips.trace_tree_depth ++;
1421    
1422     if (cpu->machine->ncpus > 1)
1423     debug("cpu%i:", cpu->cpu_id);
1424    
1425     symbol = get_symbol_name(&cpu->machine->symbol_context, addr, &offset);
1426    
1427     for (x=0; x<cpu->cd.mips.trace_tree_depth; x++)
1428     debug(" ");
1429    
1430     /* debug("<%s>\n", symbol!=NULL? symbol : "no symbol"); */
1431    
1432     if (symbol != NULL)
1433     debug("<%s(", symbol);
1434     else {
1435     debug("<0x");
1436     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1437     cpu->cd.mips.cpu_type.isa_level == 32)
1438     debug("%08x", (int)addr);
1439     else
1440     debug("%016llx", (long long)addr);
1441     debug("(");
1442     }
1443    
1444     /*
1445     * TODO: The number of arguments and the symbol type of each
1446     * argument should be taken from the symbol table, in some way.
1447     *
1448     * The MIPS binary calling convention is that the first 4
1449     * arguments are in registers a0..a3.
1450     *
1451     * Choose a value greater than 4 (eg 5) to print all values in
1452     * the A0..A3 registers and then add a ".." to indicate that
1453     * there might be more arguments.
1454     */
1455     n_args_to_print = 5;
1456    
1457     for (x=0; x<n_args_to_print; x++) {
1458     int64_t d = cpu->cd.mips.gpr[x + MIPS_GPR_A0];
1459    
1460     if (d > -256 && d < 256)
1461     debug("%i", (int)d);
1462     else if (memory_points_to_string(cpu, cpu->mem, d, 1))
1463     debug("\"%s\"", memory_conv_to_string(cpu,
1464     cpu->mem, d, strbuf, sizeof(strbuf)));
1465     else {
1466     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1467     cpu->cd.mips.cpu_type.isa_level == 32)
1468     debug("0x%x", (int)d);
1469     else
1470     debug("0x%llx", (long long)d);
1471     }
1472    
1473     if (x < n_args_to_print - 1)
1474     debug(",");
1475    
1476     /* Cannot go beyound MIPS_GPR_A3: */
1477     if (x == 3)
1478     break;
1479     }
1480    
1481     if (n_args_to_print > 4)
1482     debug("..");
1483    
1484     debug(")>\n");
1485     }
1486    
1487    
1488     /*
1489     * mips_cpu_interrupt():
1490     *
1491     * Cause an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1492     * interrupt. 0 and 1 are ignored (software interrupts).
1493     *
1494     * If irq_nr is >= 8, then this function calls md_interrupt().
1495     */
1496     int mips_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
1497     {
1498     if (irq_nr >= 8) {
1499     if (cpu->machine->md_interrupt != NULL)
1500     cpu->machine->md_interrupt(cpu->machine, cpu, irq_nr, 1);
1501     else
1502     fatal("mips_cpu_interrupt(): irq_nr = %i, but md_interrupt = NULL ?\n", irq_nr);
1503     return 1;
1504     }
1505    
1506     if (irq_nr < 2)
1507     return 0;
1508    
1509     cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |= ((1 << irq_nr) << STATUS_IM_SHIFT);
1510     cpu->cd.mips.cached_interrupt_is_possible = 1;
1511     return 1;
1512     }
1513    
1514    
1515     /*
1516     * mips_cpu_interrupt_ack():
1517     *
1518     * Acknowledge an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1519     * interrupt. Interrupts 0..1 are ignored (software interrupts).
1520     *
1521     * If irq_nr is >= 8, then it is machine dependant, and md_interrupt() is
1522     * called.
1523     */
1524     int mips_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
1525     {
1526     if (irq_nr >= 8) {
1527     if (cpu->machine->md_interrupt != NULL)
1528     cpu->machine->md_interrupt(cpu->machine, cpu, irq_nr, 0);
1529     else
1530     fatal("mips_cpu_interrupt_ack(): irq_nr = %i, but md_interrupt = NULL ?\n", irq_nr);
1531     return 1;
1532     }
1533    
1534     if (irq_nr < 2)
1535     return 0;
1536    
1537     cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &= ~((1 << irq_nr) << STATUS_IM_SHIFT);
1538     if (!(cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] & STATUS_IM_MASK))
1539     cpu->cd.mips.cached_interrupt_is_possible = 0;
1540    
1541     return 1;
1542     }
1543    
1544    
1545     /*
1546     * mips_cpu_exception():
1547     *
1548     * Cause an exception in a CPU. This sets a couple of coprocessor 0
1549     * registers, and the program counter.
1550     *
1551     * exccode the exception code
1552     * tlb set to non-zero if the exception handler at
1553     * 0x80000000 should be used. (normal = 0x80000180)
1554     * vaddr virtual address (for some exceptions)
1555     * coproc_nr coprocessor number (for some exceptions)
1556     * vaddr_vpn2 vpn2 (for some exceptions)
1557     * vaddr_asid asid (for some exceptions)
1558     * x_64 non-zero for 64-bit mode for R4000-style tlb misses
1559     */
1560     void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr,
1561     int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64)
1562     {
1563     uint64_t base;
1564     uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];
1565     int exc_model = cpu->cd.mips.cpu_type.exc_model;
1566    
1567     if (!quiet_mode) {
1568     uint64_t offset;
1569     int x;
1570     char *symbol = get_symbol_name(
1571     &cpu->machine->symbol_context, cpu->cd.mips.pc_last, &offset);
1572    
1573     debug("[ ");
1574     if (cpu->machine->ncpus > 1)
1575     debug("cpu%i: ", cpu->cpu_id);
1576    
1577     debug("exception %s%s",
1578     exception_names[exccode], tlb? " <tlb>" : "");
1579    
1580     switch (exccode) {
1581     case EXCEPTION_INT:
1582     debug(" cause_im=0x%02x", (int)((reg[COP0_CAUSE] & CAUSE_IP_MASK) >> CAUSE_IP_SHIFT));
1583     break;
1584     case EXCEPTION_SYS:
1585     debug(" v0=%i", (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1586     for (x=0; x<4; x++) {
1587     int64_t d = cpu->cd.mips.gpr[MIPS_GPR_A0 + x];
1588     char strbuf[30];
1589    
1590     if (d > -256 && d < 256)
1591     debug(" a%i=%i", x, (int)d);
1592     else if (memory_points_to_string(cpu, cpu->mem, d, 1))
1593     debug(" a%i=\"%s\"", x, memory_conv_to_string(cpu, cpu->mem, d, strbuf, sizeof(strbuf)));
1594     else
1595     debug(" a%i=0x%llx", x, (long long)d);
1596     }
1597     break;
1598     default:
1599     debug(" vaddr=0x%016llx", (long long)vaddr);
1600     }
1601    
1602     debug(" pc=%08llx ", (long long)cpu->cd.mips.pc_last);
1603    
1604     if (symbol != NULL)
1605     debug("<%s> ]\n", symbol);
1606     else
1607     debug("]\n");
1608     }
1609    
1610     if (tlb && vaddr < 0x1000) {
1611     uint64_t offset;
1612 dpavlin 4 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1613     cpu->cd.mips.pc_last, &offset);
1614 dpavlin 6 fatal("[ ");
1615     if (cpu->machine->ncpus > 1)
1616     fatal("cpu%i: ", cpu->cpu_id);
1617     fatal("warning: LOW reference vaddr=0x%08llx, exception %s, "
1618     "pc=%08llx <%s> ]\n", (long long)vaddr,
1619     exception_names[exccode], (long long)cpu->cd.mips.pc_last,
1620 dpavlin 4 symbol? symbol : "(no symbol)");
1621 dpavlin 8
1622     #ifdef TRACE_NULL_CRASHES
1623     /* This can be useful for debugging kernel bugs: */
1624     {
1625     int i = cpu->trace_null_index;
1626     do {
1627     fatal("TRACE: 0x%016llx\n",
1628     cpu->trace_null_addr[i]);
1629     i ++;
1630     i %= TRACE_NULL_N_ENTRIES;
1631     } while (i != cpu->trace_null_index);
1632     }
1633     cpu->running = 0;
1634     cpu->dead = 1;
1635     #endif
1636 dpavlin 2 }
1637    
1638     /* Clear the exception code bits of the cause register... */
1639     if (exc_model == EXC3K) {
1640     reg[COP0_CAUSE] &= ~R2K3K_CAUSE_EXCCODE_MASK;
1641     #if 0
1642     if (exccode >= 16) {
1643     fatal("exccode = %i (there are only 16 exceptions on R3000 and lower)\n", exccode);
1644     cpu->running = 0;
1645     return;
1646     }
1647     #endif
1648     } else
1649     reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
1650    
1651     /* ... and OR in the exception code: */
1652     reg[COP0_CAUSE] |= (exccode << CAUSE_EXCCODE_SHIFT);
1653    
1654     /* Always set CE (according to the R5000 manual): */
1655     reg[COP0_CAUSE] &= ~CAUSE_CE_MASK;
1656     reg[COP0_CAUSE] |= (coproc_nr << CAUSE_CE_SHIFT);
1657    
1658     /* TODO: On R4000, vaddr should NOT be set on bus errors!!! */
1659     #if 0
1660     if (exccode == EXCEPTION_DBE) {
1661     reg[COP0_BADVADDR] = vaddr;
1662     /* sign-extend vaddr, if it is 32-bit */
1663     if ((vaddr >> 32) == 0 && (vaddr & 0x80000000ULL))
1664     reg[COP0_BADVADDR] |=
1665     0xffffffff00000000ULL;
1666     }
1667     #endif
1668    
1669     if (tlb || (exccode >= EXCEPTION_MOD && exccode <= EXCEPTION_ADES) ||
1670     exccode == EXCEPTION_VCEI || exccode == EXCEPTION_VCED) {
1671     reg[COP0_BADVADDR] = vaddr;
1672     #if 1
1673     /* TODO: This should be removed. */
1674     /* sign-extend vaddr, if it is 32-bit */
1675     if ((vaddr >> 32) == 0 && (vaddr & 0x80000000ULL))
1676     reg[COP0_BADVADDR] |=
1677     0xffffffff00000000ULL;
1678     #endif
1679     if (exc_model == EXC3K) {
1680     reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
1681     reg[COP0_CONTEXT] |= ((vaddr_vpn2 << R2K3K_CONTEXT_BADVPN_SHIFT) & R2K3K_CONTEXT_BADVPN_MASK);
1682    
1683     reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)
1684     | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);
1685    
1686     /* Sign-extend: */
1687     reg[COP0_CONTEXT] = (int64_t)(int32_t)reg[COP0_CONTEXT];
1688     reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];
1689     } else {
1690     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1691     reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK_R4100;
1692     reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK_R4100);
1693    
1694     /* TODO: fix these */
1695     reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1696     reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1697     reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1698     reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1699    
1700     /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1701    
1702     reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800)) | vaddr_asid;
1703     } else {
1704     reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK;
1705     reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK);
1706    
1707     reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1708     reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1709     reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1710     reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1711    
1712     /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1713    
1714     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1715     reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K)) | vaddr_asid;
1716     else
1717     reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK)) | vaddr_asid;
1718     }
1719     }
1720     }
1721    
1722     if (exc_model == EXC4K && reg[COP0_STATUS] & STATUS_EXL) {
1723     /*
1724     * Don't set EPC if STATUS_EXL is set, for R4000 and up.
1725     * This actually happens when running IRIX and Ultrix, when
1726     * they handle interrupts and/or tlb updates, I think, so
1727     * printing this with debug() looks better than with fatal().
1728     */
1729     /* debug("[ warning: cpu%i exception while EXL is set, not setting EPC ]\n", cpu->cpu_id); */
1730     } else {
1731     if (cpu->cd.mips.delay_slot || cpu->cd.mips.nullify_next) {
1732     reg[COP0_EPC] = cpu->cd.mips.pc_last - 4;
1733     reg[COP0_CAUSE] |= CAUSE_BD;
1734    
1735     /* TODO: Should the BD flag actually be set
1736     on nullified slots? */
1737     } else {
1738     reg[COP0_EPC] = cpu->cd.mips.pc_last;
1739     reg[COP0_CAUSE] &= ~CAUSE_BD;
1740     }
1741     }
1742    
1743     cpu->cd.mips.delay_slot = NOT_DELAYED;
1744     cpu->cd.mips.nullify_next = 0;
1745    
1746     /* TODO: This is true for MIPS64, but how about others? */
1747     if (reg[COP0_STATUS] & STATUS_BEV)
1748     base = 0xffffffffbfc00200ULL;
1749     else
1750     base = 0xffffffff80000000ULL;
1751    
1752     switch (exc_model) {
1753     case EXC3K:
1754     /* Userspace tlb, vs others: */
1755     if (tlb && !(vaddr & 0x80000000ULL) &&
1756     (exccode == EXCEPTION_TLBL || exccode == EXCEPTION_TLBS) )
1757     cpu->pc = base + 0x000;
1758     else
1759     cpu->pc = base + 0x080;
1760     break;
1761     default:
1762     /*
1763     * These offsets are according to the MIPS64 manual, but
1764     * should work with R4000 and the rest too (I hope).
1765     *
1766     * 0x000 TLB refill, if EXL=0
1767     * 0x080 64-bit XTLB refill, if EXL=0
1768     * 0x100 cache error (not implemented yet)
1769     * 0x180 general exception
1770     * 0x200 interrupt (if CAUSE_IV is set)
1771     */
1772     if (tlb && (exccode == EXCEPTION_TLBL ||
1773     exccode == EXCEPTION_TLBS) &&
1774     !(reg[COP0_STATUS] & STATUS_EXL)) {
1775     if (x_64)
1776     cpu->pc = base + 0x080;
1777     else
1778     cpu->pc = base + 0x000;
1779     } else {
1780     if (exccode == EXCEPTION_INT &&
1781     (reg[COP0_CAUSE] & CAUSE_IV))
1782     cpu->pc = base + 0x200;
1783     else
1784     cpu->pc = base + 0x180;
1785     }
1786     }
1787    
1788     if (exc_model == EXC3K) {
1789     /* R2000/R3000: Shift the lowest 6 bits to the left two steps: */
1790     reg[COP0_STATUS] =
1791     (reg[COP0_STATUS] & ~0x3f) +
1792     ((reg[COP0_STATUS] & 0xf) << 2);
1793     } else {
1794     /* R4000: */
1795     reg[COP0_STATUS] |= STATUS_EXL;
1796     }
1797    
1798     /* Sign-extend: */
1799     reg[COP0_CAUSE] = (int64_t)(int32_t)reg[COP0_CAUSE];
1800     reg[COP0_STATUS] = (int64_t)(int32_t)reg[COP0_STATUS];
1801     }
1802    
1803    
1804     #ifdef BINTRANS
1805     /*
1806     * mips_cpu_cause_simple_exception():
1807     *
1808     * Useful for causing raw exceptions from bintrans, for example
1809     * SYSCALL or BREAK.
1810     */
1811     void mips_cpu_cause_simple_exception(struct cpu *cpu, int exc_code)
1812     {
1813     mips_cpu_exception(cpu, exc_code, 0, 0, 0, 0, 0, 0);
1814     }
1815     #endif
1816    
1817    
1818     /* Included here for better cache characteristics: */
1819     #include "memory_mips.c"
1820    
1821    
1822     /*
1823     * mips_cpu_run_instr():
1824     *
1825     * Execute one instruction on a cpu.
1826     *
1827     * If we are in a delay slot, set cpu->pc to cpu->cd.mips.delay_jmpaddr
1828     * after the instruction is executed.
1829     *
1830     * Return value is the number of instructions executed during this call,
1831     * 0 if no instruction was executed.
1832     */
1833     int mips_cpu_run_instr(struct emul *emul, struct cpu *cpu)
1834     {
1835     int quiet_mode_cached = quiet_mode;
1836     int instruction_trace_cached = cpu->machine->instruction_trace;
1837     struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
1838     int i, tmp, ninstrs_executed;
1839     unsigned char instr[4];
1840     uint32_t instrword;
1841     uint64_t cached_pc;
1842     int hi6, special6, regimm5, rd, rs, rt, sa, imm;
1843     int copz, which_cache, cache_op;
1844    
1845     int cond, likely, and_link;
1846    
1847     /* for unaligned load/store */
1848     uint64_t dir, is_left, reg_ofs, reg_dir;
1849    
1850     uint64_t tmpvalue, tmpaddr;
1851    
1852     int cpnr; /* coprocessor nr */
1853    
1854     /* for load/store */
1855     uint64_t addr, value, value_hi, result_value;
1856     int wlen, st, signd, linked;
1857     unsigned char d[16]; /* room for at most 128 bits */
1858    
1859    
1860     /*
1861     * Update Coprocessor 0 registers:
1862     *
1863     * The COUNT register needs to be updated on every [other] instruction.
1864     * The RANDOM register should decrease for every instruction.
1865     */
1866    
1867     if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1868     int r = (cp0->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK) >> R2K3K_RANDOM_SHIFT;
1869     r --;
1870     if (r >= cp0->nr_of_tlbs || r < 8)
1871     r = cp0->nr_of_tlbs-1;
1872     cp0->reg[COP0_RANDOM] = r << R2K3K_RANDOM_SHIFT;
1873     } else {
1874     cp0->reg[COP0_RANDOM] --;
1875     if ((int64_t)cp0->reg[COP0_RANDOM] >= cp0->nr_of_tlbs ||
1876     (int64_t)cp0->reg[COP0_RANDOM] < (int64_t) cp0->reg[COP0_WIRED])
1877     cp0->reg[COP0_RANDOM] = cp0->nr_of_tlbs-1;
1878    
1879     /*
1880     * TODO: only increase count every other instruction,
1881     * according to the R4000 manual. But according to the
1882     * R5000 manual: increment every other clock cycle.
1883     * Which one is it? :-)
1884     */
1885     cp0->reg[COP0_COUNT] = (int64_t)(int32_t)(cp0->reg[COP0_COUNT] + 1);
1886    
1887     if (cpu->cd.mips.compare_register_set &&
1888     cp0->reg[COP0_COUNT] == cp0->reg[COP0_COMPARE]) {
1889     mips_cpu_interrupt(cpu, 7);
1890     cpu->cd.mips.compare_register_set = 0;
1891     }
1892     }
1893    
1894    
1895     #ifdef ENABLE_INSTRUCTION_DELAYS
1896     if (cpu->cd.mips.instruction_delay > 0) {
1897     cpu->cd.mips.instruction_delay --;
1898     return 1;
1899     }
1900     #endif
1901    
1902     /* Cache the program counter in a local variable: */
1903     cached_pc = cpu->pc;
1904    
1905 dpavlin 8 #ifdef TRACE_NULL_CRASHES
1906     cpu->trace_null_addr[cpu->trace_null_index] = cached_pc;
1907     cpu->trace_null_index ++;
1908     cpu->trace_null_index %= TRACE_NULL_N_ENTRIES;
1909     #endif
1910    
1911 dpavlin 2 /* Hardwire the zero register to 0: */
1912     cpu->cd.mips.gpr[MIPS_GPR_ZERO] = 0;
1913    
1914     if (cpu->cd.mips.delay_slot) {
1915     if (cpu->cd.mips.delay_slot == DELAYED) {
1916     cached_pc = cpu->pc = cpu->cd.mips.delay_jmpaddr;
1917     cpu->cd.mips.delay_slot = NOT_DELAYED;
1918     } else /* if (cpu->cd.mips.delay_slot == TO_BE_DELAYED) */ {
1919     /* next instruction will be delayed */
1920     cpu->cd.mips.delay_slot = DELAYED;
1921     }
1922     }
1923    
1924     if (cpu->cd.mips.last_was_jumptoself > 0)
1925     cpu->cd.mips.last_was_jumptoself --;
1926    
1927     /* Check PC against breakpoints: */
1928     if (!single_step)
1929     for (i=0; i<cpu->machine->n_breakpoints; i++)
1930     if (cached_pc == cpu->machine->breakpoint_addr[i]) {
1931     fatal("Breakpoint reached, pc=0x");
1932     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1933     cpu->cd.mips.cpu_type.isa_level == 32)
1934     fatal("%08x", (int)cached_pc);
1935     else
1936     fatal("%016llx", (long long)cached_pc);
1937     fatal("\n");
1938     single_step = 1;
1939     return 0;
1940     }
1941    
1942    
1943     /* Remember where we are, in case of interrupt or exception: */
1944     cpu->cd.mips.pc_last = cached_pc;
1945    
1946     /*
1947     * Any pending interrupts?
1948     *
1949     * If interrupts are enabled, and any interrupt has arrived (ie its
1950     * bit in the cause register is set) and corresponding enable bits
1951     * in the status register are set, then cause an interrupt exception
1952     * instead of executing the current instruction.
1953     *
1954     * NOTE: cached_interrupt_is_possible is set to 1 whenever an
1955     * interrupt bit in the cause register is set to one (in
1956     * mips_cpu_interrupt()) and set to 0 whenever all interrupt bits are
1957     * cleared (in mips_cpu_interrupt_ack()), so we don't need to do a
1958     * full check each time.
1959     */
1960     if (cpu->cd.mips.cached_interrupt_is_possible && !cpu->cd.mips.nullify_next) {
1961     if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1962     /* R3000: */
1963     int enabled, mask;
1964     int status = cp0->reg[COP0_STATUS];
1965    
1966     enabled = status & MIPS_SR_INT_IE;
1967     mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1968     if (enabled && mask) {
1969     mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1970     return 0;
1971     }
1972     } else {
1973     /* R4000 and others: */
1974     int enabled, mask;
1975     int status = cp0->reg[COP0_STATUS];
1976    
1977     enabled = (status & STATUS_IE)
1978     && !(status & STATUS_EXL)
1979     && !(status & STATUS_ERL);
1980    
1981     mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1982     if (enabled && mask) {
1983     mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1984     return 0;
1985     }
1986     }
1987     }
1988    
1989    
1990     /*
1991     * ROM emulation:
1992     *
1993     * This assumes that a jal was made to a ROM address,
1994     * and we should return via gpr ra.
1995     */
1996     if ((cached_pc & 0xfff00000) == 0xbfc00000 &&
1997     cpu->machine->prom_emulation) {
1998     int rom_jal, res = 1;
1999     switch (cpu->machine->machine_type) {
2000     case MACHINE_DEC:
2001     res = decstation_prom_emul(cpu);
2002     rom_jal = 1;
2003     break;
2004     case MACHINE_PS2:
2005     res = playstation2_sifbios_emul(cpu);
2006     rom_jal = 1;
2007     break;
2008     case MACHINE_ARC:
2009     case MACHINE_SGI:
2010     res = arcbios_emul(cpu);
2011     rom_jal = 1;
2012     break;
2013     default:
2014     rom_jal = 0;
2015     }
2016    
2017     if (rom_jal) {
2018     /*
2019     * Special hack: If the PROM emulation layer needs
2020     * to loop (for example when emulating blocking
2021     * console input) then we should simply return, so
2022     * that the same PROM routine is called on the next
2023     * round as well.
2024     *
2025     * This still has to count as one or more
2026     * instructions, so 1000 is returned. (Ugly.)
2027     */
2028     if (!res)
2029     return 1000;
2030    
2031     cpu->pc = cpu->cd.mips.gpr[MIPS_GPR_RA];
2032     /* no need to update cached_pc, as we're returning */
2033     cpu->cd.mips.delay_slot = NOT_DELAYED;
2034    
2035     if (!quiet_mode_cached &&
2036     cpu->machine->show_trace_tree)
2037     cpu->cd.mips.trace_tree_depth --;
2038    
2039     /* TODO: how many instrs should this count as? */
2040     return 10;
2041     }
2042     }
2043    
2044     #ifdef ALWAYS_SIGNEXTEND_32
2045     /*
2046     * An extra check for 32-bit mode to make sure that all
2047     * registers are sign-extended: (Slow, but might be useful
2048     * to detect bugs that have to do with sign-extension.)
2049     */
2050     if (cpu->cd.mips.cpu_type.isa_level < 3 || cpu->cd.mips.cpu_type.isa_level == 32) {
2051     int warning = 0;
2052     uint64_t x;
2053    
2054     if (cpu->cd.mips.gpr[0] != 0) {
2055     fatal("\nWARNING: r0 was not zero! (%016llx)\n\n",
2056     (long long)cpu->cd.mips.gpr[0]);
2057     cpu->cd.mips.gpr[0] = 0;
2058     warning = 1;
2059     }
2060    
2061     if (cpu->pc != (int64_t)(int32_t)cpu->pc) {
2062     fatal("\nWARNING: pc was not sign-extended correctly"
2063     " (%016llx)\n\n", (long long)cpu->pc);
2064     cpu->pc = (int64_t)(int32_t)cpu->pc;
2065     warning = 1;
2066     }
2067    
2068     if (cpu->cd.mips.pc_last != (int64_t)(int32_t)cpu->cd.mips.pc_last) {
2069     fatal("\nWARNING: pc_last was not sign-extended correc"
2070     "tly (%016llx)\n\n", (long long)cpu->cd.mips.pc_last);
2071     cpu->cd.mips.pc_last = (int64_t)(int32_t)cpu->cd.mips.pc_last;
2072     warning = 1;
2073     }
2074    
2075     /* Sign-extend ALL registers, including coprocessor registers and tlbs: */
2076     for (i=1; i<32; i++) {
2077     x = cpu->cd.mips.gpr[i];
2078     cpu->cd.mips.gpr[i] &= 0xffffffff;
2079     if (cpu->cd.mips.gpr[i] & 0x80000000ULL)
2080     cpu->cd.mips.gpr[i] |= 0xffffffff00000000ULL;
2081     if (x != cpu->cd.mips.gpr[i]) {
2082     fatal("\nWARNING: r%i (%s) was not sign-"
2083     "extended correctly (%016llx != "
2084     "%016llx)\n\n", i, regname(cpu->machine, i),
2085     (long long)x, (long long)cpu->cd.mips.gpr[i]);
2086     warning = 1;
2087     }
2088     }
2089     for (i=0; i<32; i++) {
2090     x = cpu->cd.mips.coproc[0]->reg[i];
2091     cpu->cd.mips.coproc[0]->reg[i] &= 0xffffffffULL;
2092     if (cpu->cd.mips.coproc[0]->reg[i] & 0x80000000ULL)
2093     cpu->cd.mips.coproc[0]->reg[i] |=
2094     0xffffffff00000000ULL;
2095     if (x != cpu->cd.mips.coproc[0]->reg[i]) {
2096     fatal("\nWARNING: cop0,r%i was not sign-extended correctly (%016llx != %016llx)\n\n",
2097     i, (long long)x, (long long)cpu->cd.mips.coproc[0]->reg[i]);
2098     warning = 1;
2099     }
2100     }
2101     for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
2102     x = cpu->cd.mips.coproc[0]->tlbs[i].hi;
2103     cpu->cd.mips.coproc[0]->tlbs[i].hi &= 0xffffffffULL;
2104     if (cpu->cd.mips.coproc[0]->tlbs[i].hi & 0x80000000ULL)
2105     cpu->cd.mips.coproc[0]->tlbs[i].hi |=
2106     0xffffffff00000000ULL;
2107     if (x != cpu->cd.mips.coproc[0]->tlbs[i].hi) {
2108     fatal("\nWARNING: tlb[%i].hi was not sign-extended correctly (%016llx != %016llx)\n\n",
2109     i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].hi);
2110     warning = 1;
2111     }
2112    
2113     x = cpu->cd.mips.coproc[0]->tlbs[i].lo0;
2114     cpu->cd.mips.coproc[0]->tlbs[i].lo0 &= 0xffffffffULL;
2115     if (cpu->cd.mips.coproc[0]->tlbs[i].lo0 & 0x80000000ULL)
2116     cpu->cd.mips.coproc[0]->tlbs[i].lo0 |=
2117     0xffffffff00000000ULL;
2118     if (x != cpu->cd.mips.coproc[0]->tlbs[i].lo0) {
2119     fatal("\nWARNING: tlb[%i].lo0 was not sign-extended correctly (%016llx != %016llx)\n\n",
2120     i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].lo0);
2121     warning = 1;
2122     }
2123     }
2124    
2125     if (warning) {
2126     fatal("Halting. pc = %016llx\n", (long long)cpu->pc);
2127     cpu->running = 0;
2128     }
2129     }
2130     #endif
2131    
2132     PREFETCH(cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff));
2133    
2134     #ifdef HALT_IF_PC_ZERO
2135     /* Halt if PC = 0: */
2136     if (cached_pc == 0) {
2137     debug("cpu%i: pc=0, halting\n", cpu->cpu_id);
2138     cpu->running = 0;
2139     return 0;
2140     }
2141     #endif
2142    
2143    
2144    
2145     #ifdef BINTRANS
2146 dpavlin 4 if ((single_step || instruction_trace_cached)
2147 dpavlin 2 && cpu->machine->bintrans_enable)
2148     cpu->cd.mips.dont_run_next_bintrans = 1;
2149     #endif
2150    
2151    
2152     if (!quiet_mode_cached) {
2153     /* Dump CPU registers for debugging: */
2154     if (cpu->machine->register_dump) {
2155     debug("\n");
2156     mips_cpu_register_dump(cpu, 1, 0x1);
2157     }
2158    
2159     /* Trace tree: */
2160     if (cpu->machine->show_trace_tree && cpu->cd.mips.show_trace_delay > 0) {
2161     cpu->cd.mips.show_trace_delay --;
2162     if (cpu->cd.mips.show_trace_delay == 0)
2163     show_trace(cpu, cpu->cd.mips.show_trace_addr);
2164     }
2165     }
2166    
2167     #ifdef MFHILO_DELAY
2168     /* Decrease the MFHI/MFLO delays: */
2169     if (cpu->mfhi_delay > 0)
2170     cpu->mfhi_delay--;
2171     if (cpu->mflo_delay > 0)
2172     cpu->mflo_delay--;
2173     #endif
2174    
2175     /* Read an instruction from memory: */
2176     #ifdef ENABLE_MIPS16
2177     if (cpu->cd.mips.mips16 && (cached_pc & 1)) {
2178     /* 16-bit instruction word: */
2179     unsigned char instr16[2];
2180     int mips16_offset = 0;
2181    
2182     if (!cpu->memory_rw(cpu, cpu->mem, cached_pc ^ 1, &instr16[0],
2183     sizeof(instr16), MEM_READ, CACHE_INSTRUCTION))
2184     return 0;
2185    
2186     /* TODO: If Reverse-endian is set in the status cop0 register, and
2187     we are in usermode, then reverse endianness! */
2188    
2189     /* The rest of the code is written for little endian, so swap if necessary: */
2190     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2191     int tmp;
2192     tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2193     }
2194    
2195     cpu->cd.mips.mips16_extend = 0;
2196    
2197     /*
2198     * Translate into 32-bit instruction, little endian (instr[3..0]):
2199     *
2200     * This ugly loop is necessary because if we would get an exception between
2201     * reading an extend instruction and the next instruction, and execution
2202     * continues on the second instruction, the extend data would be lost. So the
2203     * entire instruction (the two parts) need to be read in. If an exception is
2204     * caused, it will appear as if it was caused when reading the extend instruction.
2205     */
2206     while (mips16_to_32(cpu, instr16, instr) == 0) {
2207     if (instruction_trace_cached)
2208     debug("cpu%i @ %016llx: %02x%02x\t\t\textend\n",
2209     cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2210     instr16[1], instr16[0]);
2211    
2212     /* instruction with extend: */
2213     mips16_offset += 2;
2214     if (!cpu->memory_rw(cpu, cpu->mem, (cached_pc ^ 1) +
2215     mips16_offset, &instr16[0], sizeof(instr16),
2216     MEM_READ, CACHE_INSTRUCTION))
2217     return 0;
2218    
2219     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2220     int tmp;
2221     tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2222     }
2223     }
2224    
2225     /* TODO: bintrans like in 32-bit mode? */
2226    
2227     /* Advance the program counter: */
2228     cpu->pc += sizeof(instr16) + mips16_offset;
2229     cached_pc = cpu->pc;
2230    
2231     if (instruction_trace_cached) {
2232     uint64_t offset;
2233     char *symbol = get_symbol_name(&cpu->machine->
2234     symbol_context, cpu->cd.mips.pc_last ^ 1, &offset);
2235     if (symbol != NULL && offset==0)
2236     debug("<%s>\n", symbol);
2237    
2238     debug("cpu%i @ %016llx: %02x%02x => %02x%02x%02x%02x%s\t",
2239     cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2240     instr16[1], instr16[0],
2241     instr[3], instr[2], instr[1], instr[0],
2242     cpu_flags(cpu));
2243     }
2244     } else
2245     #endif
2246     {
2247     /*
2248     * Fetch a 32-bit instruction word from memory:
2249     *
2250     * 1) The special case of reading an instruction from the
2251     * same host RAM page as the last one is handled here,
2252     * to gain a little bit performance.
2253     *
2254     * 2) Fallback to reading from memory the usual way.
2255     */
2256     if (cpu->cd.mips.pc_last_host_4k_page != NULL &&
2257     (cached_pc & ~0xfff) == cpu->cd.mips.pc_last_virtual_page) {
2258     /* NOTE: This only works on the host if offset is
2259     aligned correctly! (TODO) */
2260     *(uint32_t *)instr = *(uint32_t *)
2261     (cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff));
2262     #ifdef BINTRANS
2263     cpu->cd.mips.pc_bintrans_paddr_valid = 1;
2264     cpu->cd.mips.pc_bintrans_paddr =
2265     cpu->cd.mips.pc_last_physical_page | (cached_pc & 0xfff);
2266     cpu->cd.mips.pc_bintrans_host_4kpage = cpu->cd.mips.pc_last_host_4k_page;
2267     #endif
2268     } else {
2269     if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
2270     sizeof(instr), MEM_READ, CACHE_INSTRUCTION))
2271     return 0;
2272     }
2273    
2274     #ifdef BINTRANS
2275     if (cpu->cd.mips.dont_run_next_bintrans) {
2276     cpu->cd.mips.dont_run_next_bintrans = 0;
2277     } else if (cpu->machine->bintrans_enable &&
2278     cpu->cd.mips.pc_bintrans_paddr_valid) {
2279     int res;
2280     cpu->cd.mips.bintrans_instructions_executed = 0;
2281    
2282     res = bintrans_attempt_translate(cpu,
2283     cpu->cd.mips.pc_bintrans_paddr);
2284    
2285     if (res >= 0) {
2286     /* debug("BINTRANS translation + hit,"
2287     " pc = %016llx\n", (long long)cached_pc); */
2288     if (res > 0 || cpu->pc != cached_pc) {
2289     if (instruction_trace_cached)
2290     mips_cpu_disassemble_instr(cpu, instr, 1, 0, 1);
2291     if (res & BINTRANS_DONT_RUN_NEXT)
2292     cpu->cd.mips.dont_run_next_bintrans = 1;
2293     res &= BINTRANS_N_MASK;
2294    
2295     if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2296     int x = cp0->reg[COP0_COUNT], y = cp0->reg[COP0_COMPARE];
2297     int diff = x - y;
2298     if (diff < 0 && diff + (res-1) >= 0
2299     && cpu->cd.mips.compare_register_set) {
2300     mips_cpu_interrupt(cpu, 7);
2301     cpu->cd.mips.compare_register_set = 0;
2302     }
2303    
2304     cp0->reg[COP0_COUNT] = (int64_t)
2305     (int32_t)(cp0->reg[COP0_COUNT] + res-1);
2306     }
2307    
2308     return res;
2309     }
2310     }
2311     }
2312     #endif
2313    
2314     if (instruction_trace_cached)
2315     mips_cpu_disassemble_instr(cpu, instr, 1, 0, 0);
2316    
2317     /* Advance the program counter: */
2318     cpu->pc += sizeof(instr);
2319     cached_pc = cpu->pc;
2320    
2321     /*
2322     * TODO: If Reverse-endian is set in the status cop0 register
2323     * and we are in usermode, then reverse endianness!
2324     */
2325    
2326     /*
2327     * The rest of the code is written for little endian, so
2328     * swap if necessary:
2329     */
2330     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2331     instrword = instr[0]; instr[0] = instr[3];
2332     instr[3] = instrword;
2333     instrword = instr[1]; instr[1] = instr[2];
2334     instr[2] = instrword;
2335     }
2336     }
2337    
2338    
2339     /*
2340     * Nullify this instruction? (Set by a previous branch-likely
2341     * instruction.)
2342     *
2343     * Note: The return value is 1, even if no instruction was actually
2344     * executed.
2345     */
2346     if (cpu->cd.mips.nullify_next) {
2347     cpu->cd.mips.nullify_next = 0;
2348     return 1;
2349     }
2350    
2351    
2352     /*
2353     * Execute the instruction:
2354     */
2355    
2356     /* Get the top 6 bits of the instruction: */
2357     hi6 = instr[3] >> 2; /* & 0x3f */
2358    
2359     if (show_opcode_statistics)
2360     cpu->cd.mips.stats_opcode[hi6] ++;
2361    
2362     switch (hi6) {
2363     case HI6_SPECIAL:
2364     special6 = instr[0] & 0x3f;
2365    
2366     if (show_opcode_statistics)
2367     cpu->cd.mips.stats__special[special6] ++;
2368    
2369     switch (special6) {
2370     case SPECIAL_SLL:
2371     case SPECIAL_SRL:
2372     case SPECIAL_SRA:
2373     case SPECIAL_DSLL:
2374     case SPECIAL_DSRL:
2375     case SPECIAL_DSRA:
2376     case SPECIAL_DSLL32:
2377     case SPECIAL_DSRL32:
2378     case SPECIAL_DSRA32:
2379     rt = instr[2] & 31;
2380     rd = (instr[1] >> 3) & 31;
2381     sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
2382    
2383     /*
2384     * Check for NOP:
2385     *
2386     * The R4000 manual says that a shift amount of zero
2387     * is treated as a nop by some assemblers. Checking
2388     * for sa == 0 here would not be correct, though,
2389     * because instructions such as sll r3,r4,0 are
2390     * possible, and are definitely not a nop.
2391     * Instead, check if the destination register is r0.
2392     *
2393     * TODO: ssnop should wait until the _next_
2394     * cycle boundary, or something like that. The
2395     * code here is incorrect.
2396     */
2397     if (rd == 0 && special6 == SPECIAL_SLL) {
2398     if (sa == 1) {
2399     /* ssnop */
2400     #ifdef ENABLE_INSTRUCTION_DELAYS
2401     cpu->cd.mips.instruction_delay +=
2402     cpu->cd.mips.cpu_type.
2403     instrs_per_cycle - 1;
2404     #endif
2405     }
2406     return 1;
2407     }
2408    
2409     if (special6 == SPECIAL_SLL) {
2410     switch (sa) {
2411     case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 8; break;
2412     case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 16; break;
2413     default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2414     }
2415     /* Sign-extend rd: */
2416     cpu->cd.mips.gpr[rd] = (int64_t) (int32_t) cpu->cd.mips.gpr[rd];
2417     }
2418     if (special6 == SPECIAL_DSLL) {
2419     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2420     }
2421     if (special6 == SPECIAL_DSRL) {
2422     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2423     }
2424     if (special6 == SPECIAL_DSLL32) {
2425     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << (sa + 32);
2426     }
2427     if (special6 == SPECIAL_SRL) {
2428     /*
2429     * Three cases:
2430     * shift amount = zero: just copy
2431     * high bit of rt zero: plain shift right (of all bits)
2432     * high bit of rt one: plain shift right (of lowest 32 bits)
2433     */
2434     if (sa == 0)
2435     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2436     else if (!(cpu->cd.mips.gpr[rt] & 0x80000000ULL)) {
2437     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2438     } else
2439     cpu->cd.mips.gpr[rd] = (cpu->cd.mips.gpr[rt] & 0xffffffffULL) >> sa;
2440     }
2441     if (special6 == SPECIAL_SRA) {
2442     int topbit = cpu->cd.mips.gpr[rt] & 0x80000000ULL;
2443     switch (sa) {
2444     case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 8; break;
2445     case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 16; break;
2446     default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2447     }
2448     if (topbit)
2449     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2450     }
2451     if (special6 == SPECIAL_DSRL32) {
2452     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> (sa + 32);
2453     }
2454     if (special6 == SPECIAL_DSRA32 || special6 == SPECIAL_DSRA) {
2455     if (special6 == SPECIAL_DSRA32)
2456     sa += 32;
2457     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2458     while (sa > 0) {
2459     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2460     sa--;
2461     if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old signbit */
2462     cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2463     }
2464     }
2465     return 1;
2466     case SPECIAL_DSRLV:
2467     case SPECIAL_DSRAV:
2468     case SPECIAL_DSLLV:
2469     case SPECIAL_SLLV:
2470     case SPECIAL_SRAV:
2471     case SPECIAL_SRLV:
2472     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2473     rt = instr[2] & 31;
2474     rd = (instr[1] >> 3) & 31;
2475    
2476     if (special6 == SPECIAL_DSRLV) {
2477     sa = cpu->cd.mips.gpr[rs] & 63;
2478     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2479     }
2480     if (special6 == SPECIAL_DSRAV) {
2481     sa = cpu->cd.mips.gpr[rs] & 63;
2482     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2483     while (sa > 0) {
2484     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2485     sa--;
2486     if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old sign-bit */
2487     cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2488     }
2489     }
2490     if (special6 == SPECIAL_DSLLV) {
2491     sa = cpu->cd.mips.gpr[rs] & 63;
2492     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2493     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2494     }
2495     if (special6 == SPECIAL_SLLV) {
2496     sa = cpu->cd.mips.gpr[rs] & 31;
2497     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2498     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2499     /* Sign-extend rd: */
2500     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2501     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2502     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2503     }
2504     if (special6 == SPECIAL_SRAV) {
2505     sa = cpu->cd.mips.gpr[rs] & 31;
2506     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2507     /* Sign-extend rd: */
2508     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2509     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2510     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2511     while (sa > 0) {
2512     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2513     sa--;
2514     }
2515     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2516     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2517     }
2518     if (special6 == SPECIAL_SRLV) {
2519     sa = cpu->cd.mips.gpr[rs] & 31;
2520     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2521     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2522     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> sa;
2523     /* And finally sign-extend rd: */
2524     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2525     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2526     }
2527     return 1;
2528     case SPECIAL_JR:
2529     if (cpu->cd.mips.delay_slot) {
2530     fatal("jr: jump inside a jump's delay slot, or similar. TODO\n");
2531     cpu->running = 0;
2532     return 1;
2533     }
2534    
2535     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2536    
2537     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2538     cpu->cd.mips.delay_jmpaddr = cpu->cd.mips.gpr[rs];
2539    
2540     if (!quiet_mode_cached && cpu->machine->show_trace_tree
2541     && rs == 31) {
2542     cpu->cd.mips.trace_tree_depth --;
2543     }
2544    
2545     return 1;
2546     case SPECIAL_JALR:
2547     if (cpu->cd.mips.delay_slot) {
2548     fatal("jalr: jump inside a jump's delay slot, or similar. TODO\n");
2549     cpu->running = 0;
2550     return 1;
2551     }
2552    
2553     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2554     rd = (instr[1] >> 3) & 31;
2555    
2556     tmpvalue = cpu->cd.mips.gpr[rs];
2557     cpu->cd.mips.gpr[rd] = cached_pc + 4;
2558     /* already increased by 4 earlier */
2559    
2560     if (!quiet_mode_cached && cpu->machine->show_trace_tree
2561     && rd == 31) {
2562     cpu->cd.mips.show_trace_delay = 2;
2563     cpu->cd.mips.show_trace_addr = tmpvalue;
2564     }
2565    
2566     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2567     cpu->cd.mips.delay_jmpaddr = tmpvalue;
2568     return 1;
2569     case SPECIAL_MFHI:
2570     case SPECIAL_MFLO:
2571     rd = (instr[1] >> 3) & 31;
2572    
2573     if (special6 == SPECIAL_MFHI) {
2574     cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
2575     #ifdef MFHILO_DELAY
2576     cpu->mfhi_delay = 3;
2577     #endif
2578     }
2579     if (special6 == SPECIAL_MFLO) {
2580     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2581     #ifdef MFHILO_DELAY
2582     cpu->mflo_delay = 3;
2583     #endif
2584     }
2585     return 1;
2586     case SPECIAL_ADD:
2587     case SPECIAL_ADDU:
2588     case SPECIAL_SUB:
2589     case SPECIAL_SUBU:
2590     case SPECIAL_AND:
2591     case SPECIAL_OR:
2592     case SPECIAL_XOR:
2593     case SPECIAL_NOR:
2594     case SPECIAL_SLT:
2595     case SPECIAL_SLTU:
2596     case SPECIAL_MTLO:
2597     case SPECIAL_MTHI:
2598     case SPECIAL_MULT:
2599     case SPECIAL_MULTU:
2600     case SPECIAL_DMULT:
2601     case SPECIAL_DMULTU:
2602     case SPECIAL_DIV:
2603     case SPECIAL_DIVU:
2604     case SPECIAL_DDIV:
2605     case SPECIAL_DDIVU:
2606     case SPECIAL_TGE:
2607     case SPECIAL_TGEU:
2608     case SPECIAL_TLT:
2609     case SPECIAL_TLTU:
2610     case SPECIAL_TEQ:
2611     case SPECIAL_TNE:
2612     case SPECIAL_DADD:
2613     case SPECIAL_DADDU:
2614     case SPECIAL_DSUB:
2615     case SPECIAL_DSUBU:
2616     case SPECIAL_MOVZ:
2617     case SPECIAL_MOVN:
2618     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2619     rt = instr[2] & 31;
2620     rd = (instr[1] >> 3) & 31;
2621    
2622     #ifdef MFHILO_DELAY
2623     if (cpu->mflo_delay > 0 && (
2624     special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2625     special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2626     special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2627     special6 == SPECIAL_MTLO || special6 == SPECIAL_MULT
2628     || special6 == SPECIAL_MULTU
2629     ) )
2630     debug("warning: instruction modifying LO too early after mflo!\n");
2631    
2632     if (cpu->mfhi_delay > 0 && (
2633     special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2634     special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2635     special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2636     special6 == SPECIAL_MTHI || special6 == SPECIAL_MULT
2637     || special6 == SPECIAL_MULTU
2638     ) )
2639     debug("warning: instruction modifying HI too early after mfhi!\n");
2640     #endif
2641    
2642     if (special6 == SPECIAL_ADDU) {
2643     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2644     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2645     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2646     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2647     break;
2648     }
2649     if (special6 == SPECIAL_ADD) {
2650     /* According to the MIPS64 manual: */
2651     uint64_t temp, temp1, temp2;
2652     temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2653     temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2654     temp = temp1 + temp2;
2655     #if 0
2656     /* TODO: apparently this doesn't work (an example of
2657     something that breaks is NetBSD/sgimips' mips3_TBIA() */
2658     /* If bits 32 and 31 of temp differ, then it's an overflow */
2659     temp1 = temp & 0x100000000ULL;
2660     temp2 = temp & 0x80000000ULL;
2661     if ((temp1 && !temp2) || (!temp1 && temp2)) {
2662     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2663     break;
2664     }
2665     #endif
2666     cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2667     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2668     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2669     break;
2670     }
2671     if (special6 == SPECIAL_SUBU) {
2672     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2673     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2674     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2675     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2676     break;
2677     }
2678     if (special6 == SPECIAL_SUB) {
2679     /* According to the MIPS64 manual: */
2680     uint64_t temp, temp1, temp2;
2681     temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2682     temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2683     temp = temp1 - temp2;
2684     #if 0
2685     /* If bits 32 and 31 of temp differ, then it's an overflow */
2686     temp1 = temp & 0x100000000ULL;
2687     temp2 = temp & 0x80000000ULL;
2688     if ((temp1 && !temp2) || (!temp1 && temp2)) {
2689     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2690     break;
2691     }
2692     #endif
2693     cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2694     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2695     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2696     break;
2697     }
2698    
2699     if (special6 == SPECIAL_AND) {
2700     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] & cpu->cd.mips.gpr[rt];
2701     break;
2702     }
2703     if (special6 == SPECIAL_OR) {
2704     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
2705     break;
2706     }
2707     if (special6 == SPECIAL_XOR) {
2708     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] ^ cpu->cd.mips.gpr[rt];
2709     break;
2710     }
2711     if (special6 == SPECIAL_NOR) {
2712     cpu->cd.mips.gpr[rd] = ~(cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt]);
2713     break;
2714     }
2715     if (special6 == SPECIAL_SLT) {
2716     cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt];
2717     break;
2718     }
2719     if (special6 == SPECIAL_SLTU) {
2720     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt];
2721     break;
2722     }
2723     if (special6 == SPECIAL_MTLO) {
2724     cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
2725     break;
2726     }
2727     if (special6 == SPECIAL_MTHI) {
2728     cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
2729     break;
2730     }
2731     if (special6 == SPECIAL_MULT) {
2732     int64_t f1, f2, sum;
2733     f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2734     /* sign extend f1 */
2735     if (f1 & 0x80000000ULL)
2736     f1 |= 0xffffffff00000000ULL;
2737     f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2738     /* sign extend f2 */
2739     if (f2 & 0x80000000ULL)
2740     f2 |= 0xffffffff00000000ULL;
2741     sum = f1 * f2;
2742    
2743     cpu->cd.mips.lo = sum & 0xffffffffULL;
2744     cpu->cd.mips.hi = ((uint64_t)sum >> 32) & 0xffffffffULL;
2745    
2746     /* sign-extend: */
2747     if (cpu->cd.mips.lo & 0x80000000ULL)
2748     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2749     if (cpu->cd.mips.hi & 0x80000000ULL)
2750     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2751    
2752     /*
2753     * NOTE: The stuff about rd!=0 is just a
2754     * guess, judging from how some NetBSD code
2755     * seems to execute. It is not documented in
2756     * the MIPS64 ISA docs :-/
2757     */
2758    
2759     if (rd != 0) {
2760     if (cpu->cd.mips.cpu_type.rev != MIPS_R5900)
2761     debug("WARNING! mult_xx is an undocumented instruction!");
2762     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2763     }
2764     break;
2765     }
2766     if (special6 == SPECIAL_MULTU) {
2767     uint64_t f1, f2, sum;
2768     /* zero extend f1 and f2 */
2769     f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2770     f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2771     sum = f1 * f2;
2772     cpu->cd.mips.lo = sum & 0xffffffffULL;
2773     cpu->cd.mips.hi = (sum >> 32) & 0xffffffffULL;
2774    
2775     /* sign-extend: */
2776     if (cpu->cd.mips.lo & 0x80000000ULL)
2777     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2778     if (cpu->cd.mips.hi & 0x80000000ULL)
2779     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2780     break;
2781     }
2782     /*
2783     * TODO: I'm too tired to think now. DMULT is probably
2784     * correct, but is DMULTU? (Unsigned 64x64 multiply.)
2785     * Or, hm, perhaps it is dmult which is incorrect.
2786     */
2787     if (special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU) {
2788     /* 64x64 = 128 bit multiplication: SLOW!!! TODO */
2789     uint64_t i, low_add, high_add;
2790    
2791     cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2792     for (i=0; i<64; i++) {
2793     uint64_t bit = cpu->cd.mips.gpr[rt] & ((uint64_t)1 << i);
2794     if (bit) {
2795     /* Add cpu->cd.mips.gpr[rs] to hi and lo: */
2796     low_add = (cpu->cd.mips.gpr[rs] << i);
2797     high_add = (cpu->cd.mips.gpr[rs] >> (64-i));
2798     if (i==0) /* WEIRD BUG in the compiler? Or maybe I'm just stupid */
2799     high_add = 0; /* these lines are necessary, a >> 64 doesn't seem to do anything */
2800     if (cpu->cd.mips.lo + low_add < cpu->cd.mips.lo)
2801     cpu->cd.mips.hi ++;
2802     cpu->cd.mips.lo += low_add;
2803     cpu->cd.mips.hi += high_add;
2804     }
2805     }
2806     break;
2807     }
2808     if (special6 == SPECIAL_DIV) {
2809     int64_t a, b;
2810     /* Signextend rs and rt: */
2811     a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2812     if (a & 0x80000000ULL)
2813     a |= 0xffffffff00000000ULL;
2814     b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2815     if (b & 0x80000000ULL)
2816     b |= 0xffffffff00000000ULL;
2817    
2818     if (b == 0) {
2819     /* undefined */
2820     cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2821     } else {
2822     cpu->cd.mips.lo = a / b;
2823     cpu->cd.mips.hi = a % b;
2824     }
2825     /* Sign-extend lo and hi: */
2826     cpu->cd.mips.lo &= 0xffffffffULL;
2827     if (cpu->cd.mips.lo & 0x80000000ULL)
2828     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2829     cpu->cd.mips.hi &= 0xffffffffULL;
2830     if (cpu->cd.mips.hi & 0x80000000ULL)
2831     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2832     break;
2833     }
2834     if (special6 == SPECIAL_DIVU) {
2835     int64_t a, b;
2836     /* Zero-extend rs and rt: */
2837     a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2838     b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2839     if (b == 0) {
2840     /* undefined */
2841     cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2842     } else {
2843     cpu->cd.mips.lo = a / b;
2844     cpu->cd.mips.hi = a % b;
2845     }
2846     /* Sign-extend lo and hi: */
2847     cpu->cd.mips.lo &= 0xffffffffULL;
2848     if (cpu->cd.mips.lo & 0x80000000ULL)
2849     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2850     cpu->cd.mips.hi &= 0xffffffffULL;
2851     if (cpu->cd.mips.hi & 0x80000000ULL)
2852     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2853     break;
2854     }
2855     if (special6 == SPECIAL_DDIV) {
2856     if (cpu->cd.mips.gpr[rt] == 0) {
2857     cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2858     } else {
2859     cpu->cd.mips.lo = (int64_t)cpu->cd.mips.gpr[rs] / (int64_t)cpu->cd.mips.gpr[rt];
2860     cpu->cd.mips.hi = (int64_t)cpu->cd.mips.gpr[rs] % (int64_t)cpu->cd.mips.gpr[rt];
2861     }
2862     break;
2863     }
2864     if (special6 == SPECIAL_DDIVU) {
2865     if (cpu->cd.mips.gpr[rt] == 0) {
2866     cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2867     } else {
2868     cpu->cd.mips.lo = cpu->cd.mips.gpr[rs] / cpu->cd.mips.gpr[rt];
2869     cpu->cd.mips.hi = cpu->cd.mips.gpr[rs] % cpu->cd.mips.gpr[rt];
2870     }
2871     break;
2872     }
2873     if (special6 == SPECIAL_TGE) {
2874     if ((int64_t)cpu->cd.mips.gpr[rs] >= (int64_t)cpu->cd.mips.gpr[rt])
2875     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2876     break;
2877     }
2878     if (special6 == SPECIAL_TGEU) {
2879     if (cpu->cd.mips.gpr[rs] >= cpu->cd.mips.gpr[rt])
2880     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2881     break;
2882     }
2883     if (special6 == SPECIAL_TLT) {
2884     if ((int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt])
2885     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2886     break;
2887     }
2888     if (special6 == SPECIAL_TLTU) {
2889     if (cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt])
2890     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2891     break;
2892     }
2893     if (special6 == SPECIAL_TEQ) {
2894     if (cpu->cd.mips.gpr[rs] == cpu->cd.mips.gpr[rt])
2895     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2896     break;
2897     }
2898     if (special6 == SPECIAL_TNE) {
2899     if (cpu->cd.mips.gpr[rs] != cpu->cd.mips.gpr[rt])
2900     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2901     break;
2902     }
2903     if (special6 == SPECIAL_DADD) {
2904     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2905     /* TODO: exception on overflow */
2906     break;
2907     }
2908     if (special6 == SPECIAL_DADDU) {
2909     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2910     break;
2911     }
2912     if (special6 == SPECIAL_DSUB) {
2913     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2914     /* TODO: exception on overflow */
2915     break;
2916     }
2917     if (special6 == SPECIAL_DSUBU) {
2918     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2919     break;
2920     }
2921     if (special6 == SPECIAL_MOVZ) {
2922     if (cpu->cd.mips.gpr[rt] == 0)
2923     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2924     break;
2925     }
2926     if (special6 == SPECIAL_MOVN) {
2927     if (cpu->cd.mips.gpr[rt] != 0)
2928     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2929     return 1;
2930     }
2931     return 1;
2932     case SPECIAL_SYNC:
2933     imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
2934     /* TODO: actually sync */
2935    
2936     /* Clear the LLbit (at least on R10000): */
2937     cpu->cd.mips.rmw = 0;
2938     return 1;
2939     case SPECIAL_SYSCALL:
2940     imm = ((instr[3] << 24) + (instr[2] << 16) +
2941     (instr[1] << 8) + instr[0]) >> 6;
2942     imm &= 0xfffff;
2943    
2944     if (cpu->machine->userland_emul != NULL)
2945     useremul_syscall(cpu, imm);
2946     else
2947     mips_cpu_exception(cpu, EXCEPTION_SYS,
2948     0, 0, 0, 0, 0, 0);
2949     return 1;
2950     case SPECIAL_BREAK:
2951     mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
2952     return 1;
2953     case SPECIAL_MFSA:
2954     /* R5900? What on earth does this thing do? */
2955     rd = (instr[1] >> 3) & 31;
2956     /* TODO */
2957     return 1;
2958     case SPECIAL_MTSA:
2959     /* R5900? What on earth does this thing do? */
2960     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2961     /* TODO */
2962     return 1;
2963     default:
2964     if (!instruction_trace_cached) {
2965     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
2966     cpu->cpu_id, cpu->cd.mips.pc_last,
2967     instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
2968     }
2969     fatal("unimplemented special6 = 0x%02x\n", special6);
2970     cpu->running = 0;
2971     return 1;
2972     }
2973     return 1;
2974     case HI6_BEQ:
2975     case HI6_BEQL:
2976     case HI6_BNE:
2977     case HI6_BGTZ:
2978     case HI6_BGTZL:
2979     case HI6_BLEZ:
2980     case HI6_BLEZL:
2981     case HI6_BNEL:
2982     case HI6_ADDI:
2983     case HI6_ADDIU:
2984     case HI6_DADDI:
2985     case HI6_DADDIU:
2986     case HI6_SLTI:
2987     case HI6_SLTIU:
2988     case HI6_ANDI:
2989     case HI6_ORI:
2990     case HI6_XORI:
2991     case HI6_LUI:
2992     case HI6_LB:
2993     case HI6_LBU:
2994     case HI6_LH:
2995     case HI6_LHU:
2996     case HI6_LW:
2997     case HI6_LWU:
2998     case HI6_LD:
2999     case HI6_LQ_MDMX:
3000     case HI6_LWC1:
3001     case HI6_LWC2:
3002     case HI6_LWC3:
3003     case HI6_LDC1:
3004     case HI6_LDC2:
3005     case HI6_LL:
3006     case HI6_LLD:
3007     case HI6_SB:
3008     case HI6_SH:
3009     case HI6_SW:
3010     case HI6_SD:
3011     case HI6_SQ:
3012     case HI6_SC:
3013     case HI6_SCD:
3014     case HI6_SWC1:
3015     case HI6_SWC2:
3016     case HI6_SWC3:
3017     case HI6_SDC1:
3018     case HI6_SDC2:
3019     case HI6_LWL: /* Unaligned load/store */
3020     case HI6_LWR:
3021     case HI6_LDL:
3022     case HI6_LDR:
3023     case HI6_SWL:
3024     case HI6_SWR:
3025     case HI6_SDL:
3026     case HI6_SDR:
3027     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3028     rt = instr[2] & 31;
3029     imm = (instr[1] << 8) + instr[0];
3030     if (imm >= 32768) /* signed 16-bit */
3031     imm -= 65536;
3032    
3033     tmpvalue = imm; /* used later in several cases */
3034    
3035     switch (hi6) {
3036     case HI6_ADDI:
3037     case HI6_ADDIU:
3038     case HI6_DADDI:
3039     case HI6_DADDIU:
3040     tmpvalue = cpu->cd.mips.gpr[rs];
3041     result_value = cpu->cd.mips.gpr[rs] + imm;
3042    
3043     if (hi6 == HI6_ADDI || hi6 == HI6_DADDI) {
3044     /*
3045     * addi and daddi should trap on overflow:
3046     *
3047     * TODO: This is incorrect? The R4000 manual
3048     * says that overflow occurs if the carry bits
3049     * out of bit 62 and 63 differ. The
3050     * destination register should not be modified
3051     * on overflow.
3052     */
3053     if (imm >= 0) {
3054     /* Turn around from 0x7fff.. to 0x800 ? Then overflow. */
3055     if ( ((hi6 == HI6_ADDI && (result_value &
3056     0x80000000ULL) && (tmpvalue &
3057     0x80000000ULL)==0))
3058     || ((hi6 == HI6_DADDI && (result_value &
3059     0x8000000000000000ULL) && (tmpvalue &
3060     0x8000000000000000ULL)==0)) ) {
3061     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3062     break;
3063     }
3064     } else {
3065     /* Turn around from 0x8000.. to 0x7fff.. ? Then overflow. */
3066     if ( ((hi6 == HI6_ADDI && (result_value &
3067     0x80000000ULL)==0 && (tmpvalue &
3068     0x80000000ULL)))
3069     || ((hi6 == HI6_DADDI && (result_value &
3070     0x8000000000000000ULL)==0 && (tmpvalue &
3071     0x8000000000000000ULL))) ) {
3072     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3073     break;
3074     }
3075     }
3076     }
3077    
3078     cpu->cd.mips.gpr[rt] = result_value;
3079    
3080     /*
3081     * Super-ugly speed-hack: (only if speed_tricks != 0)
3082     * NOTE: This makes the emulation less correct.
3083     *
3084     * If we encounter a loop such as:
3085     *
3086     * 8012f5f4: 1c40ffff bgtz r0,r2,ffffffff8012f5f4
3087     * 8012f5f8: 2442ffff (d) addiu r2,r2,-1
3088     *
3089     * then it is a small loop which simply waits for r2
3090     * to become zero.
3091     *
3092     * TODO: increaste the count register, and cause
3093     * interrupts!!! For now: return as if we just
3094     * executed 1 instruction.
3095     */
3096     ninstrs_executed = 1;
3097     if (cpu->machine->speed_tricks && cpu->cd.mips.delay_slot &&
3098     cpu->cd.mips.last_was_jumptoself &&
3099     cpu->cd.mips.jump_to_self_reg == rt &&
3100     cpu->cd.mips.jump_to_self_reg == rs) {
3101     if ((int64_t)cpu->cd.mips.gpr[rt] > 1 && (int64_t)cpu->cd.mips.gpr[rt] < 0x70000000
3102     && (imm >= -30000 && imm <= -1)) {
3103     if (instruction_trace_cached)
3104     debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3105    
3106     while ((int64_t)cpu->cd.mips.gpr[rt] > 0 && ninstrs_executed < 1000
3107     && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) > 0) {
3108     cpu->cd.mips.gpr[rt] += (int64_t)imm;
3109     ninstrs_executed += 2;
3110     }
3111    
3112     if (instruction_trace_cached)
3113     debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3114    
3115     /* TODO: return value, cpu->cd.mips.gpr[rt] * 2; */
3116     }
3117     if ((int64_t)cpu->cd.mips.gpr[rt] > -0x70000000 && (int64_t)cpu->cd.mips.gpr[rt] < -1
3118     && (imm >= 1 && imm <= 30000)) {
3119     if (instruction_trace_cached)
3120     debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3121    
3122     while ((int64_t)cpu->cd.mips.gpr[rt] < 0 && ninstrs_executed < 1000
3123     && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) < 0) {
3124     cpu->cd.mips.gpr[rt] += (int64_t)imm;
3125     ninstrs_executed += 2;
3126     }
3127    
3128     if (instruction_trace_cached)
3129     debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3130     }
3131     }
3132    
3133     if (hi6 == HI6_ADDI || hi6 == HI6_ADDIU) {
3134     /* Sign-extend: */
3135     cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3136     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3137     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3138     }
3139     return ninstrs_executed;
3140     case HI6_BEQ:
3141     case HI6_BNE:
3142     case HI6_BGTZ:
3143     case HI6_BGTZL:
3144     case HI6_BLEZ:
3145     case HI6_BLEZL:
3146     case HI6_BEQL:
3147     case HI6_BNEL:
3148     if (cpu->cd.mips.delay_slot) {
3149     fatal("b*: jump inside a jump's delay slot, or similar. TODO\n");
3150     cpu->running = 0;
3151     return 1;
3152     }
3153     likely = cond = 0;
3154     switch (hi6) {
3155     case HI6_BNEL: likely = 1;
3156     case HI6_BNE: cond = (cpu->cd.mips.gpr[rt] != cpu->cd.mips.gpr[rs]);
3157     break;
3158     case HI6_BEQL: likely = 1;
3159     case HI6_BEQ: cond = (cpu->cd.mips.gpr[rt] == cpu->cd.mips.gpr[rs]);
3160     break;
3161     case HI6_BLEZL: likely = 1;
3162     case HI6_BLEZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] <= 0);
3163     break;
3164     case HI6_BGTZL: likely = 1;
3165     case HI6_BGTZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] > 0);
3166     break;
3167     }
3168    
3169     if (cond) {
3170     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3171     cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3172     } else {
3173     if (likely)
3174     cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3175     }
3176    
3177     if (imm==-1 && (hi6 == HI6_BGTZ || hi6 == HI6_BLEZ ||
3178     (hi6 == HI6_BGTZL && cond) ||
3179     (hi6 == HI6_BLEZL && cond) ||
3180     (hi6 == HI6_BNE && (rt==0 || rs==0)) ||
3181     (hi6 == HI6_BEQ && (rt==0 || rs==0)))) {
3182     cpu->cd.mips.last_was_jumptoself = 2;
3183     if (rs == 0)
3184     cpu->cd.mips.jump_to_self_reg = rt;
3185     else
3186     cpu->cd.mips.jump_to_self_reg = rs;
3187     }
3188     return 1;
3189     case HI6_LUI:
3190     cpu->cd.mips.gpr[rt] = (imm << 16);
3191     /* No sign-extending necessary, as imm already
3192     was sign-extended if it was negative. */
3193     break;
3194     case HI6_SLTI:
3195     cpu->cd.mips.gpr[rt] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)tmpvalue;
3196     break;
3197     case HI6_SLTIU:
3198     cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] < (uint64_t)imm;
3199     break;
3200     case HI6_ANDI:
3201     cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] & (tmpvalue & 0xffff);
3202     break;
3203     case HI6_ORI:
3204     cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] | (tmpvalue & 0xffff);
3205     break;
3206     case HI6_XORI:
3207     cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] ^ (tmpvalue & 0xffff);
3208     break;
3209     case HI6_LB:
3210     case HI6_LBU:
3211     case HI6_LH:
3212     case HI6_LHU:
3213     case HI6_LW:
3214     case HI6_LWU:
3215     case HI6_LD:
3216     case HI6_LQ_MDMX:
3217     case HI6_LWC1:
3218     case HI6_LWC2:
3219     case HI6_LWC3: /* pref */
3220     case HI6_LDC1:
3221     case HI6_LDC2:
3222     case HI6_LL:
3223     case HI6_LLD:
3224     case HI6_SB:
3225     case HI6_SH:
3226     case HI6_SW:
3227     case HI6_SD:
3228     case HI6_SQ:
3229     case HI6_SC:
3230     case HI6_SCD:
3231     case HI6_SWC1:
3232     case HI6_SWC2:
3233     case HI6_SWC3:
3234     case HI6_SDC1:
3235     case HI6_SDC2:
3236     /* These are the default "assumptions". */
3237     linked = 0;
3238     st = 1;
3239     signd = 1;
3240     wlen = 4;
3241    
3242     switch (hi6) {
3243     /* The most common ones: */
3244     case HI6_LW: { st = 0; } break;
3245     case HI6_SW: { signd = 0; } break;
3246    
3247     case HI6_LB: { wlen = 1; st = 0; } break;
3248     case HI6_LBU: { wlen = 1; st = 0; signd = 0; } break;
3249     case HI6_SB: { wlen = 1; signd = 0; } break;
3250    
3251     case HI6_LD: { wlen = 8; st = 0; signd = 0; } break;
3252     case HI6_SD: { wlen = 8; signd = 0; } break;
3253    
3254     case HI6_LQ_MDMX: { wlen = 16; st = 0; signd = 0; } break; /* R5900, otherwise MDMX (TODO) */
3255     case HI6_SQ: { wlen = 16; signd = 0; } break; /* R5900 ? */
3256    
3257     /* The rest: */
3258     case HI6_LH: { wlen = 2; st = 0; } break;
3259     case HI6_LHU: { wlen = 2; st = 0; signd = 0; } break;
3260     case HI6_LWU: { st = 0; signd = 0; } break;
3261     case HI6_LWC1: { st = 0; } break;
3262     case HI6_LWC2: { st = 0; } break;
3263     case HI6_LWC3: { st = 0; } break;
3264     case HI6_LDC1: { wlen = 8; st = 0; signd = 0; } break;
3265     case HI6_LDC2: { wlen = 8; st = 0; signd = 0; } break;
3266    
3267     case HI6_SH: { wlen = 2; signd = 0; } break;
3268     case HI6_SDC1:
3269     case HI6_SDC2: wlen = 8;
3270     case HI6_SWC1:
3271     case HI6_SWC2:
3272     case HI6_SWC3: { signd = 0; } break;
3273    
3274     case HI6_LL: { st = 0; signd = 1; linked = 1; } break;
3275     case HI6_LLD: { wlen = 8; st = 0; signd = 0; linked = 1; } break;
3276    
3277     case HI6_SC: { signd = 1; linked = 1; } break;
3278     case HI6_SCD: { wlen = 8; signd = 0; linked = 1; } break;
3279    
3280     default:
3281     fatal("cannot be here\n");
3282     wlen = 4; st = 0; signd = 0;
3283     }
3284    
3285     /*
3286     * In the MIPS IV ISA, the 'lwc3' instruction is changed into 'pref'.
3287     * The pref instruction is emulated by not doing anything. :-) TODO
3288     */
3289     if (hi6 == HI6_LWC3 && cpu->cd.mips.cpu_type.isa_level >= 4) {
3290     /* Clear the LLbit (at least on R10000): */
3291     cpu->cd.mips.rmw = 0;
3292     break;
3293     }
3294    
3295     addr = cpu->cd.mips.gpr[rs] + imm;
3296    
3297     /* Check for natural alignment: */
3298     if ((addr & (wlen - 1)) != 0) {
3299     mips_cpu_exception(cpu, st? EXCEPTION_ADES : EXCEPTION_ADEL,
3300     0, addr, 0, 0, 0, 0);
3301     break;
3302     }
3303    
3304     #if 0
3305     if (cpu->cd.mips.cpu_type.isa_level == 4 && (imm & (wlen - 1)) != 0)
3306     debug("WARNING: low bits of imm value not zero! (MIPS IV) "
3307     "pc=%016llx", (long long)cpu->cd.mips.pc_last);
3308     #endif
3309    
3310     /*
3311     * Load Linked: This initiates a Read-Modify-Write
3312     * sequence.
3313     */
3314     if (linked) {
3315     if (st==0) {
3316     /* st == 0: Load */
3317     cpu->cd.mips.rmw = 1;
3318     cpu->cd.mips.rmw_addr = addr;
3319     cpu->cd.mips.rmw_len = wlen;
3320    
3321     /*
3322     * COP0_LLADDR is updated for
3323     * diagnostic purposes, except for
3324     * CPUs in the R10000 family.
3325     */
3326     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
3327     cp0->reg[COP0_LLADDR] =
3328     (addr >> 4) & 0xffffffffULL;
3329     } else {
3330     /*
3331     * st == 1: Store
3332     * If rmw is 0, then the store failed.
3333     * (This cache-line was written to by
3334     * someone else.)
3335     */
3336 dpavlin 4 if (cpu->cd.mips.rmw == 0 ||
3337     cpu->cd.mips.rmw_addr != addr ||
3338     cpu->cd.mips.rmw_len != wlen) {
3339 dpavlin 2 /* The store failed: */
3340     cpu->cd.mips.gpr[rt] = 0;
3341     if (instruction_trace_cached)
3342     debug(" [COLLISION] ");
3343     break;
3344     }
3345     }
3346     } else {
3347     /*
3348     * If any kind of load or store occurs between
3349     * an ll and an sc, then the ll-sc sequence
3350     * should fail. (This is local to each cpu.)
3351     */
3352     cpu->cd.mips.rmw = 0;
3353     }
3354    
3355     value_hi = 0;
3356    
3357     if (st) {
3358     /* store: */
3359     int cpnr, success;
3360    
3361     if (hi6 == HI6_SWC3 || hi6 == HI6_SWC2 ||
3362     hi6 == HI6_SDC1 || hi6 == HI6_SWC1) {
3363     cpnr = 1;
3364     switch (hi6) {
3365     case HI6_SWC3: cpnr++; /* fallthrough */
3366     case HI6_SWC2: cpnr++;
3367     case HI6_SDC1:
3368     case HI6_SWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3369     (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3370     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3371     cpnr = -1;
3372     break;
3373     } else {
3374     /* Special handling of 64-bit stores
3375     on 32-bit CPUs, and on newer CPUs
3376     in 32-bit compatiblity mode: */
3377     if ((hi6==HI6_SDC1 || hi6==HI6_SDC2) &&
3378     (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3379     !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3380     uint64_t a, b;
3381     coproc_register_read(cpu,
3382     cpu->cd.mips.coproc[cpnr], rt, &a);
3383     coproc_register_read(cpu,
3384     cpu->cd.mips.coproc[cpnr], rt^1, &b);
3385     if (rt & 1)
3386     fatal("WARNING: SDCx in 32-bit mode from odd register!\n");
3387     value = (a & 0xffffffffULL)
3388     | (b << 32);
3389     } else
3390     coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr], rt, &value);
3391     }
3392     break;
3393     default:
3394     ;
3395     }
3396     if (cpnr < 0)
3397     break;
3398     } else
3399     value = cpu->cd.mips.gpr[rt];
3400    
3401     if (wlen == 4) {
3402     /* Special case for 32-bit stores... (perhaps not worth it) */
3403     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3404     d[0] = value & 0xff; d[1] = (value >> 8) & 0xff;
3405     d[2] = (value >> 16) & 0xff; d[3] = (value >> 24) & 0xff;
3406     } else {
3407     d[3] = value & 0xff; d[2] = (value >> 8) & 0xff;
3408     d[1] = (value >> 16) & 0xff; d[0] = (value >> 24) & 0xff;
3409     }
3410     } else if (wlen == 16) {
3411     value_hi = cpu->cd.mips.gpr_quadhi[rt];
3412     /* Special case for R5900 128-bit stores: */
3413     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3414     for (i=0; i<8; i++) {
3415     d[i] = (value >> (i*8)) & 255;
3416     d[i+8] = (value_hi >> (i*8)) & 255;
3417     }
3418     else
3419     for (i=0; i<8; i++) {
3420     d[i] = (value >> ((wlen-1-i)*8)) & 255;
3421     d[i + 8] = (value_hi >> ((wlen-1-i)*8)) & 255;
3422     }
3423     } else if (wlen == 1) {
3424     d[0] = value & 0xff;
3425     } else {
3426     /* General case: */
3427     uint64_t v = value;
3428     if (cpu->byte_order ==
3429     EMUL_LITTLE_ENDIAN)
3430     for (i=0; i<wlen; i++) {
3431     d[i] = v & 255;
3432     v >>= 8;
3433     }
3434     else
3435     for (i=0; i<wlen; i++) {
3436     d[wlen-1-i] = v & 255;
3437     v >>= 8;
3438     }
3439     }
3440    
3441     success = cpu->memory_rw(cpu, cpu->mem, addr,
3442     d, wlen, MEM_WRITE, CACHE_DATA);
3443     if (!success) {
3444     /* The store failed, and might have caused an exception. */
3445     if (instruction_trace_cached)
3446     debug("(failed)]\n");
3447     break;
3448     }
3449     } else {
3450     /* load: */
3451     int cpnr = 1;
3452     int success;
3453    
3454     success = cpu->memory_rw(cpu, cpu->mem, addr,
3455     d, wlen, MEM_READ, CACHE_DATA);
3456     if (!success) {
3457     /* The load failed, and might have caused an exception. */
3458     if (instruction_trace_cached)
3459     debug("(failed)]\n");
3460     break;
3461     }
3462    
3463     if (wlen == 1)
3464     value = d[0] | (signd && (d[0]&128)? (-1 << 8) : 0);
3465     else if (wlen != 16) {
3466     /* General case (except for 128-bit): */
3467     int i;
3468     value = 0;
3469     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3470     if (signd && (d[wlen-1] & 128)!=0) /* sign extend */
3471     value = -1;
3472     for (i=wlen-1; i>=0; i--) {
3473     value <<= 8;
3474     value += d[i];
3475     }
3476     } else {
3477     if (signd && (d[0] & 128)!=0) /* sign extend */
3478     value = -1;
3479     for (i=0; i<wlen; i++) {
3480     value <<= 8;
3481     value += d[i];
3482     }
3483     }
3484     } else {
3485     /* R5900 128-bit quadword: */
3486     int i;
3487     value_hi = 0;
3488     value = 0;
3489     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3490     for (i=wlen-1; i>=0; i--) {
3491     value_hi <<= 8;
3492     value_hi += (value >> 56) & 255;
3493     value <<= 8;
3494     value += d[i];
3495     }
3496     } else {
3497     for (i=0; i<wlen; i++) {
3498     value_hi <<= 8;
3499     value_hi += (value >> 56) & 255;
3500     value <<= 8;
3501     value += d[i];
3502     }
3503     }
3504     cpu->cd.mips.gpr_quadhi[rt] = value_hi;
3505     }
3506    
3507     switch (hi6) {
3508     case HI6_LWC3: cpnr++; /* fallthrough */
3509     case HI6_LDC2:
3510     case HI6_LWC2: cpnr++;
3511     case HI6_LDC1:
3512     case HI6_LWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3513     (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3514     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3515     } else {
3516     /* Special handling of 64-bit loads
3517     on 32-bit CPUs, and on newer CPUs
3518     in 32-bit compatiblity mode: */
3519     if ((hi6==HI6_LDC1 || hi6==HI6_LDC2) &&
3520     (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3521     !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3522     uint64_t a, b;
3523     a = (int64_t)(int32_t) (value & 0xffffffffULL);
3524     b = (int64_t)(int32_t) (value >> 32);
3525     coproc_register_write(cpu,
3526     cpu->cd.mips.coproc[cpnr], rt, &a,
3527     hi6==HI6_LDC1 || hi6==HI6_LDC2);
3528     coproc_register_write(cpu,
3529     cpu->cd.mips.coproc[cpnr], rt ^ 1, &b,
3530     hi6==HI6_LDC1 || hi6==HI6_LDC2);
3531     if (rt & 1)
3532     fatal("WARNING: LDCx in 32-bit mode to odd register!\n");
3533     } else {
3534     coproc_register_write(cpu,
3535     cpu->cd.mips.coproc[cpnr], rt, &value,
3536     hi6==HI6_LDC1 || hi6==HI6_LDC2);
3537     }
3538     }
3539     break;
3540     default: if (rt != 0)
3541     cpu->cd.mips.gpr[rt] = value;
3542     }
3543     }
3544    
3545     if (linked && st==1) {
3546     /*
3547     * The store succeeded. Invalidate any other
3548     * cpu's store to this cache line, and then
3549     * return 1 in gpr rt:
3550     *
3551     * (this is a semi-ugly hack using global
3552     * 'cpus')
3553     *
3554     * TODO: How about invalidating other CPUs
3555     * stores to this cache line, even if this
3556     * was _NOT_ a linked store?
3557     */
3558     for (i=0; i<cpu->machine->ncpus; i++) {
3559     if (cpu->machine->cpus[i]->cd.mips.rmw) {
3560     uint64_t yaddr = addr;
3561     uint64_t xaddr =
3562     cpu->machine->cpus[i]->cd.mips.rmw_addr;
3563     uint64_t mask;
3564     mask = ~(cpu->machine->cpus[i]->
3565     cd.mips.cache_linesize[CACHE_DATA]
3566     - 1);
3567     xaddr &= mask;
3568     yaddr &= mask;
3569     if (xaddr == yaddr) {
3570     cpu->machine->cpus[i]->cd.mips.rmw = 0;
3571     cpu->machine->cpus[i]->cd.mips.rmw_addr = 0;
3572     }
3573     }
3574     }
3575    
3576     if (rt != 0)
3577     cpu->cd.mips.gpr[rt] = 1;
3578    
3579     if (instruction_trace_cached)
3580     debug(" [no collision] ");
3581     cpu->cd.mips.rmw = 0;
3582     }
3583    
3584     if (instruction_trace_cached) {
3585     switch (wlen) {
3586     case 2: debug("0x%04x", (int)value); break;
3587     case 4: debug("0x%08x", (int)value); break;
3588     case 8: debug("0x%016llx", (long long)value);
3589     break;
3590     case 16:debug("0x%016llx", (long long)value_hi);
3591     debug("%016llx", (long long)value);
3592     break;
3593     default:debug("0x%02x", (int)value);
3594     }
3595     debug("]\n");
3596     }
3597     return 1;
3598     case HI6_LWL: /* Unaligned load/store */
3599     case HI6_LWR:
3600     case HI6_LDL:
3601     case HI6_LDR:
3602     case HI6_SWL:
3603     case HI6_SWR:
3604     case HI6_SDL:
3605     case HI6_SDR:
3606     /* For L (Left): address is the most significant byte */
3607     /* For R (Right): address is the least significant byte */
3608     addr = cpu->cd.mips.gpr[rs] + imm;
3609    
3610     is_left = 0;
3611     if (hi6 == HI6_SWL || hi6 == HI6_LWL ||
3612     hi6 == HI6_SDL || hi6 == HI6_LDL)
3613     is_left = 1;
3614    
3615     wlen = 0; st = 0;
3616     signd = 0;
3617     if (hi6 == HI6_LWL || hi6 == HI6_LWR)
3618     signd = 1;
3619    
3620     if (hi6 == HI6_LWL || hi6 == HI6_LWR) { wlen = 4; st = 0; }
3621     if (hi6 == HI6_SWL || hi6 == HI6_SWR) { wlen = 4; st = 1; }
3622     if (hi6 == HI6_LDL || hi6 == HI6_LDR) { wlen = 8; st = 0; }
3623     if (hi6 == HI6_SDL || hi6 == HI6_SDR) { wlen = 8; st = 1; }
3624    
3625     dir = 1; /* big endian, Left */
3626     reg_dir = -1;
3627     reg_ofs = wlen - 1; /* byte offset in the register */
3628     if (!is_left) {
3629     dir = -dir;
3630     reg_ofs = 0;
3631     reg_dir = 1;
3632     }
3633     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3634     dir = -dir;
3635    
3636     result_value = cpu->cd.mips.gpr[rt];
3637    
3638     if (st) {
3639     /* Store: */
3640     uint64_t aligned_addr = addr & ~(wlen-1);
3641     unsigned char aligned_word[8];
3642     uint64_t oldpc = cpu->pc;
3643     /*
3644     * NOTE (this is ugly): The memory_rw()
3645     * call generates a TLBL exception, if there
3646     * is a tlb refill exception. However, since
3647     * this is a Store, the exception is converted
3648     * to a TLBS:
3649     */
3650     int ok = cpu->memory_rw(cpu, cpu->mem,
3651     aligned_addr, &aligned_word[0], wlen,
3652     MEM_READ, CACHE_DATA);
3653     if (!ok) {
3654     if (cpu->pc != oldpc) {
3655     cp0->reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
3656     cp0->reg[COP0_CAUSE] |= (EXCEPTION_TLBS << CAUSE_EXCCODE_SHIFT);
3657     }
3658     return 1;
3659     }
3660    
3661     for (i=0; i<wlen; i++) {
3662     tmpaddr = addr + i*dir;
3663     /* Have we moved into another word/dword? Then stop: */
3664     if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3665     break;
3666    
3667     /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3668     tmpaddr, reg_ofs, (long long)result_value); */
3669    
3670     /* Store one byte: */
3671     aligned_word[tmpaddr & (wlen-1)] = (result_value >> (reg_ofs * 8)) & 255;
3672    
3673     reg_ofs += reg_dir;
3674     }
3675    
3676     ok = cpu->memory_rw(cpu, cpu->mem,
3677     aligned_addr, &aligned_word[0], wlen,
3678     MEM_WRITE, CACHE_DATA);
3679     if (!ok)
3680     return 1;
3681     } else {
3682     /* Load: */
3683     uint64_t aligned_addr = addr & ~(wlen-1);
3684     unsigned char aligned_word[8], databyte;
3685     int ok = cpu->memory_rw(cpu, cpu->mem,
3686     aligned_addr, &aligned_word[0], wlen,
3687     MEM_READ, CACHE_DATA);
3688     if (!ok)
3689     return 1;
3690    
3691     for (i=0; i<wlen; i++) {
3692     tmpaddr = addr + i*dir;
3693     /* Have we moved into another word/dword? Then stop: */
3694     if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3695     break;
3696    
3697     /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3698     tmpaddr, reg_ofs, (long long)result_value); */
3699    
3700     /* Load one byte: */
3701     databyte = aligned_word[tmpaddr & (wlen-1)];
3702     result_value &= ~((uint64_t)0xff << (reg_ofs * 8));
3703     result_value |= (uint64_t)databyte << (reg_ofs * 8);
3704    
3705     reg_ofs += reg_dir;
3706     }
3707    
3708     if (rt != 0)
3709     cpu->cd.mips.gpr[rt] = result_value;
3710     }
3711    
3712     /* Sign extend for 32-bit load lefts: */
3713     if (!st && signd && wlen == 4) {
3714     cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3715     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3716     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3717     }
3718    
3719     if (instruction_trace_cached) {
3720     char *t;
3721     switch (wlen) {
3722     case 2: t = "0x%04llx"; break;
3723     case 4: t = "0x%08llx"; break;
3724     case 8: t = "0x%016llx"; break;
3725     default: t = "0x%02llx";
3726     }
3727     debug(t, (long long)cpu->cd.mips.gpr[rt]);
3728     debug("]\n");
3729     }
3730    
3731     return 1;
3732     }
3733     return 1;
3734     case HI6_REGIMM:
3735     regimm5 = instr[2] & 0x1f;
3736    
3737     if (show_opcode_statistics)
3738     cpu->cd.mips.stats__regimm[regimm5] ++;
3739    
3740     switch (regimm5) {
3741     case REGIMM_BLTZ:
3742     case REGIMM_BGEZ:
3743     case REGIMM_BLTZL:
3744     case REGIMM_BGEZL:
3745     case REGIMM_BLTZAL:
3746     case REGIMM_BLTZALL:
3747     case REGIMM_BGEZAL:
3748     case REGIMM_BGEZALL:
3749     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3750     imm = (instr[1] << 8) + instr[0];
3751     if (imm >= 32768) /* signed 16-bit */
3752     imm -= 65536;
3753    
3754     cond = and_link = likely = 0;
3755    
3756     switch (regimm5) {
3757     case REGIMM_BLTZL: likely = 1;
3758     case REGIMM_BLTZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3759     break;
3760     case REGIMM_BGEZL: likely = 1;
3761     case REGIMM_BGEZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3762     break;
3763    
3764     case REGIMM_BLTZALL: likely = 1;
3765     case REGIMM_BLTZAL: and_link = 1;
3766     cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3767     break;
3768     case REGIMM_BGEZALL: likely = 1;
3769     case REGIMM_BGEZAL: and_link = 1;
3770     cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3771     break;
3772     }
3773    
3774     if (and_link)
3775     cpu->cd.mips.gpr[31] = cached_pc + 4;
3776    
3777     if (cond) {
3778     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3779     cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3780     } else {
3781     if (likely)
3782     cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3783     }
3784    
3785     return 1;
3786     default:
3787     if (!instruction_trace_cached) {
3788     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
3789     cpu->cpu_id, cpu->cd.mips.pc_last,
3790     instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
3791     }
3792     fatal("unimplemented regimm5 = 0x%02x\n", regimm5);
3793     cpu->running = 0;
3794     return 1;
3795     }
3796     /* NOT REACHED */
3797     case HI6_J:
3798     case HI6_JAL:
3799     if (cpu->cd.mips.delay_slot) {
3800     fatal("j/jal: jump inside a jump's delay slot, or similar. TODO\n");
3801     cpu->running = 0;
3802     return 1;
3803     }
3804     imm = ((instr[3] & 3) << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3805     imm <<= 2;
3806    
3807     if (hi6 == HI6_JAL)
3808     cpu->cd.mips.gpr[31] = cached_pc + 4; /* pc already increased by 4 earlier */
3809    
3810     addr = cached_pc & ~((1 << 28) - 1);
3811     addr |= imm;
3812    
3813     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3814     cpu->cd.mips.delay_jmpaddr = addr;
3815    
3816     if (!quiet_mode_cached && cpu->machine->show_trace_tree &&
3817     hi6 == HI6_JAL) {
3818     cpu->cd.mips.show_trace_delay = 2;
3819     cpu->cd.mips.show_trace_addr = addr;
3820     }
3821    
3822     return 1;
3823     case HI6_COP0:
3824     case HI6_COP1:
3825     case HI6_COP2:
3826     case HI6_COP3:
3827     imm = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3828     imm &= ((1 << 26) - 1);
3829    
3830     cpnr = 0;
3831     if (hi6 == HI6_COP0) cpnr = 0;
3832     if (hi6 == HI6_COP1) cpnr = 1;
3833     if (hi6 == HI6_COP2) cpnr = 2;
3834     if (hi6 == HI6_COP3) cpnr = 3;
3835    
3836     /*
3837     * If there is no coprocessor nr cpnr, or we are running in
3838     * userland and the coprocessor is not marked as Useable in
3839     * the status register of CP0, then we get an exception.
3840     *
3841     * An exception (hehe) to this rule is that the kernel should
3842     * always be able to access CP0.
3843     */
3844     /* Set tmp = 1 if we're in user mode. */
3845     tmp = 0;
3846     switch (cpu->cd.mips.cpu_type.exc_model) {
3847     case EXC3K:
3848     /*
3849     * NOTE: If the KU bit is checked, Linux crashes.
3850     * It is the PC that counts. TODO: Check whether
3851     * this is true or not for R4000 as well.
3852     */
3853     if (cached_pc <= 0x7fffffff) /* if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */
3854     tmp = 1;
3855     break;
3856     default:
3857     /* R4000 etc: (TODO: How about supervisor mode?) */
3858     if (((cp0->reg[COP0_STATUS] & STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
3859     tmp = 1;
3860     if (cp0->reg[COP0_STATUS] & STATUS_ERL)
3861     tmp = 0;
3862     if (cp0->reg[COP0_STATUS] & STATUS_EXL)
3863     tmp = 0;
3864     break;
3865     }
3866     if (cpu->cd.mips.coproc[cpnr] == NULL ||
3867     (tmp && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ||
3868     (!tmp && cpnr >= 1 && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)))
3869     ) {
3870     if (instruction_trace_cached)
3871     debug("cop%i\t0x%08x => coprocessor unusable\n", cpnr, (int)imm);
3872    
3873     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3874     } else {
3875     /*
3876     * Execute the coprocessor function. The
3877     * coproc_function code outputs instruction
3878     * trace, if necessary.
3879     */
3880     coproc_function(cpu, cpu->cd.mips.coproc[cpnr],
3881     cpnr, imm, 0, 1);
3882     }
3883     return 1;
3884     case HI6_CACHE:
3885     rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
3886     copz = instr[2] & 31;
3887     imm = (instr[1] << 8) + instr[0];
3888    
3889     cache_op = copz >> 2;
3890     which_cache = copz & 3;
3891    
3892     /*
3893     * TODO: The cache instruction is implementation dependant.
3894     * This is really ugly.
3895     */
3896    
3897     #if 0
3898     Remove this...
3899    
3900     /* if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) { */
3901     /* printf("taghi=%08lx taglo=%08lx\n",
3902     (long)cp0->reg[COP0_TAGDATA_HI],
3903     (long)cp0->reg[COP0_TAGDATA_LO]);
3904     */
3905     if (cp0->reg[COP0_TAGDATA_HI] == 0 &&
3906     cp0->reg[COP0_TAGDATA_LO] == 0) {
3907     /* Normal cache operation: */
3908     cpu->r10k_cache_disable_TODO = 0;
3909     } else {
3910     /* Dislocate the cache: */
3911     cpu->r10k_cache_disable_TODO = 1;
3912     }
3913     /* } */
3914     #endif
3915    
3916     /*
3917     * Clear the LLbit (at least on R10000):
3918     * TODO: How about R4000?
3919     */
3920     cpu->cd.mips.rmw = 0;
3921    
3922     return 1;
3923     case HI6_SPECIAL2:
3924     special6 = instr[0] & 0x3f;
3925    
3926     if (show_opcode_statistics)
3927     cpu->cd.mips.stats__special2[special6] ++;
3928    
3929     instrword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3930    
3931     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3932     rt = instr[2] & 31;
3933     rd = (instr[1] >> 3) & 31;
3934    
3935     /* printf("special2 %08x rs=0x%02x rt=0x%02x rd=0x%02x\n", instrword, rs,rt,rd); */
3936    
3937     /*
3938     * Many of these can be found in the R5000 docs, or figured out
3939     * by studying binutils source code for MIPS instructions.
3940     */
3941    
3942     if ((instrword & 0xfc0007ffULL) == 0x70000000) {
3943     {
3944     int32_t a, b;
3945     int64_t c;
3946     a = (int32_t)cpu->cd.mips.gpr[rs];
3947     b = (int32_t)cpu->cd.mips.gpr[rt];
3948     c = a * b;
3949     c += (cpu->cd.mips.lo & 0xffffffffULL)
3950     + (cpu->cd.mips.hi << 32);
3951     cpu->cd.mips.lo = (int64_t)((int32_t)c);
3952     cpu->cd.mips.hi = (int64_t)((int32_t)(c >> 32));
3953    
3954     /*
3955     * The R5000 manual says that rd should be all zeros,
3956     * but it isn't on R5900. I'm just guessing here that
3957     * it stores the value in register rd, in addition to hi/lo.
3958     * TODO
3959     */
3960     if (rd != 0)
3961     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3962     }
3963     } else if ((instrword & 0xffff07ffULL) == 0x70000209
3964     || (instrword & 0xffff07ffULL) == 0x70000249) {
3965     /*
3966     * This is just a guess for R5900, I've not found any docs on this one yet.
3967     *
3968     * pmfhi/pmflo rd
3969     *
3970     * If the lowest 8 bits of the instruction word are 0x09, it's a pmfhi.
3971     * If the lowest bits are 0x49, it's a pmflo.
3972     *
3973     * A wild guess is that this is a 128-bit version of mfhi/mflo.
3974     * For now, this is implemented as 64-bit only. (TODO)
3975     */
3976     if (instr[0] == 0x49) {
3977     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3978     } else {
3979     cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
3980     }
3981     } else if ((instrword & 0xfc1fffff) == 0x70000269 || (instrword & 0xfc1fffff) == 0x70000229) {
3982     /*
3983     * This is just a guess for R5900, I've not found any docs on this one yet.
3984     *
3985     * pmthi/pmtlo rs (pmtlo = 269, pmthi = 229)
3986     *
3987     * A wild guess is that this is a 128-bit version of mthi/mtlo.
3988     * For now, this is implemented as 64-bit only. (TODO)
3989     */
3990     if (instr[0] == 0x69) {
3991     cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
3992     } else {
3993     cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
3994     }
3995     } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
3996     /*
3997     * This is just a guess for R5900, I've not found any docs on this one yet.
3998     *
3999     * por dst,src,src2 ==> rs=src rt=src2 rd=dst
4000     *
4001     * A wild guess is that this is a 128-bit "or" between two registers.
4002     * For now, let's just or using 64-bits. (TODO)
4003     */
4004     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
4005     } else if ((instrword & 0xfc0007ff) == 0x70000488) {
4006     /*
4007     * R5900 "undocumented" pextlw. TODO: find out if this is correct.
4008     * It seems that this instruction is used to combine two 32-bit
4009     * words into a 64-bit dword, typically before a sd (store dword).
4010     */
4011     cpu->cd.mips.gpr[rd] =
4012     ((cpu->cd.mips.gpr[rs] & 0xffffffffULL) << 32) /* TODO: switch rt and rs? */
4013     | (cpu->cd.mips.gpr[rt] & 0xffffffffULL);
4014     } else if (special6 == SPECIAL2_MUL) {
4015     cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rt] *
4016     (int64_t)cpu->cd.mips.gpr[rs];
4017     } else if (special6 == SPECIAL2_CLZ) {
4018     /* clz: count leading zeroes */
4019     int i, n=0;
4020     for (i=31; i>=0; i--) {
4021     if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
4022     break;
4023     else
4024     n++;
4025     }
4026     cpu->cd.mips.gpr[rd] = n;
4027     } else if (special6 == SPECIAL2_CLO) {
4028     /* clo: count leading ones */
4029     int i, n=0;
4030     for (i=31; i>=0; i--) {
4031     if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
4032     n++;
4033     else
4034     break;
4035     }
4036     cpu->cd.mips.gpr[rd] = n;
4037     } else if (special6 == SPECIAL2_DCLZ) {
4038     /* dclz: count leading zeroes */
4039     int i, n=0;
4040     for (i=63; i>=0; i--) {
4041     if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4042     break;
4043     else
4044     n++;
4045     }
4046     cpu->cd.mips.gpr[rd] = n;
4047     } else if (special6 == SPECIAL2_DCLO) {
4048     /* dclo: count leading ones */
4049     int i, n=0;
4050     for (i=63; i>=0; i--) {
4051     if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4052     n++;
4053     else
4054     break;
4055     }
4056     cpu->cd.mips.gpr[rd] = n;
4057     } else {
4058     if (!instruction_trace_cached) {
4059     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4060     cpu->cpu_id, cpu->cd.mips.pc_last,
4061     instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4062     }
4063     fatal("unimplemented special_2 = 0x%02x, rs=0x%02x rt=0x%02x rd=0x%02x\n",
4064     special6, rs, rt, rd);
4065     cpu->running = 0;
4066     return 1;
4067     }
4068     return 1;
4069     default:
4070     if (!instruction_trace_cached) {
4071     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4072     cpu->cpu_id, cpu->cd.mips.pc_last,
4073     instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4074     }
4075     fatal("unimplemented hi6 = 0x%02x\n", hi6);
4076     cpu->running = 0;
4077     return 1;
4078     }
4079    
4080     /* NOTREACHED */
4081     }
4082    
4083    
4084     #define CPU_RUN mips_cpu_run
4085     #define CPU_RUN_MIPS
4086     #define CPU_RINSTR mips_cpu_run_instr
4087     #include "cpu_run.c"
4088     #undef CPU_RINSTR
4089     #undef CPU_RUN_MIPS
4090     #undef CPU_RUN
4091    
4092    
4093     /*
4094     * mips_cpu_dumpinfo():
4095     *
4096     * Debug dump of MIPS-specific CPU data for specific CPU.
4097     */
4098     void mips_cpu_dumpinfo(struct cpu *cpu)
4099     {
4100     struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type;
4101    
4102     debug(" (%i-bit ", (ct->isa_level < 3 ||
4103     ct->isa_level == 32)? 32 : 64);
4104    
4105     debug("%s, ", cpu->byte_order == EMUL_BIG_ENDIAN? "BE" : "LE");
4106    
4107     debug("nTLB=%i", ct->nr_of_tlb_entries);
4108    
4109     if (ct->default_picache || ct->default_pdcache)
4110     debug(", I+D = %i+%i KB",
4111     (1 << ct->default_picache) / 1024,
4112     (1 << ct->default_pdcache) / 1024);
4113    
4114     if (ct->default_scache) {
4115     int kb = (1 << ct->default_scache) / 1024;
4116     debug(", L2 = %i %cB",
4117     kb >= 1024? kb / 1024 : kb,
4118     kb >= 1024? 'M' : 'K');
4119     }
4120    
4121     debug(")\n");
4122     }
4123    
4124    
4125     /*
4126     * mips_cpu_list_available_types():
4127     *
4128     * Print a list of available MIPS CPU types.
4129     */
4130     void mips_cpu_list_available_types(void)
4131     {
4132     int i, j;
4133     struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
4134    
4135     i = 0;
4136     while (cpu_type_defs[i].name != NULL) {
4137     debug("%s", cpu_type_defs[i].name);
4138     for (j=10 - strlen(cpu_type_defs[i].name); j>0; j--)
4139     debug(" ");
4140     i++;
4141     if ((i % 6) == 0 || cpu_type_defs[i].name == NULL)
4142     debug("\n");
4143     }
4144     }
4145    
4146    
4147     /*
4148     * mips_cpu_family_init():
4149     *
4150     * Fill in the cpu_family struct for MIPS.
4151     */
4152     int mips_cpu_family_init(struct cpu_family *fp)
4153     {
4154     fp->name = "MIPS";
4155     fp->cpu_new = mips_cpu_new;
4156     fp->list_available_types = mips_cpu_list_available_types;
4157     fp->register_match = mips_cpu_register_match;
4158     fp->disassemble_instr = mips_cpu_disassemble_instr;
4159     fp->register_dump = mips_cpu_register_dump;
4160     fp->run = mips_cpu_run;
4161     fp->dumpinfo = mips_cpu_dumpinfo;
4162     fp->show_full_statistics = mips_cpu_show_full_statistics;
4163     fp->tlbdump = mips_cpu_tlbdump;
4164     fp->interrupt = mips_cpu_interrupt;
4165     fp->interrupt_ack = mips_cpu_interrupt_ack;
4166     return 1;
4167     }
4168    
4169    
4170     #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26