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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26