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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26