/[gxemul]/trunk/src/cpu_mips.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpu_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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

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


1 /*
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 * $Id: cpu_mips.c,v 1.42 2005/06/11 20:59:11 debug Exp $
29 *
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 if ((dumpaddr & 3) != 0)
730 printf("WARNING: Unaligned address!\n");
731
732 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 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1613 cpu->cd.mips.pc_last, &offset);
1614 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 symbol? symbol : "(no symbol)");
1621
1622 #ifdef TRACE_NULL_CRASHES
1623 /* This can be useful for debugging kernel bugs: */
1624 {
1625 int i = cpu->trace_null_index;
1626 do {
1627 fatal("TRACE: 0x%016llx\n",
1628 cpu->trace_null_addr[i]);
1629 i ++;
1630 i %= TRACE_NULL_N_ENTRIES;
1631 } while (i != cpu->trace_null_index);
1632 }
1633 cpu->running = 0;
1634 cpu->dead = 1;
1635 #endif
1636 }
1637
1638 /* Clear the exception code bits of the cause register... */
1639 if (exc_model == EXC3K) {
1640 reg[COP0_CAUSE] &= ~R2K3K_CAUSE_EXCCODE_MASK;
1641 #if 0
1642 if (exccode >= 16) {
1643 fatal("exccode = %i (there are only 16 exceptions on R3000 and lower)\n", exccode);
1644 cpu->running = 0;
1645 return;
1646 }
1647 #endif
1648 } else
1649 reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
1650
1651 /* ... and OR in the exception code: */
1652 reg[COP0_CAUSE] |= (exccode << CAUSE_EXCCODE_SHIFT);
1653
1654 /* Always set CE (according to the R5000 manual): */
1655 reg[COP0_CAUSE] &= ~CAUSE_CE_MASK;
1656 reg[COP0_CAUSE] |= (coproc_nr << CAUSE_CE_SHIFT);
1657
1658 /* TODO: On R4000, vaddr should NOT be set on bus errors!!! */
1659 #if 0
1660 if (exccode == EXCEPTION_DBE) {
1661 reg[COP0_BADVADDR] = vaddr;
1662 /* sign-extend vaddr, if it is 32-bit */
1663 if ((vaddr >> 32) == 0 && (vaddr & 0x80000000ULL))
1664 reg[COP0_BADVADDR] |=
1665 0xffffffff00000000ULL;
1666 }
1667 #endif
1668
1669 if (tlb || (exccode >= EXCEPTION_MOD && exccode <= EXCEPTION_ADES) ||
1670 exccode == EXCEPTION_VCEI || exccode == EXCEPTION_VCED) {
1671 reg[COP0_BADVADDR] = vaddr;
1672 #if 1
1673 /* TODO: This should be removed. */
1674 /* sign-extend vaddr, if it is 32-bit */
1675 if ((vaddr >> 32) == 0 && (vaddr & 0x80000000ULL))
1676 reg[COP0_BADVADDR] |=
1677 0xffffffff00000000ULL;
1678 #endif
1679 if (exc_model == EXC3K) {
1680 reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
1681 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << R2K3K_CONTEXT_BADVPN_SHIFT) & R2K3K_CONTEXT_BADVPN_MASK);
1682
1683 reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)
1684 | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);
1685
1686 /* Sign-extend: */
1687 reg[COP0_CONTEXT] = (int64_t)(int32_t)reg[COP0_CONTEXT];
1688 reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];
1689 } else {
1690 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1691 reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK_R4100;
1692 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK_R4100);
1693
1694 /* TODO: fix these */
1695 reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1696 reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1697 reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1698 reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1699
1700 /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1701
1702 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800)) | vaddr_asid;
1703 } else {
1704 reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK;
1705 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK);
1706
1707 reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1708 reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1709 reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1710 reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1711
1712 /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1713
1714 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1715 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K)) | vaddr_asid;
1716 else
1717 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK)) | vaddr_asid;
1718 }
1719 }
1720 }
1721
1722 if (exc_model == EXC4K && reg[COP0_STATUS] & STATUS_EXL) {
1723 /*
1724 * Don't set EPC if STATUS_EXL is set, for R4000 and up.
1725 * This actually happens when running IRIX and Ultrix, when
1726 * they handle interrupts and/or tlb updates, I think, so
1727 * printing this with debug() looks better than with fatal().
1728 */
1729 /* debug("[ warning: cpu%i exception while EXL is set, not setting EPC ]\n", cpu->cpu_id); */
1730 } else {
1731 if (cpu->cd.mips.delay_slot || cpu->cd.mips.nullify_next) {
1732 reg[COP0_EPC] = cpu->cd.mips.pc_last - 4;
1733 reg[COP0_CAUSE] |= CAUSE_BD;
1734
1735 /* TODO: Should the BD flag actually be set
1736 on nullified slots? */
1737 } else {
1738 reg[COP0_EPC] = cpu->cd.mips.pc_last;
1739 reg[COP0_CAUSE] &= ~CAUSE_BD;
1740 }
1741 }
1742
1743 cpu->cd.mips.delay_slot = NOT_DELAYED;
1744 cpu->cd.mips.nullify_next = 0;
1745
1746 /* TODO: This is true for MIPS64, but how about others? */
1747 if (reg[COP0_STATUS] & STATUS_BEV)
1748 base = 0xffffffffbfc00200ULL;
1749 else
1750 base = 0xffffffff80000000ULL;
1751
1752 switch (exc_model) {
1753 case EXC3K:
1754 /* Userspace tlb, vs others: */
1755 if (tlb && !(vaddr & 0x80000000ULL) &&
1756 (exccode == EXCEPTION_TLBL || exccode == EXCEPTION_TLBS) )
1757 cpu->pc = base + 0x000;
1758 else
1759 cpu->pc = base + 0x080;
1760 break;
1761 default:
1762 /*
1763 * These offsets are according to the MIPS64 manual, but
1764 * should work with R4000 and the rest too (I hope).
1765 *
1766 * 0x000 TLB refill, if EXL=0
1767 * 0x080 64-bit XTLB refill, if EXL=0
1768 * 0x100 cache error (not implemented yet)
1769 * 0x180 general exception
1770 * 0x200 interrupt (if CAUSE_IV is set)
1771 */
1772 if (tlb && (exccode == EXCEPTION_TLBL ||
1773 exccode == EXCEPTION_TLBS) &&
1774 !(reg[COP0_STATUS] & STATUS_EXL)) {
1775 if (x_64)
1776 cpu->pc = base + 0x080;
1777 else
1778 cpu->pc = base + 0x000;
1779 } else {
1780 if (exccode == EXCEPTION_INT &&
1781 (reg[COP0_CAUSE] & CAUSE_IV))
1782 cpu->pc = base + 0x200;
1783 else
1784 cpu->pc = base + 0x180;
1785 }
1786 }
1787
1788 if (exc_model == EXC3K) {
1789 /* R2000/R3000: Shift the lowest 6 bits to the left two steps: */
1790 reg[COP0_STATUS] =
1791 (reg[COP0_STATUS] & ~0x3f) +
1792 ((reg[COP0_STATUS] & 0xf) << 2);
1793 } else {
1794 /* R4000: */
1795 reg[COP0_STATUS] |= STATUS_EXL;
1796 }
1797
1798 /* Sign-extend: */
1799 reg[COP0_CAUSE] = (int64_t)(int32_t)reg[COP0_CAUSE];
1800 reg[COP0_STATUS] = (int64_t)(int32_t)reg[COP0_STATUS];
1801 }
1802
1803
1804 #ifdef BINTRANS
1805 /*
1806 * mips_cpu_cause_simple_exception():
1807 *
1808 * Useful for causing raw exceptions from bintrans, for example
1809 * SYSCALL or BREAK.
1810 */
1811 void mips_cpu_cause_simple_exception(struct cpu *cpu, int exc_code)
1812 {
1813 mips_cpu_exception(cpu, exc_code, 0, 0, 0, 0, 0, 0);
1814 }
1815 #endif
1816
1817
1818 /* Included here for better cache characteristics: */
1819 #include "memory_mips.c"
1820
1821
1822 /*
1823 * mips_cpu_run_instr():
1824 *
1825 * Execute one instruction on a cpu.
1826 *
1827 * If we are in a delay slot, set cpu->pc to cpu->cd.mips.delay_jmpaddr
1828 * after the instruction is executed.
1829 *
1830 * Return value is the number of instructions executed during this call,
1831 * 0 if no instruction was executed.
1832 */
1833 int mips_cpu_run_instr(struct emul *emul, struct cpu *cpu)
1834 {
1835 int quiet_mode_cached = quiet_mode;
1836 int instruction_trace_cached = cpu->machine->instruction_trace;
1837 struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
1838 int i, tmp, ninstrs_executed;
1839 unsigned char instr[4];
1840 uint32_t instrword;
1841 uint64_t cached_pc;
1842 int hi6, special6, regimm5, rd, rs, rt, sa, imm;
1843 int copz, which_cache, cache_op;
1844
1845 int cond, likely, and_link;
1846
1847 /* for unaligned load/store */
1848 uint64_t dir, is_left, reg_ofs, reg_dir;
1849
1850 uint64_t tmpvalue, tmpaddr;
1851
1852 int cpnr; /* coprocessor nr */
1853
1854 /* for load/store */
1855 uint64_t addr, value, value_hi, result_value;
1856 int wlen, st, signd, linked;
1857 unsigned char d[16]; /* room for at most 128 bits */
1858
1859
1860 /*
1861 * Update Coprocessor 0 registers:
1862 *
1863 * The COUNT register needs to be updated on every [other] instruction.
1864 * The RANDOM register should decrease for every instruction.
1865 */
1866
1867 if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1868 int r = (cp0->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK) >> R2K3K_RANDOM_SHIFT;
1869 r --;
1870 if (r >= cp0->nr_of_tlbs || r < 8)
1871 r = cp0->nr_of_tlbs-1;
1872 cp0->reg[COP0_RANDOM] = r << R2K3K_RANDOM_SHIFT;
1873 } else {
1874 cp0->reg[COP0_RANDOM] --;
1875 if ((int64_t)cp0->reg[COP0_RANDOM] >= cp0->nr_of_tlbs ||
1876 (int64_t)cp0->reg[COP0_RANDOM] < (int64_t) cp0->reg[COP0_WIRED])
1877 cp0->reg[COP0_RANDOM] = cp0->nr_of_tlbs-1;
1878
1879 /*
1880 * TODO: only increase count every other instruction,
1881 * according to the R4000 manual. But according to the
1882 * R5000 manual: increment every other clock cycle.
1883 * Which one is it? :-)
1884 */
1885 cp0->reg[COP0_COUNT] = (int64_t)(int32_t)(cp0->reg[COP0_COUNT] + 1);
1886
1887 if (cpu->cd.mips.compare_register_set &&
1888 cp0->reg[COP0_COUNT] == cp0->reg[COP0_COMPARE]) {
1889 mips_cpu_interrupt(cpu, 7);
1890 cpu->cd.mips.compare_register_set = 0;
1891 }
1892 }
1893
1894
1895 #ifdef ENABLE_INSTRUCTION_DELAYS
1896 if (cpu->cd.mips.instruction_delay > 0) {
1897 cpu->cd.mips.instruction_delay --;
1898 return 1;
1899 }
1900 #endif
1901
1902 /* Cache the program counter in a local variable: */
1903 cached_pc = cpu->pc;
1904
1905 #ifdef TRACE_NULL_CRASHES
1906 cpu->trace_null_addr[cpu->trace_null_index] = cached_pc;
1907 cpu->trace_null_index ++;
1908 cpu->trace_null_index %= TRACE_NULL_N_ENTRIES;
1909 #endif
1910
1911 /* Hardwire the zero register to 0: */
1912 cpu->cd.mips.gpr[MIPS_GPR_ZERO] = 0;
1913
1914 if (cpu->cd.mips.delay_slot) {
1915 if (cpu->cd.mips.delay_slot == DELAYED) {
1916 cached_pc = cpu->pc = cpu->cd.mips.delay_jmpaddr;
1917 cpu->cd.mips.delay_slot = NOT_DELAYED;
1918 } else /* if (cpu->cd.mips.delay_slot == TO_BE_DELAYED) */ {
1919 /* next instruction will be delayed */
1920 cpu->cd.mips.delay_slot = DELAYED;
1921 }
1922 }
1923
1924 if (cpu->cd.mips.last_was_jumptoself > 0)
1925 cpu->cd.mips.last_was_jumptoself --;
1926
1927 /* Check PC against breakpoints: */
1928 if (!single_step)
1929 for (i=0; i<cpu->machine->n_breakpoints; i++)
1930 if (cached_pc == cpu->machine->breakpoint_addr[i]) {
1931 fatal("Breakpoint reached, pc=0x");
1932 if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1933 cpu->cd.mips.cpu_type.isa_level == 32)
1934 fatal("%08x", (int)cached_pc);
1935 else
1936 fatal("%016llx", (long long)cached_pc);
1937 fatal("\n");
1938 single_step = 1;
1939 return 0;
1940 }
1941
1942
1943 /* Remember where we are, in case of interrupt or exception: */
1944 cpu->cd.mips.pc_last = cached_pc;
1945
1946 /*
1947 * Any pending interrupts?
1948 *
1949 * If interrupts are enabled, and any interrupt has arrived (ie its
1950 * bit in the cause register is set) and corresponding enable bits
1951 * in the status register are set, then cause an interrupt exception
1952 * instead of executing the current instruction.
1953 *
1954 * NOTE: cached_interrupt_is_possible is set to 1 whenever an
1955 * interrupt bit in the cause register is set to one (in
1956 * mips_cpu_interrupt()) and set to 0 whenever all interrupt bits are
1957 * cleared (in mips_cpu_interrupt_ack()), so we don't need to do a
1958 * full check each time.
1959 */
1960 if (cpu->cd.mips.cached_interrupt_is_possible && !cpu->cd.mips.nullify_next) {
1961 if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1962 /* R3000: */
1963 int enabled, mask;
1964 int status = cp0->reg[COP0_STATUS];
1965
1966 enabled = status & MIPS_SR_INT_IE;
1967 mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1968 if (enabled && mask) {
1969 mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1970 return 0;
1971 }
1972 } else {
1973 /* R4000 and others: */
1974 int enabled, mask;
1975 int status = cp0->reg[COP0_STATUS];
1976
1977 enabled = (status & STATUS_IE)
1978 && !(status & STATUS_EXL)
1979 && !(status & STATUS_ERL);
1980
1981 mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1982 if (enabled && mask) {
1983 mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1984 return 0;
1985 }
1986 }
1987 }
1988
1989
1990 /*
1991 * ROM emulation:
1992 *
1993 * This assumes that a jal was made to a ROM address,
1994 * and we should return via gpr ra.
1995 */
1996 if ((cached_pc & 0xfff00000) == 0xbfc00000 &&
1997 cpu->machine->prom_emulation) {
1998 int rom_jal, res = 1;
1999 switch (cpu->machine->machine_type) {
2000 case MACHINE_DEC:
2001 res = decstation_prom_emul(cpu);
2002 rom_jal = 1;
2003 break;
2004 case MACHINE_PS2:
2005 res = playstation2_sifbios_emul(cpu);
2006 rom_jal = 1;
2007 break;
2008 case MACHINE_ARC:
2009 case MACHINE_SGI:
2010 res = arcbios_emul(cpu);
2011 rom_jal = 1;
2012 break;
2013 default:
2014 rom_jal = 0;
2015 }
2016
2017 if (rom_jal) {
2018 /*
2019 * Special hack: If the PROM emulation layer needs
2020 * to loop (for example when emulating blocking
2021 * console input) then we should simply return, so
2022 * that the same PROM routine is called on the next
2023 * round as well.
2024 *
2025 * This still has to count as one or more
2026 * instructions, so 1000 is returned. (Ugly.)
2027 */
2028 if (!res)
2029 return 1000;
2030
2031 cpu->pc = cpu->cd.mips.gpr[MIPS_GPR_RA];
2032 /* no need to update cached_pc, as we're returning */
2033 cpu->cd.mips.delay_slot = NOT_DELAYED;
2034
2035 if (!quiet_mode_cached &&
2036 cpu->machine->show_trace_tree)
2037 cpu->cd.mips.trace_tree_depth --;
2038
2039 /* TODO: how many instrs should this count as? */
2040 return 10;
2041 }
2042 }
2043
2044 #ifdef ALWAYS_SIGNEXTEND_32
2045 /*
2046 * An extra check for 32-bit mode to make sure that all
2047 * registers are sign-extended: (Slow, but might be useful
2048 * to detect bugs that have to do with sign-extension.)
2049 */
2050 if (cpu->cd.mips.cpu_type.isa_level < 3 || cpu->cd.mips.cpu_type.isa_level == 32) {
2051 int warning = 0;
2052 uint64_t x;
2053
2054 if (cpu->cd.mips.gpr[0] != 0) {
2055 fatal("\nWARNING: r0 was not zero! (%016llx)\n\n",
2056 (long long)cpu->cd.mips.gpr[0]);
2057 cpu->cd.mips.gpr[0] = 0;
2058 warning = 1;
2059 }
2060
2061 if (cpu->pc != (int64_t)(int32_t)cpu->pc) {
2062 fatal("\nWARNING: pc was not sign-extended correctly"
2063 " (%016llx)\n\n", (long long)cpu->pc);
2064 cpu->pc = (int64_t)(int32_t)cpu->pc;
2065 warning = 1;
2066 }
2067
2068 if (cpu->cd.mips.pc_last != (int64_t)(int32_t)cpu->cd.mips.pc_last) {
2069 fatal("\nWARNING: pc_last was not sign-extended correc"
2070 "tly (%016llx)\n\n", (long long)cpu->cd.mips.pc_last);
2071 cpu->cd.mips.pc_last = (int64_t)(int32_t)cpu->cd.mips.pc_last;
2072 warning = 1;
2073 }
2074
2075 /* Sign-extend ALL registers, including coprocessor registers and tlbs: */
2076 for (i=1; i<32; i++) {
2077 x = cpu->cd.mips.gpr[i];
2078 cpu->cd.mips.gpr[i] &= 0xffffffff;
2079 if (cpu->cd.mips.gpr[i] & 0x80000000ULL)
2080 cpu->cd.mips.gpr[i] |= 0xffffffff00000000ULL;
2081 if (x != cpu->cd.mips.gpr[i]) {
2082 fatal("\nWARNING: r%i (%s) was not sign-"
2083 "extended correctly (%016llx != "
2084 "%016llx)\n\n", i, regname(cpu->machine, i),
2085 (long long)x, (long long)cpu->cd.mips.gpr[i]);
2086 warning = 1;
2087 }
2088 }
2089 for (i=0; i<32; i++) {
2090 x = cpu->cd.mips.coproc[0]->reg[i];
2091 cpu->cd.mips.coproc[0]->reg[i] &= 0xffffffffULL;
2092 if (cpu->cd.mips.coproc[0]->reg[i] & 0x80000000ULL)
2093 cpu->cd.mips.coproc[0]->reg[i] |=
2094 0xffffffff00000000ULL;
2095 if (x != cpu->cd.mips.coproc[0]->reg[i]) {
2096 fatal("\nWARNING: cop0,r%i was not sign-extended correctly (%016llx != %016llx)\n\n",
2097 i, (long long)x, (long long)cpu->cd.mips.coproc[0]->reg[i]);
2098 warning = 1;
2099 }
2100 }
2101 for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
2102 x = cpu->cd.mips.coproc[0]->tlbs[i].hi;
2103 cpu->cd.mips.coproc[0]->tlbs[i].hi &= 0xffffffffULL;
2104 if (cpu->cd.mips.coproc[0]->tlbs[i].hi & 0x80000000ULL)
2105 cpu->cd.mips.coproc[0]->tlbs[i].hi |=
2106 0xffffffff00000000ULL;
2107 if (x != cpu->cd.mips.coproc[0]->tlbs[i].hi) {
2108 fatal("\nWARNING: tlb[%i].hi was not sign-extended correctly (%016llx != %016llx)\n\n",
2109 i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].hi);
2110 warning = 1;
2111 }
2112
2113 x = cpu->cd.mips.coproc[0]->tlbs[i].lo0;
2114 cpu->cd.mips.coproc[0]->tlbs[i].lo0 &= 0xffffffffULL;
2115 if (cpu->cd.mips.coproc[0]->tlbs[i].lo0 & 0x80000000ULL)
2116 cpu->cd.mips.coproc[0]->tlbs[i].lo0 |=
2117 0xffffffff00000000ULL;
2118 if (x != cpu->cd.mips.coproc[0]->tlbs[i].lo0) {
2119 fatal("\nWARNING: tlb[%i].lo0 was not sign-extended correctly (%016llx != %016llx)\n\n",
2120 i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].lo0);
2121 warning = 1;
2122 }
2123 }
2124
2125 if (warning) {
2126 fatal("Halting. pc = %016llx\n", (long long)cpu->pc);
2127 cpu->running = 0;
2128 }
2129 }
2130 #endif
2131
2132 PREFETCH(cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff));
2133
2134 #ifdef HALT_IF_PC_ZERO
2135 /* Halt if PC = 0: */
2136 if (cached_pc == 0) {
2137 debug("cpu%i: pc=0, halting\n", cpu->cpu_id);
2138 cpu->running = 0;
2139 return 0;
2140 }
2141 #endif
2142
2143
2144
2145 #ifdef BINTRANS
2146 if ((single_step || instruction_trace_cached)
2147 && cpu->machine->bintrans_enable)
2148 cpu->cd.mips.dont_run_next_bintrans = 1;
2149 #endif
2150
2151
2152 if (!quiet_mode_cached) {
2153 /* Dump CPU registers for debugging: */
2154 if (cpu->machine->register_dump) {
2155 debug("\n");
2156 mips_cpu_register_dump(cpu, 1, 0x1);
2157 }
2158
2159 /* Trace tree: */
2160 if (cpu->machine->show_trace_tree && cpu->cd.mips.show_trace_delay > 0) {
2161 cpu->cd.mips.show_trace_delay --;
2162 if (cpu->cd.mips.show_trace_delay == 0)
2163 show_trace(cpu, cpu->cd.mips.show_trace_addr);
2164 }
2165 }
2166
2167 #ifdef MFHILO_DELAY
2168 /* Decrease the MFHI/MFLO delays: */
2169 if (cpu->mfhi_delay > 0)
2170 cpu->mfhi_delay--;
2171 if (cpu->mflo_delay > 0)
2172 cpu->mflo_delay--;
2173 #endif
2174
2175 /* Read an instruction from memory: */
2176 #ifdef ENABLE_MIPS16
2177 if (cpu->cd.mips.mips16 && (cached_pc & 1)) {
2178 /* 16-bit instruction word: */
2179 unsigned char instr16[2];
2180 int mips16_offset = 0;
2181
2182 if (!cpu->memory_rw(cpu, cpu->mem, cached_pc ^ 1, &instr16[0],
2183 sizeof(instr16), MEM_READ, CACHE_INSTRUCTION))
2184 return 0;
2185
2186 /* TODO: If Reverse-endian is set in the status cop0 register, and
2187 we are in usermode, then reverse endianness! */
2188
2189 /* The rest of the code is written for little endian, so swap if necessary: */
2190 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2191 int tmp;
2192 tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2193 }
2194
2195 cpu->cd.mips.mips16_extend = 0;
2196
2197 /*
2198 * Translate into 32-bit instruction, little endian (instr[3..0]):
2199 *
2200 * This ugly loop is necessary because if we would get an exception between
2201 * reading an extend instruction and the next instruction, and execution
2202 * continues on the second instruction, the extend data would be lost. So the
2203 * entire instruction (the two parts) need to be read in. If an exception is
2204 * caused, it will appear as if it was caused when reading the extend instruction.
2205 */
2206 while (mips16_to_32(cpu, instr16, instr) == 0) {
2207 if (instruction_trace_cached)
2208 debug("cpu%i @ %016llx: %02x%02x\t\t\textend\n",
2209 cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2210 instr16[1], instr16[0]);
2211
2212 /* instruction with extend: */
2213 mips16_offset += 2;
2214 if (!cpu->memory_rw(cpu, cpu->mem, (cached_pc ^ 1) +
2215 mips16_offset, &instr16[0], sizeof(instr16),
2216 MEM_READ, CACHE_INSTRUCTION))
2217 return 0;
2218
2219 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2220 int tmp;
2221 tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2222 }
2223 }
2224
2225 /* TODO: bintrans like in 32-bit mode? */
2226
2227 /* Advance the program counter: */
2228 cpu->pc += sizeof(instr16) + mips16_offset;
2229 cached_pc = cpu->pc;
2230
2231 if (instruction_trace_cached) {
2232 uint64_t offset;
2233 char *symbol = get_symbol_name(&cpu->machine->
2234 symbol_context, cpu->cd.mips.pc_last ^ 1, &offset);
2235 if (symbol != NULL && offset==0)
2236 debug("<%s>\n", symbol);
2237
2238 debug("cpu%i @ %016llx: %02x%02x => %02x%02x%02x%02x%s\t",
2239 cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2240 instr16[1], instr16[0],
2241 instr[3], instr[2], instr[1], instr[0],
2242 cpu_flags(cpu));
2243 }
2244 } else
2245 #endif
2246 {
2247 /*
2248 * Fetch a 32-bit instruction word from memory:
2249 *
2250 * 1) The special case of reading an instruction from the
2251 * same host RAM page as the last one is handled here,
2252 * to gain a little bit performance.
2253 *
2254 * 2) Fallback to reading from memory the usual way.
2255 */
2256 if (cpu->cd.mips.pc_last_host_4k_page != NULL &&
2257 (cached_pc & ~0xfff) == cpu->cd.mips.pc_last_virtual_page) {
2258 /* NOTE: This only works on the host if offset is
2259 aligned correctly! (TODO) */
2260 *(uint32_t *)instr = *(uint32_t *)
2261 (cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff));
2262 #ifdef BINTRANS
2263 cpu->cd.mips.pc_bintrans_paddr_valid = 1;
2264 cpu->cd.mips.pc_bintrans_paddr =
2265 cpu->cd.mips.pc_last_physical_page | (cached_pc & 0xfff);
2266 cpu->cd.mips.pc_bintrans_host_4kpage = cpu->cd.mips.pc_last_host_4k_page;
2267 #endif
2268 } else {
2269 if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
2270 sizeof(instr), MEM_READ, CACHE_INSTRUCTION))
2271 return 0;
2272 }
2273
2274 #ifdef BINTRANS
2275 if (cpu->cd.mips.dont_run_next_bintrans) {
2276 cpu->cd.mips.dont_run_next_bintrans = 0;
2277 } else if (cpu->machine->bintrans_enable &&
2278 cpu->cd.mips.pc_bintrans_paddr_valid) {
2279 int res;
2280 cpu->cd.mips.bintrans_instructions_executed = 0;
2281
2282 res = bintrans_attempt_translate(cpu,
2283 cpu->cd.mips.pc_bintrans_paddr);
2284
2285 if (res >= 0) {
2286 /* debug("BINTRANS translation + hit,"
2287 " pc = %016llx\n", (long long)cached_pc); */
2288 if (res > 0 || cpu->pc != cached_pc) {
2289 if (instruction_trace_cached)
2290 mips_cpu_disassemble_instr(cpu, instr, 1, 0, 1);
2291 if (res & BINTRANS_DONT_RUN_NEXT)
2292 cpu->cd.mips.dont_run_next_bintrans = 1;
2293 res &= BINTRANS_N_MASK;
2294
2295 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2296 int x = cp0->reg[COP0_COUNT], y = cp0->reg[COP0_COMPARE];
2297 int diff = x - y;
2298 if (diff < 0 && diff + (res-1) >= 0
2299 && cpu->cd.mips.compare_register_set) {
2300 mips_cpu_interrupt(cpu, 7);
2301 cpu->cd.mips.compare_register_set = 0;
2302 }
2303
2304 cp0->reg[COP0_COUNT] = (int64_t)
2305 (int32_t)(cp0->reg[COP0_COUNT] + res-1);
2306 }
2307
2308 return res;
2309 }
2310 }
2311 }
2312 #endif
2313
2314 if (instruction_trace_cached)
2315 mips_cpu_disassemble_instr(cpu, instr, 1, 0, 0);
2316
2317 /* Advance the program counter: */
2318 cpu->pc += sizeof(instr);
2319 cached_pc = cpu->pc;
2320
2321 /*
2322 * TODO: If Reverse-endian is set in the status cop0 register
2323 * and we are in usermode, then reverse endianness!
2324 */
2325
2326 /*
2327 * The rest of the code is written for little endian, so
2328 * swap if necessary:
2329 */
2330 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2331 instrword = instr[0]; instr[0] = instr[3];
2332 instr[3] = instrword;
2333 instrword = instr[1]; instr[1] = instr[2];
2334 instr[2] = instrword;
2335 }
2336 }
2337
2338
2339 /*
2340 * Nullify this instruction? (Set by a previous branch-likely
2341 * instruction.)
2342 *
2343 * Note: The return value is 1, even if no instruction was actually
2344 * executed.
2345 */
2346 if (cpu->cd.mips.nullify_next) {
2347 cpu->cd.mips.nullify_next = 0;
2348 return 1;
2349 }
2350
2351
2352 /*
2353 * Execute the instruction:
2354 */
2355
2356 /* Get the top 6 bits of the instruction: */
2357 hi6 = instr[3] >> 2; /* & 0x3f */
2358
2359 if (show_opcode_statistics)
2360 cpu->cd.mips.stats_opcode[hi6] ++;
2361
2362 switch (hi6) {
2363 case HI6_SPECIAL:
2364 special6 = instr[0] & 0x3f;
2365
2366 if (show_opcode_statistics)
2367 cpu->cd.mips.stats__special[special6] ++;
2368
2369 switch (special6) {
2370 case SPECIAL_SLL:
2371 case SPECIAL_SRL:
2372 case SPECIAL_SRA:
2373 case SPECIAL_DSLL:
2374 case SPECIAL_DSRL:
2375 case SPECIAL_DSRA:
2376 case SPECIAL_DSLL32:
2377 case SPECIAL_DSRL32:
2378 case SPECIAL_DSRA32:
2379 rt = instr[2] & 31;
2380 rd = (instr[1] >> 3) & 31;
2381 sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
2382
2383 /*
2384 * Check for NOP:
2385 *
2386 * The R4000 manual says that a shift amount of zero
2387 * is treated as a nop by some assemblers. Checking
2388 * for sa == 0 here would not be correct, though,
2389 * because instructions such as sll r3,r4,0 are
2390 * possible, and are definitely not a nop.
2391 * Instead, check if the destination register is r0.
2392 *
2393 * TODO: ssnop should wait until the _next_
2394 * cycle boundary, or something like that. The
2395 * code here is incorrect.
2396 */
2397 if (rd == 0 && special6 == SPECIAL_SLL) {
2398 if (sa == 1) {
2399 /* ssnop */
2400 #ifdef ENABLE_INSTRUCTION_DELAYS
2401 cpu->cd.mips.instruction_delay +=
2402 cpu->cd.mips.cpu_type.
2403 instrs_per_cycle - 1;
2404 #endif
2405 }
2406 return 1;
2407 }
2408
2409 if (special6 == SPECIAL_SLL) {
2410 switch (sa) {
2411 case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 8; break;
2412 case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 16; break;
2413 default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2414 }
2415 /* Sign-extend rd: */
2416 cpu->cd.mips.gpr[rd] = (int64_t) (int32_t) cpu->cd.mips.gpr[rd];
2417 }
2418 if (special6 == SPECIAL_DSLL) {
2419 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2420 }
2421 if (special6 == SPECIAL_DSRL) {
2422 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2423 }
2424 if (special6 == SPECIAL_DSLL32) {
2425 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << (sa + 32);
2426 }
2427 if (special6 == SPECIAL_SRL) {
2428 /*
2429 * Three cases:
2430 * shift amount = zero: just copy
2431 * high bit of rt zero: plain shift right (of all bits)
2432 * high bit of rt one: plain shift right (of lowest 32 bits)
2433 */
2434 if (sa == 0)
2435 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2436 else if (!(cpu->cd.mips.gpr[rt] & 0x80000000ULL)) {
2437 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2438 } else
2439 cpu->cd.mips.gpr[rd] = (cpu->cd.mips.gpr[rt] & 0xffffffffULL) >> sa;
2440 }
2441 if (special6 == SPECIAL_SRA) {
2442 int topbit = cpu->cd.mips.gpr[rt] & 0x80000000ULL;
2443 switch (sa) {
2444 case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 8; break;
2445 case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 16; break;
2446 default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2447 }
2448 if (topbit)
2449 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2450 }
2451 if (special6 == SPECIAL_DSRL32) {
2452 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> (sa + 32);
2453 }
2454 if (special6 == SPECIAL_DSRA32 || special6 == SPECIAL_DSRA) {
2455 if (special6 == SPECIAL_DSRA32)
2456 sa += 32;
2457 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2458 while (sa > 0) {
2459 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2460 sa--;
2461 if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old signbit */
2462 cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2463 }
2464 }
2465 return 1;
2466 case SPECIAL_DSRLV:
2467 case SPECIAL_DSRAV:
2468 case SPECIAL_DSLLV:
2469 case SPECIAL_SLLV:
2470 case SPECIAL_SRAV:
2471 case SPECIAL_SRLV:
2472 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2473 rt = instr[2] & 31;
2474 rd = (instr[1] >> 3) & 31;
2475
2476 if (special6 == SPECIAL_DSRLV) {
2477 sa = cpu->cd.mips.gpr[rs] & 63;
2478 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2479 }
2480 if (special6 == SPECIAL_DSRAV) {
2481 sa = cpu->cd.mips.gpr[rs] & 63;
2482 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2483 while (sa > 0) {
2484 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2485 sa--;
2486 if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old sign-bit */
2487 cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2488 }
2489 }
2490 if (special6 == SPECIAL_DSLLV) {
2491 sa = cpu->cd.mips.gpr[rs] & 63;
2492 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2493 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2494 }
2495 if (special6 == SPECIAL_SLLV) {
2496 sa = cpu->cd.mips.gpr[rs] & 31;
2497 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2498 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2499 /* Sign-extend rd: */
2500 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2501 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2502 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2503 }
2504 if (special6 == SPECIAL_SRAV) {
2505 sa = cpu->cd.mips.gpr[rs] & 31;
2506 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2507 /* Sign-extend rd: */
2508 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2509 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2510 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2511 while (sa > 0) {
2512 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2513 sa--;
2514 }
2515 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2516 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2517 }
2518 if (special6 == SPECIAL_SRLV) {
2519 sa = cpu->cd.mips.gpr[rs] & 31;
2520 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2521 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2522 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> sa;
2523 /* And finally sign-extend rd: */
2524 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2525 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2526 }
2527 return 1;
2528 case SPECIAL_JR:
2529 if (cpu->cd.mips.delay_slot) {
2530 fatal("jr: jump inside a jump's delay slot, or similar. TODO\n");
2531 cpu->running = 0;
2532 return 1;
2533 }
2534
2535 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2536
2537 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2538 cpu->cd.mips.delay_jmpaddr = cpu->cd.mips.gpr[rs];
2539
2540 if (!quiet_mode_cached && cpu->machine->show_trace_tree
2541 && rs == 31) {
2542 cpu->cd.mips.trace_tree_depth --;
2543 }
2544
2545 return 1;
2546 case SPECIAL_JALR:
2547 if (cpu->cd.mips.delay_slot) {
2548 fatal("jalr: jump inside a jump's delay slot, or similar. TODO\n");
2549 cpu->running = 0;
2550 return 1;
2551 }
2552
2553 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2554 rd = (instr[1] >> 3) & 31;
2555
2556 tmpvalue = cpu->cd.mips.gpr[rs];
2557 cpu->cd.mips.gpr[rd] = cached_pc + 4;
2558 /* already increased by 4 earlier */
2559
2560 if (!quiet_mode_cached && cpu->machine->show_trace_tree
2561 && rd == 31) {
2562 cpu->cd.mips.show_trace_delay = 2;
2563 cpu->cd.mips.show_trace_addr = tmpvalue;
2564 }
2565
2566 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2567 cpu->cd.mips.delay_jmpaddr = tmpvalue;
2568 return 1;
2569 case SPECIAL_MFHI:
2570 case SPECIAL_MFLO:
2571 rd = (instr[1] >> 3) & 31;
2572
2573 if (special6 == SPECIAL_MFHI) {
2574 cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
2575 #ifdef MFHILO_DELAY
2576 cpu->mfhi_delay = 3;
2577 #endif
2578 }
2579 if (special6 == SPECIAL_MFLO) {
2580 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2581 #ifdef MFHILO_DELAY
2582 cpu->mflo_delay = 3;
2583 #endif
2584 }
2585 return 1;
2586 case SPECIAL_ADD:
2587 case SPECIAL_ADDU:
2588 case SPECIAL_SUB:
2589 case SPECIAL_SUBU:
2590 case SPECIAL_AND:
2591 case SPECIAL_OR:
2592 case SPECIAL_XOR:
2593 case SPECIAL_NOR:
2594 case SPECIAL_SLT:
2595 case SPECIAL_SLTU:
2596 case SPECIAL_MTLO:
2597 case SPECIAL_MTHI:
2598 case SPECIAL_MULT:
2599 case SPECIAL_MULTU:
2600 case SPECIAL_DMULT:
2601 case SPECIAL_DMULTU:
2602 case SPECIAL_DIV:
2603 case SPECIAL_DIVU:
2604 case SPECIAL_DDIV:
2605 case SPECIAL_DDIVU:
2606 case SPECIAL_TGE:
2607 case SPECIAL_TGEU:
2608 case SPECIAL_TLT:
2609 case SPECIAL_TLTU:
2610 case SPECIAL_TEQ:
2611 case SPECIAL_TNE:
2612 case SPECIAL_DADD:
2613 case SPECIAL_DADDU:
2614 case SPECIAL_DSUB:
2615 case SPECIAL_DSUBU:
2616 case SPECIAL_MOVZ:
2617 case SPECIAL_MOVN:
2618 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2619 rt = instr[2] & 31;
2620 rd = (instr[1] >> 3) & 31;
2621
2622 #ifdef MFHILO_DELAY
2623 if (cpu->mflo_delay > 0 && (
2624 special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2625 special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2626 special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2627 special6 == SPECIAL_MTLO || special6 == SPECIAL_MULT
2628 || special6 == SPECIAL_MULTU
2629 ) )
2630 debug("warning: instruction modifying LO too early after mflo!\n");
2631
2632 if (cpu->mfhi_delay > 0 && (
2633 special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2634 special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2635 special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2636 special6 == SPECIAL_MTHI || special6 == SPECIAL_MULT
2637 || special6 == SPECIAL_MULTU
2638 ) )
2639 debug("warning: instruction modifying HI too early after mfhi!\n");
2640 #endif
2641
2642 if (special6 == SPECIAL_ADDU) {
2643 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2644 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2645 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2646 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2647 break;
2648 }
2649 if (special6 == SPECIAL_ADD) {
2650 /* According to the MIPS64 manual: */
2651 uint64_t temp, temp1, temp2;
2652 temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2653 temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2654 temp = temp1 + temp2;
2655 #if 0
2656 /* TODO: apparently this doesn't work (an example of
2657 something that breaks is NetBSD/sgimips' mips3_TBIA() */
2658 /* If bits 32 and 31 of temp differ, then it's an overflow */
2659 temp1 = temp & 0x100000000ULL;
2660 temp2 = temp & 0x80000000ULL;
2661 if ((temp1 && !temp2) || (!temp1 && temp2)) {
2662 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2663 break;
2664 }
2665 #endif
2666 cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2667 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2668 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2669 break;
2670 }
2671 if (special6 == SPECIAL_SUBU) {
2672 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2673 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2674 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2675 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2676 break;
2677 }
2678 if (special6 == SPECIAL_SUB) {
2679 /* According to the MIPS64 manual: */
2680 uint64_t temp, temp1, temp2;
2681 temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2682 temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2683 temp = temp1 - temp2;
2684 #if 0
2685 /* If bits 32 and 31 of temp differ, then it's an overflow */
2686 temp1 = temp & 0x100000000ULL;
2687 temp2 = temp & 0x80000000ULL;
2688 if ((temp1 && !temp2) || (!temp1 && temp2)) {
2689 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2690 break;
2691 }
2692 #endif
2693 cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2694 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2695 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2696 break;
2697 }
2698
2699 if (special6 == SPECIAL_AND) {
2700 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] & cpu->cd.mips.gpr[rt];
2701 break;
2702 }
2703 if (special6 == SPECIAL_OR) {
2704 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
2705 break;
2706 }
2707 if (special6 == SPECIAL_XOR) {
2708 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] ^ cpu->cd.mips.gpr[rt];
2709 break;
2710 }
2711 if (special6 == SPECIAL_NOR) {
2712 cpu->cd.mips.gpr[rd] = ~(cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt]);
2713 break;
2714 }
2715 if (special6 == SPECIAL_SLT) {
2716 cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt];
2717 break;
2718 }
2719 if (special6 == SPECIAL_SLTU) {
2720 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt];
2721 break;
2722 }
2723 if (special6 == SPECIAL_MTLO) {
2724 cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
2725 break;
2726 }
2727 if (special6 == SPECIAL_MTHI) {
2728 cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
2729 break;
2730 }
2731 if (special6 == SPECIAL_MULT) {
2732 int64_t f1, f2, sum;
2733 f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2734 /* sign extend f1 */
2735 if (f1 & 0x80000000ULL)
2736 f1 |= 0xffffffff00000000ULL;
2737 f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2738 /* sign extend f2 */
2739 if (f2 & 0x80000000ULL)
2740 f2 |= 0xffffffff00000000ULL;
2741 sum = f1 * f2;
2742
2743 cpu->cd.mips.lo = sum & 0xffffffffULL;
2744 cpu->cd.mips.hi = ((uint64_t)sum >> 32) & 0xffffffffULL;
2745
2746 /* sign-extend: */
2747 if (cpu->cd.mips.lo & 0x80000000ULL)
2748 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2749 if (cpu->cd.mips.hi & 0x80000000ULL)
2750 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2751
2752 /*
2753 * NOTE: The stuff about rd!=0 is just a
2754 * guess, judging from how some NetBSD code
2755 * seems to execute. It is not documented in
2756 * the MIPS64 ISA docs :-/
2757 */
2758
2759 if (rd != 0) {
2760 if (cpu->cd.mips.cpu_type.rev != MIPS_R5900)
2761 debug("WARNING! mult_xx is an undocumented instruction!");
2762 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2763 }
2764 break;
2765 }
2766 if (special6 == SPECIAL_MULTU) {
2767 uint64_t f1, f2, sum;
2768 /* zero extend f1 and f2 */
2769 f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2770 f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2771 sum = f1 * f2;
2772 cpu->cd.mips.lo = sum & 0xffffffffULL;
2773 cpu->cd.mips.hi = (sum >> 32) & 0xffffffffULL;
2774
2775 /* sign-extend: */
2776 if (cpu->cd.mips.lo & 0x80000000ULL)
2777 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2778 if (cpu->cd.mips.hi & 0x80000000ULL)
2779 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2780 break;
2781 }
2782 /*
2783 * TODO: I'm too tired to think now. DMULT is probably
2784 * correct, but is DMULTU? (Unsigned 64x64 multiply.)
2785 * Or, hm, perhaps it is dmult which is incorrect.
2786 */
2787 if (special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU) {
2788 /* 64x64 = 128 bit multiplication: SLOW!!! TODO */
2789 uint64_t i, low_add, high_add;
2790
2791 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2792 for (i=0; i<64; i++) {
2793 uint64_t bit = cpu->cd.mips.gpr[rt] & ((uint64_t)1 << i);
2794 if (bit) {
2795 /* Add cpu->cd.mips.gpr[rs] to hi and lo: */
2796 low_add = (cpu->cd.mips.gpr[rs] << i);
2797 high_add = (cpu->cd.mips.gpr[rs] >> (64-i));
2798 if (i==0) /* WEIRD BUG in the compiler? Or maybe I'm just stupid */
2799 high_add = 0; /* these lines are necessary, a >> 64 doesn't seem to do anything */
2800 if (cpu->cd.mips.lo + low_add < cpu->cd.mips.lo)
2801 cpu->cd.mips.hi ++;
2802 cpu->cd.mips.lo += low_add;
2803 cpu->cd.mips.hi += high_add;
2804 }
2805 }
2806 break;
2807 }
2808 if (special6 == SPECIAL_DIV) {
2809 int64_t a, b;
2810 /* Signextend rs and rt: */
2811 a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2812 if (a & 0x80000000ULL)
2813 a |= 0xffffffff00000000ULL;
2814 b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2815 if (b & 0x80000000ULL)
2816 b |= 0xffffffff00000000ULL;
2817
2818 if (b == 0) {
2819 /* undefined */
2820 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2821 } else {
2822 cpu->cd.mips.lo = a / b;
2823 cpu->cd.mips.hi = a % b;
2824 }
2825 /* Sign-extend lo and hi: */
2826 cpu->cd.mips.lo &= 0xffffffffULL;
2827 if (cpu->cd.mips.lo & 0x80000000ULL)
2828 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2829 cpu->cd.mips.hi &= 0xffffffffULL;
2830 if (cpu->cd.mips.hi & 0x80000000ULL)
2831 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2832 break;
2833 }
2834 if (special6 == SPECIAL_DIVU) {
2835 int64_t a, b;
2836 /* Zero-extend rs and rt: */
2837 a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2838 b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2839 if (b == 0) {
2840 /* undefined */
2841 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2842 } else {
2843 cpu->cd.mips.lo = a / b;
2844 cpu->cd.mips.hi = a % b;
2845 }
2846 /* Sign-extend lo and hi: */
2847 cpu->cd.mips.lo &= 0xffffffffULL;
2848 if (cpu->cd.mips.lo & 0x80000000ULL)
2849 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2850 cpu->cd.mips.hi &= 0xffffffffULL;
2851 if (cpu->cd.mips.hi & 0x80000000ULL)
2852 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2853 break;
2854 }
2855 if (special6 == SPECIAL_DDIV) {
2856 if (cpu->cd.mips.gpr[rt] == 0) {
2857 cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2858 } else {
2859 cpu->cd.mips.lo = (int64_t)cpu->cd.mips.gpr[rs] / (int64_t)cpu->cd.mips.gpr[rt];
2860 cpu->cd.mips.hi = (int64_t)cpu->cd.mips.gpr[rs] % (int64_t)cpu->cd.mips.gpr[rt];
2861 }
2862 break;
2863 }
2864 if (special6 == SPECIAL_DDIVU) {
2865 if (cpu->cd.mips.gpr[rt] == 0) {
2866 cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2867 } else {
2868 cpu->cd.mips.lo = cpu->cd.mips.gpr[rs] / cpu->cd.mips.gpr[rt];
2869 cpu->cd.mips.hi = cpu->cd.mips.gpr[rs] % cpu->cd.mips.gpr[rt];
2870 }
2871 break;
2872 }
2873 if (special6 == SPECIAL_TGE) {
2874 if ((int64_t)cpu->cd.mips.gpr[rs] >= (int64_t)cpu->cd.mips.gpr[rt])
2875 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2876 break;
2877 }
2878 if (special6 == SPECIAL_TGEU) {
2879 if (cpu->cd.mips.gpr[rs] >= cpu->cd.mips.gpr[rt])
2880 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2881 break;
2882 }
2883 if (special6 == SPECIAL_TLT) {
2884 if ((int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt])
2885 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2886 break;
2887 }
2888 if (special6 == SPECIAL_TLTU) {
2889 if (cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt])
2890 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2891 break;
2892 }
2893 if (special6 == SPECIAL_TEQ) {
2894 if (cpu->cd.mips.gpr[rs] == cpu->cd.mips.gpr[rt])
2895 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2896 break;
2897 }
2898 if (special6 == SPECIAL_TNE) {
2899 if (cpu->cd.mips.gpr[rs] != cpu->cd.mips.gpr[rt])
2900 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2901 break;
2902 }
2903 if (special6 == SPECIAL_DADD) {
2904 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2905 /* TODO: exception on overflow */
2906 break;
2907 }
2908 if (special6 == SPECIAL_DADDU) {
2909 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2910 break;
2911 }
2912 if (special6 == SPECIAL_DSUB) {
2913 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2914 /* TODO: exception on overflow */
2915 break;
2916 }
2917 if (special6 == SPECIAL_DSUBU) {
2918 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2919 break;
2920 }
2921 if (special6 == SPECIAL_MOVZ) {
2922 if (cpu->cd.mips.gpr[rt] == 0)
2923 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2924 break;
2925 }
2926 if (special6 == SPECIAL_MOVN) {
2927 if (cpu->cd.mips.gpr[rt] != 0)
2928 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2929 return 1;
2930 }
2931 return 1;
2932 case SPECIAL_SYNC:
2933 imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
2934 /* TODO: actually sync */
2935
2936 /* Clear the LLbit (at least on R10000): */
2937 cpu->cd.mips.rmw = 0;
2938 return 1;
2939 case SPECIAL_SYSCALL:
2940 imm = ((instr[3] << 24) + (instr[2] << 16) +
2941 (instr[1] << 8) + instr[0]) >> 6;
2942 imm &= 0xfffff;
2943
2944 if (cpu->machine->userland_emul != NULL)
2945 useremul_syscall(cpu, imm);
2946 else
2947 mips_cpu_exception(cpu, EXCEPTION_SYS,
2948 0, 0, 0, 0, 0, 0);
2949 return 1;
2950 case SPECIAL_BREAK:
2951 mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
2952 return 1;
2953 case SPECIAL_MFSA:
2954 /* R5900? What on earth does this thing do? */
2955 rd = (instr[1] >> 3) & 31;
2956 /* TODO */
2957 return 1;
2958 case SPECIAL_MTSA:
2959 /* R5900? What on earth does this thing do? */
2960 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2961 /* TODO */
2962 return 1;
2963 default:
2964 if (!instruction_trace_cached) {
2965 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
2966 cpu->cpu_id, cpu->cd.mips.pc_last,
2967 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
2968 }
2969 fatal("unimplemented special6 = 0x%02x\n", special6);
2970 cpu->running = 0;
2971 return 1;
2972 }
2973 return 1;
2974 case HI6_BEQ:
2975 case HI6_BEQL:
2976 case HI6_BNE:
2977 case HI6_BGTZ:
2978 case HI6_BGTZL:
2979 case HI6_BLEZ:
2980 case HI6_BLEZL:
2981 case HI6_BNEL:
2982 case HI6_ADDI:
2983 case HI6_ADDIU:
2984 case HI6_DADDI:
2985 case HI6_DADDIU:
2986 case HI6_SLTI:
2987 case HI6_SLTIU:
2988 case HI6_ANDI:
2989 case HI6_ORI:
2990 case HI6_XORI:
2991 case HI6_LUI:
2992 case HI6_LB:
2993 case HI6_LBU:
2994 case HI6_LH:
2995 case HI6_LHU:
2996 case HI6_LW:
2997 case HI6_LWU:
2998 case HI6_LD:
2999 case HI6_LQ_MDMX:
3000 case HI6_LWC1:
3001 case HI6_LWC2:
3002 case HI6_LWC3:
3003 case HI6_LDC1:
3004 case HI6_LDC2:
3005 case HI6_LL:
3006 case HI6_LLD:
3007 case HI6_SB:
3008 case HI6_SH:
3009 case HI6_SW:
3010 case HI6_SD:
3011 case HI6_SQ:
3012 case HI6_SC:
3013 case HI6_SCD:
3014 case HI6_SWC1:
3015 case HI6_SWC2:
3016 case HI6_SWC3:
3017 case HI6_SDC1:
3018 case HI6_SDC2:
3019 case HI6_LWL: /* Unaligned load/store */
3020 case HI6_LWR:
3021 case HI6_LDL:
3022 case HI6_LDR:
3023 case HI6_SWL:
3024 case HI6_SWR:
3025 case HI6_SDL:
3026 case HI6_SDR:
3027 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3028 rt = instr[2] & 31;
3029 imm = (instr[1] << 8) + instr[0];
3030 if (imm >= 32768) /* signed 16-bit */
3031 imm -= 65536;
3032
3033 tmpvalue = imm; /* used later in several cases */
3034
3035 switch (hi6) {
3036 case HI6_ADDI:
3037 case HI6_ADDIU:
3038 case HI6_DADDI:
3039 case HI6_DADDIU:
3040 tmpvalue = cpu->cd.mips.gpr[rs];
3041 result_value = cpu->cd.mips.gpr[rs] + imm;
3042
3043 if (hi6 == HI6_ADDI || hi6 == HI6_DADDI) {
3044 /*
3045 * addi and daddi should trap on overflow:
3046 *
3047 * TODO: This is incorrect? The R4000 manual
3048 * says that overflow occurs if the carry bits
3049 * out of bit 62 and 63 differ. The
3050 * destination register should not be modified
3051 * on overflow.
3052 */
3053 if (imm >= 0) {
3054 /* Turn around from 0x7fff.. to 0x800 ? Then overflow. */
3055 if ( ((hi6 == HI6_ADDI && (result_value &
3056 0x80000000ULL) && (tmpvalue &
3057 0x80000000ULL)==0))
3058 || ((hi6 == HI6_DADDI && (result_value &
3059 0x8000000000000000ULL) && (tmpvalue &
3060 0x8000000000000000ULL)==0)) ) {
3061 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3062 break;
3063 }
3064 } else {
3065 /* Turn around from 0x8000.. to 0x7fff.. ? Then overflow. */
3066 if ( ((hi6 == HI6_ADDI && (result_value &
3067 0x80000000ULL)==0 && (tmpvalue &
3068 0x80000000ULL)))
3069 || ((hi6 == HI6_DADDI && (result_value &
3070 0x8000000000000000ULL)==0 && (tmpvalue &
3071 0x8000000000000000ULL))) ) {
3072 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3073 break;
3074 }
3075 }
3076 }
3077
3078 cpu->cd.mips.gpr[rt] = result_value;
3079
3080 /*
3081 * Super-ugly speed-hack: (only if speed_tricks != 0)
3082 * NOTE: This makes the emulation less correct.
3083 *
3084 * If we encounter a loop such as:
3085 *
3086 * 8012f5f4: 1c40ffff bgtz r0,r2,ffffffff8012f5f4
3087 * 8012f5f8: 2442ffff (d) addiu r2,r2,-1
3088 *
3089 * then it is a small loop which simply waits for r2
3090 * to become zero.
3091 *
3092 * TODO: increaste the count register, and cause
3093 * interrupts!!! For now: return as if we just
3094 * executed 1 instruction.
3095 */
3096 ninstrs_executed = 1;
3097 if (cpu->machine->speed_tricks && cpu->cd.mips.delay_slot &&
3098 cpu->cd.mips.last_was_jumptoself &&
3099 cpu->cd.mips.jump_to_self_reg == rt &&
3100 cpu->cd.mips.jump_to_self_reg == rs) {
3101 if ((int64_t)cpu->cd.mips.gpr[rt] > 1 && (int64_t)cpu->cd.mips.gpr[rt] < 0x70000000
3102 && (imm >= -30000 && imm <= -1)) {
3103 if (instruction_trace_cached)
3104 debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3105
3106 while ((int64_t)cpu->cd.mips.gpr[rt] > 0 && ninstrs_executed < 1000
3107 && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) > 0) {
3108 cpu->cd.mips.gpr[rt] += (int64_t)imm;
3109 ninstrs_executed += 2;
3110 }
3111
3112 if (instruction_trace_cached)
3113 debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3114
3115 /* TODO: return value, cpu->cd.mips.gpr[rt] * 2; */
3116 }
3117 if ((int64_t)cpu->cd.mips.gpr[rt] > -0x70000000 && (int64_t)cpu->cd.mips.gpr[rt] < -1
3118 && (imm >= 1 && imm <= 30000)) {
3119 if (instruction_trace_cached)
3120 debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3121
3122 while ((int64_t)cpu->cd.mips.gpr[rt] < 0 && ninstrs_executed < 1000
3123 && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) < 0) {
3124 cpu->cd.mips.gpr[rt] += (int64_t)imm;
3125 ninstrs_executed += 2;
3126 }
3127
3128 if (instruction_trace_cached)
3129 debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3130 }
3131 }
3132
3133 if (hi6 == HI6_ADDI || hi6 == HI6_ADDIU) {
3134 /* Sign-extend: */
3135 cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3136 if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3137 cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3138 }
3139 return ninstrs_executed;
3140 case HI6_BEQ:
3141 case HI6_BNE:
3142 case HI6_BGTZ:
3143 case HI6_BGTZL:
3144 case HI6_BLEZ:
3145 case HI6_BLEZL:
3146 case HI6_BEQL:
3147 case HI6_BNEL:
3148 if (cpu->cd.mips.delay_slot) {
3149 fatal("b*: jump inside a jump's delay slot, or similar. TODO\n");
3150 cpu->running = 0;
3151 return 1;
3152 }
3153 likely = cond = 0;
3154 switch (hi6) {
3155 case HI6_BNEL: likely = 1;
3156 case HI6_BNE: cond = (cpu->cd.mips.gpr[rt] != cpu->cd.mips.gpr[rs]);
3157 break;
3158 case HI6_BEQL: likely = 1;
3159 case HI6_BEQ: cond = (cpu->cd.mips.gpr[rt] == cpu->cd.mips.gpr[rs]);
3160 break;
3161 case HI6_BLEZL: likely = 1;
3162 case HI6_BLEZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] <= 0);
3163 break;
3164 case HI6_BGTZL: likely = 1;
3165 case HI6_BGTZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] > 0);
3166 break;
3167 }
3168
3169 if (cond) {
3170 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3171 cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3172 } else {
3173 if (likely)
3174 cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3175 }
3176
3177 if (imm==-1 && (hi6 == HI6_BGTZ || hi6 == HI6_BLEZ ||
3178 (hi6 == HI6_BGTZL && cond) ||
3179 (hi6 == HI6_BLEZL && cond) ||
3180 (hi6 == HI6_BNE && (rt==0 || rs==0)) ||
3181 (hi6 == HI6_BEQ && (rt==0 || rs==0)))) {
3182 cpu->cd.mips.last_was_jumptoself = 2;
3183 if (rs == 0)
3184 cpu->cd.mips.jump_to_self_reg = rt;
3185 else
3186 cpu->cd.mips.jump_to_self_reg = rs;
3187 }
3188 return 1;
3189 case HI6_LUI:
3190 cpu->cd.mips.gpr[rt] = (imm << 16);
3191 /* No sign-extending necessary, as imm already
3192 was sign-extended if it was negative. */
3193 break;
3194 case HI6_SLTI:
3195 cpu->cd.mips.gpr[rt] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)tmpvalue;
3196 break;
3197 case HI6_SLTIU:
3198 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] < (uint64_t)imm;
3199 break;
3200 case HI6_ANDI:
3201 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] & (tmpvalue & 0xffff);
3202 break;
3203 case HI6_ORI:
3204 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] | (tmpvalue & 0xffff);
3205 break;
3206 case HI6_XORI:
3207 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] ^ (tmpvalue & 0xffff);
3208 break;
3209 case HI6_LB:
3210 case HI6_LBU:
3211 case HI6_LH:
3212 case HI6_LHU:
3213 case HI6_LW:
3214 case HI6_LWU:
3215 case HI6_LD:
3216 case HI6_LQ_MDMX:
3217 case HI6_LWC1:
3218 case HI6_LWC2:
3219 case HI6_LWC3: /* pref */
3220 case HI6_LDC1:
3221 case HI6_LDC2:
3222 case HI6_LL:
3223 case HI6_LLD:
3224 case HI6_SB:
3225 case HI6_SH:
3226 case HI6_SW:
3227 case HI6_SD:
3228 case HI6_SQ:
3229 case HI6_SC:
3230 case HI6_SCD:
3231 case HI6_SWC1:
3232 case HI6_SWC2:
3233 case HI6_SWC3:
3234 case HI6_SDC1:
3235 case HI6_SDC2:
3236 /* These are the default "assumptions". */
3237 linked = 0;
3238 st = 1;
3239 signd = 1;
3240 wlen = 4;
3241
3242 switch (hi6) {
3243 /* The most common ones: */
3244 case HI6_LW: { st = 0; } break;
3245 case HI6_SW: { signd = 0; } break;
3246
3247 case HI6_LB: { wlen = 1; st = 0; } break;
3248 case HI6_LBU: { wlen = 1; st = 0; signd = 0; } break;
3249 case HI6_SB: { wlen = 1; signd = 0; } break;
3250
3251 case HI6_LD: { wlen = 8; st = 0; signd = 0; } break;
3252 case HI6_SD: { wlen = 8; signd = 0; } break;
3253
3254 case HI6_LQ_MDMX: { wlen = 16; st = 0; signd = 0; } break; /* R5900, otherwise MDMX (TODO) */
3255 case HI6_SQ: { wlen = 16; signd = 0; } break; /* R5900 ? */
3256
3257 /* The rest: */
3258 case HI6_LH: { wlen = 2; st = 0; } break;
3259 case HI6_LHU: { wlen = 2; st = 0; signd = 0; } break;
3260 case HI6_LWU: { st = 0; signd = 0; } break;
3261 case HI6_LWC1: { st = 0; } break;
3262 case HI6_LWC2: { st = 0; } break;
3263 case HI6_LWC3: { st = 0; } break;
3264 case HI6_LDC1: { wlen = 8; st = 0; signd = 0; } break;
3265 case HI6_LDC2: { wlen = 8; st = 0; signd = 0; } break;
3266
3267 case HI6_SH: { wlen = 2; signd = 0; } break;
3268 case HI6_SDC1:
3269 case HI6_SDC2: wlen = 8;
3270 case HI6_SWC1:
3271 case HI6_SWC2:
3272 case HI6_SWC3: { signd = 0; } break;
3273
3274 case HI6_LL: { st = 0; signd = 1; linked = 1; } break;
3275 case HI6_LLD: { wlen = 8; st = 0; signd = 0; linked = 1; } break;
3276
3277 case HI6_SC: { signd = 1; linked = 1; } break;
3278 case HI6_SCD: { wlen = 8; signd = 0; linked = 1; } break;
3279
3280 default:
3281 fatal("cannot be here\n");
3282 wlen = 4; st = 0; signd = 0;
3283 }
3284
3285 /*
3286 * In the MIPS IV ISA, the 'lwc3' instruction is changed into 'pref'.
3287 * The pref instruction is emulated by not doing anything. :-) TODO
3288 */
3289 if (hi6 == HI6_LWC3 && cpu->cd.mips.cpu_type.isa_level >= 4) {
3290 /* Clear the LLbit (at least on R10000): */
3291 cpu->cd.mips.rmw = 0;
3292 break;
3293 }
3294
3295 addr = cpu->cd.mips.gpr[rs] + imm;
3296
3297 /* Check for natural alignment: */
3298 if ((addr & (wlen - 1)) != 0) {
3299 mips_cpu_exception(cpu, st? EXCEPTION_ADES : EXCEPTION_ADEL,
3300 0, addr, 0, 0, 0, 0);
3301 break;
3302 }
3303
3304 #if 0
3305 if (cpu->cd.mips.cpu_type.isa_level == 4 && (imm & (wlen - 1)) != 0)
3306 debug("WARNING: low bits of imm value not zero! (MIPS IV) "
3307 "pc=%016llx", (long long)cpu->cd.mips.pc_last);
3308 #endif
3309
3310 /*
3311 * Load Linked: This initiates a Read-Modify-Write
3312 * sequence.
3313 */
3314 if (linked) {
3315 if (st==0) {
3316 /* st == 0: Load */
3317 cpu->cd.mips.rmw = 1;
3318 cpu->cd.mips.rmw_addr = addr;
3319 cpu->cd.mips.rmw_len = wlen;
3320
3321 /*
3322 * COP0_LLADDR is updated for
3323 * diagnostic purposes, except for
3324 * CPUs in the R10000 family.
3325 */
3326 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
3327 cp0->reg[COP0_LLADDR] =
3328 (addr >> 4) & 0xffffffffULL;
3329 } else {
3330 /*
3331 * st == 1: Store
3332 * If rmw is 0, then the store failed.
3333 * (This cache-line was written to by
3334 * someone else.)
3335 */
3336 if (cpu->cd.mips.rmw == 0 ||
3337 cpu->cd.mips.rmw_addr != addr ||
3338 cpu->cd.mips.rmw_len != wlen) {
3339 /* The store failed: */
3340 cpu->cd.mips.gpr[rt] = 0;
3341 if (instruction_trace_cached)
3342 debug(" [COLLISION] ");
3343 break;
3344 }
3345 }
3346 } else {
3347 /*
3348 * If any kind of load or store occurs between
3349 * an ll and an sc, then the ll-sc sequence
3350 * should fail. (This is local to each cpu.)
3351 */
3352 cpu->cd.mips.rmw = 0;
3353 }
3354
3355 value_hi = 0;
3356
3357 if (st) {
3358 /* store: */
3359 int cpnr, success;
3360
3361 if (hi6 == HI6_SWC3 || hi6 == HI6_SWC2 ||
3362 hi6 == HI6_SDC1 || hi6 == HI6_SWC1) {
3363 cpnr = 1;
3364 switch (hi6) {
3365 case HI6_SWC3: cpnr++; /* fallthrough */
3366 case HI6_SWC2: cpnr++;
3367 case HI6_SDC1:
3368 case HI6_SWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3369 (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3370 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3371 cpnr = -1;
3372 break;
3373 } else {
3374 /* Special handling of 64-bit stores
3375 on 32-bit CPUs, and on newer CPUs
3376 in 32-bit compatiblity mode: */
3377 if ((hi6==HI6_SDC1 || hi6==HI6_SDC2) &&
3378 (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3379 !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3380 uint64_t a, b;
3381 coproc_register_read(cpu,
3382 cpu->cd.mips.coproc[cpnr], rt, &a);
3383 coproc_register_read(cpu,
3384 cpu->cd.mips.coproc[cpnr], rt^1, &b);
3385 if (rt & 1)
3386 fatal("WARNING: SDCx in 32-bit mode from odd register!\n");
3387 value = (a & 0xffffffffULL)
3388 | (b << 32);
3389 } else
3390 coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr], rt, &value);
3391 }
3392 break;
3393 default:
3394 ;
3395 }
3396 if (cpnr < 0)
3397 break;
3398 } else
3399 value = cpu->cd.mips.gpr[rt];
3400
3401 if (wlen == 4) {
3402 /* Special case for 32-bit stores... (perhaps not worth it) */
3403 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3404 d[0] = value & 0xff; d[1] = (value >> 8) & 0xff;
3405 d[2] = (value >> 16) & 0xff; d[3] = (value >> 24) & 0xff;
3406 } else {
3407 d[3] = value & 0xff; d[2] = (value >> 8) & 0xff;
3408 d[1] = (value >> 16) & 0xff; d[0] = (value >> 24) & 0xff;
3409 }
3410 } else if (wlen == 16) {
3411 value_hi = cpu->cd.mips.gpr_quadhi[rt];
3412 /* Special case for R5900 128-bit stores: */
3413 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3414 for (i=0; i<8; i++) {
3415 d[i] = (value >> (i*8)) & 255;
3416 d[i+8] = (value_hi >> (i*8)) & 255;
3417 }
3418 else
3419 for (i=0; i<8; i++) {
3420 d[i] = (value >> ((wlen-1-i)*8)) & 255;
3421 d[i + 8] = (value_hi >> ((wlen-1-i)*8)) & 255;
3422 }
3423 } else if (wlen == 1) {
3424 d[0] = value & 0xff;
3425 } else {
3426 /* General case: */
3427 uint64_t v = value;
3428 if (cpu->byte_order ==
3429 EMUL_LITTLE_ENDIAN)
3430 for (i=0; i<wlen; i++) {
3431 d[i] = v & 255;
3432 v >>= 8;
3433 }
3434 else
3435 for (i=0; i<wlen; i++) {
3436 d[wlen-1-i] = v & 255;
3437 v >>= 8;
3438 }
3439 }
3440
3441 success = cpu->memory_rw(cpu, cpu->mem, addr,
3442 d, wlen, MEM_WRITE, CACHE_DATA);
3443 if (!success) {
3444 /* The store failed, and might have caused an exception. */
3445 if (instruction_trace_cached)
3446 debug("(failed)]\n");
3447 break;
3448 }
3449 } else {
3450 /* load: */
3451 int cpnr = 1;
3452 int success;
3453
3454 success = cpu->memory_rw(cpu, cpu->mem, addr,
3455 d, wlen, MEM_READ, CACHE_DATA);
3456 if (!success) {
3457 /* The load failed, and might have caused an exception. */
3458 if (instruction_trace_cached)
3459 debug("(failed)]\n");
3460 break;
3461 }
3462
3463 if (wlen == 1)
3464 value = d[0] | (signd && (d[0]&128)? (-1 << 8) : 0);
3465 else if (wlen != 16) {
3466 /* General case (except for 128-bit): */
3467 int i;
3468 value = 0;
3469 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3470 if (signd && (d[wlen-1] & 128)!=0) /* sign extend */
3471 value = -1;
3472 for (i=wlen-1; i>=0; i--) {
3473 value <<= 8;
3474 value += d[i];
3475 }
3476 } else {
3477 if (signd && (d[0] & 128)!=0) /* sign extend */
3478 value = -1;
3479 for (i=0; i<wlen; i++) {
3480 value <<= 8;
3481 value += d[i];
3482 }
3483 }
3484 } else {
3485 /* R5900 128-bit quadword: */
3486 int i;
3487 value_hi = 0;
3488 value = 0;
3489 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3490 for (i=wlen-1; i>=0; i--) {
3491 value_hi <<= 8;
3492 value_hi += (value >> 56) & 255;
3493 value <<= 8;
3494 value += d[i];
3495 }
3496 } else {
3497 for (i=0; i<wlen; i++) {
3498 value_hi <<= 8;
3499 value_hi += (value >> 56) & 255;
3500 value <<= 8;
3501 value += d[i];
3502 }
3503 }
3504 cpu->cd.mips.gpr_quadhi[rt] = value_hi;
3505 }
3506
3507 switch (hi6) {
3508 case HI6_LWC3: cpnr++; /* fallthrough */
3509 case HI6_LDC2:
3510 case HI6_LWC2: cpnr++;
3511 case HI6_LDC1:
3512 case HI6_LWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3513 (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3514 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3515 } else {
3516 /* Special handling of 64-bit loads
3517 on 32-bit CPUs, and on newer CPUs
3518 in 32-bit compatiblity mode: */
3519 if ((hi6==HI6_LDC1 || hi6==HI6_LDC2) &&
3520 (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3521 !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3522 uint64_t a, b;
3523 a = (int64_t)(int32_t) (value & 0xffffffffULL);
3524 b = (int64_t)(int32_t) (value >> 32);
3525 coproc_register_write(cpu,
3526 cpu->cd.mips.coproc[cpnr], rt, &a,
3527 hi6==HI6_LDC1 || hi6==HI6_LDC2);
3528 coproc_register_write(cpu,
3529 cpu->cd.mips.coproc[cpnr], rt ^ 1, &b,
3530 hi6==HI6_LDC1 || hi6==HI6_LDC2);
3531 if (rt & 1)
3532 fatal("WARNING: LDCx in 32-bit mode to odd register!\n");
3533 } else {
3534 coproc_register_write(cpu,
3535 cpu->cd.mips.coproc[cpnr], rt, &value,
3536 hi6==HI6_LDC1 || hi6==HI6_LDC2);
3537 }
3538 }
3539 break;
3540 default: if (rt != 0)
3541 cpu->cd.mips.gpr[rt] = value;
3542 }
3543 }
3544
3545 if (linked && st==1) {
3546 /*
3547 * The store succeeded. Invalidate any other
3548 * cpu's store to this cache line, and then
3549 * return 1 in gpr rt:
3550 *
3551 * (this is a semi-ugly hack using global
3552 * 'cpus')
3553 *
3554 * TODO: How about invalidating other CPUs
3555 * stores to this cache line, even if this
3556 * was _NOT_ a linked store?
3557 */
3558 for (i=0; i<cpu->machine->ncpus; i++) {
3559 if (cpu->machine->cpus[i]->cd.mips.rmw) {
3560 uint64_t yaddr = addr;
3561 uint64_t xaddr =
3562 cpu->machine->cpus[i]->cd.mips.rmw_addr;
3563 uint64_t mask;
3564 mask = ~(cpu->machine->cpus[i]->
3565 cd.mips.cache_linesize[CACHE_DATA]
3566 - 1);
3567 xaddr &= mask;
3568 yaddr &= mask;
3569 if (xaddr == yaddr) {
3570 cpu->machine->cpus[i]->cd.mips.rmw = 0;
3571 cpu->machine->cpus[i]->cd.mips.rmw_addr = 0;
3572 }
3573 }
3574 }
3575
3576 if (rt != 0)
3577 cpu->cd.mips.gpr[rt] = 1;
3578
3579 if (instruction_trace_cached)
3580 debug(" [no collision] ");
3581 cpu->cd.mips.rmw = 0;
3582 }
3583
3584 if (instruction_trace_cached) {
3585 switch (wlen) {
3586 case 2: debug("0x%04x", (int)value); break;
3587 case 4: debug("0x%08x", (int)value); break;
3588 case 8: debug("0x%016llx", (long long)value);
3589 break;
3590 case 16:debug("0x%016llx", (long long)value_hi);
3591 debug("%016llx", (long long)value);
3592 break;
3593 default:debug("0x%02x", (int)value);
3594 }
3595 debug("]\n");
3596 }
3597 return 1;
3598 case HI6_LWL: /* Unaligned load/store */
3599 case HI6_LWR:
3600 case HI6_LDL:
3601 case HI6_LDR:
3602 case HI6_SWL:
3603 case HI6_SWR:
3604 case HI6_SDL:
3605 case HI6_SDR:
3606 /* For L (Left): address is the most significant byte */
3607 /* For R (Right): address is the least significant byte */
3608 addr = cpu->cd.mips.gpr[rs] + imm;
3609
3610 is_left = 0;
3611 if (hi6 == HI6_SWL || hi6 == HI6_LWL ||
3612 hi6 == HI6_SDL || hi6 == HI6_LDL)
3613 is_left = 1;
3614
3615 wlen = 0; st = 0;
3616 signd = 0;
3617 if (hi6 == HI6_LWL || hi6 == HI6_LWR)
3618 signd = 1;
3619
3620 if (hi6 == HI6_LWL || hi6 == HI6_LWR) { wlen = 4; st = 0; }
3621 if (hi6 == HI6_SWL || hi6 == HI6_SWR) { wlen = 4; st = 1; }
3622 if (hi6 == HI6_LDL || hi6 == HI6_LDR) { wlen = 8; st = 0; }
3623 if (hi6 == HI6_SDL || hi6 == HI6_SDR) { wlen = 8; st = 1; }
3624
3625 dir = 1; /* big endian, Left */
3626 reg_dir = -1;
3627 reg_ofs = wlen - 1; /* byte offset in the register */
3628 if (!is_left) {
3629 dir = -dir;
3630 reg_ofs = 0;
3631 reg_dir = 1;
3632 }
3633 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3634 dir = -dir;
3635
3636 result_value = cpu->cd.mips.gpr[rt];
3637
3638 if (st) {
3639 /* Store: */
3640 uint64_t aligned_addr = addr & ~(wlen-1);
3641 unsigned char aligned_word[8];
3642 uint64_t oldpc = cpu->pc;
3643 /*
3644 * NOTE (this is ugly): The memory_rw()
3645 * call generates a TLBL exception, if there
3646 * is a tlb refill exception. However, since
3647 * this is a Store, the exception is converted
3648 * to a TLBS:
3649 */
3650 int ok = cpu->memory_rw(cpu, cpu->mem,
3651 aligned_addr, &aligned_word[0], wlen,
3652 MEM_READ, CACHE_DATA);
3653 if (!ok) {
3654 if (cpu->pc != oldpc) {
3655 cp0->reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
3656 cp0->reg[COP0_CAUSE] |= (EXCEPTION_TLBS << CAUSE_EXCCODE_SHIFT);
3657 }
3658 return 1;
3659 }
3660
3661 for (i=0; i<wlen; i++) {
3662 tmpaddr = addr + i*dir;
3663 /* Have we moved into another word/dword? Then stop: */
3664 if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3665 break;
3666
3667 /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3668 tmpaddr, reg_ofs, (long long)result_value); */
3669
3670 /* Store one byte: */
3671 aligned_word[tmpaddr & (wlen-1)] = (result_value >> (reg_ofs * 8)) & 255;
3672
3673 reg_ofs += reg_dir;
3674 }
3675
3676 ok = cpu->memory_rw(cpu, cpu->mem,
3677 aligned_addr, &aligned_word[0], wlen,
3678 MEM_WRITE, CACHE_DATA);
3679 if (!ok)
3680 return 1;
3681 } else {
3682 /* Load: */
3683 uint64_t aligned_addr = addr & ~(wlen-1);
3684 unsigned char aligned_word[8], databyte;
3685 int ok = cpu->memory_rw(cpu, cpu->mem,
3686 aligned_addr, &aligned_word[0], wlen,
3687 MEM_READ, CACHE_DATA);
3688 if (!ok)
3689 return 1;
3690
3691 for (i=0; i<wlen; i++) {
3692 tmpaddr = addr + i*dir;
3693 /* Have we moved into another word/dword? Then stop: */
3694 if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3695 break;
3696
3697 /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3698 tmpaddr, reg_ofs, (long long)result_value); */
3699
3700 /* Load one byte: */
3701 databyte = aligned_word[tmpaddr & (wlen-1)];
3702 result_value &= ~((uint64_t)0xff << (reg_ofs * 8));
3703 result_value |= (uint64_t)databyte << (reg_ofs * 8);
3704
3705 reg_ofs += reg_dir;
3706 }
3707
3708 if (rt != 0)
3709 cpu->cd.mips.gpr[rt] = result_value;
3710 }
3711
3712 /* Sign extend for 32-bit load lefts: */
3713 if (!st && signd && wlen == 4) {
3714 cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3715 if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3716 cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3717 }
3718
3719 if (instruction_trace_cached) {
3720 char *t;
3721 switch (wlen) {
3722 case 2: t = "0x%04llx"; break;
3723 case 4: t = "0x%08llx"; break;
3724 case 8: t = "0x%016llx"; break;
3725 default: t = "0x%02llx";
3726 }
3727 debug(t, (long long)cpu->cd.mips.gpr[rt]);
3728 debug("]\n");
3729 }
3730
3731 return 1;
3732 }
3733 return 1;
3734 case HI6_REGIMM:
3735 regimm5 = instr[2] & 0x1f;
3736
3737 if (show_opcode_statistics)
3738 cpu->cd.mips.stats__regimm[regimm5] ++;
3739
3740 switch (regimm5) {
3741 case REGIMM_BLTZ:
3742 case REGIMM_BGEZ:
3743 case REGIMM_BLTZL:
3744 case REGIMM_BGEZL:
3745 case REGIMM_BLTZAL:
3746 case REGIMM_BLTZALL:
3747 case REGIMM_BGEZAL:
3748 case REGIMM_BGEZALL:
3749 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3750 imm = (instr[1] << 8) + instr[0];
3751 if (imm >= 32768) /* signed 16-bit */
3752 imm -= 65536;
3753
3754 cond = and_link = likely = 0;
3755
3756 switch (regimm5) {
3757 case REGIMM_BLTZL: likely = 1;
3758 case REGIMM_BLTZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3759 break;
3760 case REGIMM_BGEZL: likely = 1;
3761 case REGIMM_BGEZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3762 break;
3763
3764 case REGIMM_BLTZALL: likely = 1;
3765 case REGIMM_BLTZAL: and_link = 1;
3766 cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3767 break;
3768 case REGIMM_BGEZALL: likely = 1;
3769 case REGIMM_BGEZAL: and_link = 1;
3770 cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3771 break;
3772 }
3773
3774 if (and_link)
3775 cpu->cd.mips.gpr[31] = cached_pc + 4;
3776
3777 if (cond) {
3778 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3779 cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3780 } else {
3781 if (likely)
3782 cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3783 }
3784
3785 return 1;
3786 default:
3787 if (!instruction_trace_cached) {
3788 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
3789 cpu->cpu_id, cpu->cd.mips.pc_last,
3790 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
3791 }
3792 fatal("unimplemented regimm5 = 0x%02x\n", regimm5);
3793 cpu->running = 0;
3794 return 1;
3795 }
3796 /* NOT REACHED */
3797 case HI6_J:
3798 case HI6_JAL:
3799 if (cpu->cd.mips.delay_slot) {
3800 fatal("j/jal: jump inside a jump's delay slot, or similar. TODO\n");
3801 cpu->running = 0;
3802 return 1;
3803 }
3804 imm = ((instr[3] & 3) << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3805 imm <<= 2;
3806
3807 if (hi6 == HI6_JAL)
3808 cpu->cd.mips.gpr[31] = cached_pc + 4; /* pc already increased by 4 earlier */
3809
3810 addr = cached_pc & ~((1 << 28) - 1);
3811 addr |= imm;
3812
3813 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3814 cpu->cd.mips.delay_jmpaddr = addr;
3815
3816 if (!quiet_mode_cached && cpu->machine->show_trace_tree &&
3817 hi6 == HI6_JAL) {
3818 cpu->cd.mips.show_trace_delay = 2;
3819 cpu->cd.mips.show_trace_addr = addr;
3820 }
3821
3822 return 1;
3823 case HI6_COP0:
3824 case HI6_COP1:
3825 case HI6_COP2:
3826 case HI6_COP3:
3827 imm = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3828 imm &= ((1 << 26) - 1);
3829
3830 cpnr = 0;
3831 if (hi6 == HI6_COP0) cpnr = 0;
3832 if (hi6 == HI6_COP1) cpnr = 1;
3833 if (hi6 == HI6_COP2) cpnr = 2;
3834 if (hi6 == HI6_COP3) cpnr = 3;
3835
3836 /*
3837 * If there is no coprocessor nr cpnr, or we are running in
3838 * userland and the coprocessor is not marked as Useable in
3839 * the status register of CP0, then we get an exception.
3840 *
3841 * An exception (hehe) to this rule is that the kernel should
3842 * always be able to access CP0.
3843 */
3844 /* Set tmp = 1 if we're in user mode. */
3845 tmp = 0;
3846 switch (cpu->cd.mips.cpu_type.exc_model) {
3847 case EXC3K:
3848 /*
3849 * NOTE: If the KU bit is checked, Linux crashes.
3850 * It is the PC that counts. TODO: Check whether
3851 * this is true or not for R4000 as well.
3852 */
3853 if (cached_pc <= 0x7fffffff) /* if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */
3854 tmp = 1;
3855 break;
3856 default:
3857 /* R4000 etc: (TODO: How about supervisor mode?) */
3858 if (((cp0->reg[COP0_STATUS] & STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
3859 tmp = 1;
3860 if (cp0->reg[COP0_STATUS] & STATUS_ERL)
3861 tmp = 0;
3862 if (cp0->reg[COP0_STATUS] & STATUS_EXL)
3863 tmp = 0;
3864 break;
3865 }
3866 if (cpu->cd.mips.coproc[cpnr] == NULL ||
3867 (tmp && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ||
3868 (!tmp && cpnr >= 1 && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)))
3869 ) {
3870 if (instruction_trace_cached)
3871 debug("cop%i\t0x%08x => coprocessor unusable\n", cpnr, (int)imm);
3872
3873 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3874 } else {
3875 /*
3876 * Execute the coprocessor function. The
3877 * coproc_function code outputs instruction
3878 * trace, if necessary.
3879 */
3880 coproc_function(cpu, cpu->cd.mips.coproc[cpnr],
3881 cpnr, imm, 0, 1);
3882 }
3883 return 1;
3884 case HI6_CACHE:
3885 rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
3886 copz = instr[2] & 31;
3887 imm = (instr[1] << 8) + instr[0];
3888
3889 cache_op = copz >> 2;
3890 which_cache = copz & 3;
3891
3892 /*
3893 * TODO: The cache instruction is implementation dependant.
3894 * This is really ugly.
3895 */
3896
3897 #if 0
3898 Remove this...
3899
3900 /* if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) { */
3901 /* printf("taghi=%08lx taglo=%08lx\n",
3902 (long)cp0->reg[COP0_TAGDATA_HI],
3903 (long)cp0->reg[COP0_TAGDATA_LO]);
3904 */
3905 if (cp0->reg[COP0_TAGDATA_HI] == 0 &&
3906 cp0->reg[COP0_TAGDATA_LO] == 0) {
3907 /* Normal cache operation: */
3908 cpu->r10k_cache_disable_TODO = 0;
3909 } else {
3910 /* Dislocate the cache: */
3911 cpu->r10k_cache_disable_TODO = 1;
3912 }
3913 /* } */
3914 #endif
3915
3916 /*
3917 * Clear the LLbit (at least on R10000):
3918 * TODO: How about R4000?
3919 */
3920 cpu->cd.mips.rmw = 0;
3921
3922 return 1;
3923 case HI6_SPECIAL2:
3924 special6 = instr[0] & 0x3f;
3925
3926 if (show_opcode_statistics)
3927 cpu->cd.mips.stats__special2[special6] ++;
3928
3929 instrword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3930
3931 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3932 rt = instr[2] & 31;
3933 rd = (instr[1] >> 3) & 31;
3934
3935 /* printf("special2 %08x rs=0x%02x rt=0x%02x rd=0x%02x\n", instrword, rs,rt,rd); */
3936
3937 /*
3938 * Many of these can be found in the R5000 docs, or figured out
3939 * by studying binutils source code for MIPS instructions.
3940 */
3941
3942 if ((instrword & 0xfc0007ffULL) == 0x70000000) {
3943 {
3944 int32_t a, b;
3945 int64_t c;
3946 a = (int32_t)cpu->cd.mips.gpr[rs];
3947 b = (int32_t)cpu->cd.mips.gpr[rt];
3948 c = a * b;
3949 c += (cpu->cd.mips.lo & 0xffffffffULL)
3950 + (cpu->cd.mips.hi << 32);
3951 cpu->cd.mips.lo = (int64_t)((int32_t)c);
3952 cpu->cd.mips.hi = (int64_t)((int32_t)(c >> 32));
3953
3954 /*
3955 * The R5000 manual says that rd should be all zeros,
3956 * but it isn't on R5900. I'm just guessing here that
3957 * it stores the value in register rd, in addition to hi/lo.
3958 * TODO
3959 */
3960 if (rd != 0)
3961 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3962 }
3963 } else if ((instrword & 0xffff07ffULL) == 0x70000209
3964 || (instrword & 0xffff07ffULL) == 0x70000249) {
3965 /*
3966 * This is just a guess for R5900, I've not found any docs on this one yet.
3967 *
3968 * pmfhi/pmflo rd
3969 *
3970 * If the lowest 8 bits of the instruction word are 0x09, it's a pmfhi.
3971 * If the lowest bits are 0x49, it's a pmflo.
3972 *
3973 * A wild guess is that this is a 128-bit version of mfhi/mflo.
3974 * For now, this is implemented as 64-bit only. (TODO)
3975 */
3976 if (instr[0] == 0x49) {
3977 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3978 } else {
3979 cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
3980 }
3981 } else if ((instrword & 0xfc1fffff) == 0x70000269 || (instrword & 0xfc1fffff) == 0x70000229) {
3982 /*
3983 * This is just a guess for R5900, I've not found any docs on this one yet.
3984 *
3985 * pmthi/pmtlo rs (pmtlo = 269, pmthi = 229)
3986 *
3987 * A wild guess is that this is a 128-bit version of mthi/mtlo.
3988 * For now, this is implemented as 64-bit only. (TODO)
3989 */
3990 if (instr[0] == 0x69) {
3991 cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
3992 } else {
3993 cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
3994 }
3995 } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
3996 /*
3997 * This is just a guess for R5900, I've not found any docs on this one yet.
3998 *
3999 * por dst,src,src2 ==> rs=src rt=src2 rd=dst
4000 *
4001 * A wild guess is that this is a 128-bit "or" between two registers.
4002 * For now, let's just or using 64-bits. (TODO)
4003 */
4004 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
4005 } else if ((instrword & 0xfc0007ff) == 0x70000488) {
4006 /*
4007 * R5900 "undocumented" pextlw. TODO: find out if this is correct.
4008 * It seems that this instruction is used to combine two 32-bit
4009 * words into a 64-bit dword, typically before a sd (store dword).
4010 */
4011 cpu->cd.mips.gpr[rd] =
4012 ((cpu->cd.mips.gpr[rs] & 0xffffffffULL) << 32) /* TODO: switch rt and rs? */
4013 | (cpu->cd.mips.gpr[rt] & 0xffffffffULL);
4014 } else if (special6 == SPECIAL2_MUL) {
4015 cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rt] *
4016 (int64_t)cpu->cd.mips.gpr[rs];
4017 } else if (special6 == SPECIAL2_CLZ) {
4018 /* clz: count leading zeroes */
4019 int i, n=0;
4020 for (i=31; i>=0; i--) {
4021 if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
4022 break;
4023 else
4024 n++;
4025 }
4026 cpu->cd.mips.gpr[rd] = n;
4027 } else if (special6 == SPECIAL2_CLO) {
4028 /* clo: count leading ones */
4029 int i, n=0;
4030 for (i=31; i>=0; i--) {
4031 if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
4032 n++;
4033 else
4034 break;
4035 }
4036 cpu->cd.mips.gpr[rd] = n;
4037 } else if (special6 == SPECIAL2_DCLZ) {
4038 /* dclz: count leading zeroes */
4039 int i, n=0;
4040 for (i=63; i>=0; i--) {
4041 if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4042 break;
4043 else
4044 n++;
4045 }
4046 cpu->cd.mips.gpr[rd] = n;
4047 } else if (special6 == SPECIAL2_DCLO) {
4048 /* dclo: count leading ones */
4049 int i, n=0;
4050 for (i=63; i>=0; i--) {
4051 if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4052 n++;
4053 else
4054 break;
4055 }
4056 cpu->cd.mips.gpr[rd] = n;
4057 } else {
4058 if (!instruction_trace_cached) {
4059 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4060 cpu->cpu_id, cpu->cd.mips.pc_last,
4061 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4062 }
4063 fatal("unimplemented special_2 = 0x%02x, rs=0x%02x rt=0x%02x rd=0x%02x\n",
4064 special6, rs, rt, rd);
4065 cpu->running = 0;
4066 return 1;
4067 }
4068 return 1;
4069 default:
4070 if (!instruction_trace_cached) {
4071 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4072 cpu->cpu_id, cpu->cd.mips.pc_last,
4073 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4074 }
4075 fatal("unimplemented hi6 = 0x%02x\n", hi6);
4076 cpu->running = 0;
4077 return 1;
4078 }
4079
4080 /* NOTREACHED */
4081 }
4082
4083
4084 #define CPU_RUN mips_cpu_run
4085 #define CPU_RUN_MIPS
4086 #define CPU_RINSTR mips_cpu_run_instr
4087 #include "cpu_run.c"
4088 #undef CPU_RINSTR
4089 #undef CPU_RUN_MIPS
4090 #undef CPU_RUN
4091
4092
4093 /*
4094 * mips_cpu_dumpinfo():
4095 *
4096 * Debug dump of MIPS-specific CPU data for specific CPU.
4097 */
4098 void mips_cpu_dumpinfo(struct cpu *cpu)
4099 {
4100 struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type;
4101
4102 debug(" (%i-bit ", (ct->isa_level < 3 ||
4103 ct->isa_level == 32)? 32 : 64);
4104
4105 debug("%s, ", cpu->byte_order == EMUL_BIG_ENDIAN? "BE" : "LE");
4106
4107 debug("nTLB=%i", ct->nr_of_tlb_entries);
4108
4109 if (ct->default_picache || ct->default_pdcache)
4110 debug(", I+D = %i+%i KB",
4111 (1 << ct->default_picache) / 1024,
4112 (1 << ct->default_pdcache) / 1024);
4113
4114 if (ct->default_scache) {
4115 int kb = (1 << ct->default_scache) / 1024;
4116 debug(", L2 = %i %cB",
4117 kb >= 1024? kb / 1024 : kb,
4118 kb >= 1024? 'M' : 'K');
4119 }
4120
4121 debug(")\n");
4122 }
4123
4124
4125 /*
4126 * mips_cpu_list_available_types():
4127 *
4128 * Print a list of available MIPS CPU types.
4129 */
4130 void mips_cpu_list_available_types(void)
4131 {
4132 int i, j;
4133 struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
4134
4135 i = 0;
4136 while (cpu_type_defs[i].name != NULL) {
4137 debug("%s", cpu_type_defs[i].name);
4138 for (j=10 - strlen(cpu_type_defs[i].name); j>0; j--)
4139 debug(" ");
4140 i++;
4141 if ((i % 6) == 0 || cpu_type_defs[i].name == NULL)
4142 debug("\n");
4143 }
4144 }
4145
4146
4147 /*
4148 * mips_cpu_family_init():
4149 *
4150 * Fill in the cpu_family struct for MIPS.
4151 */
4152 int mips_cpu_family_init(struct cpu_family *fp)
4153 {
4154 fp->name = "MIPS";
4155 fp->cpu_new = mips_cpu_new;
4156 fp->list_available_types = mips_cpu_list_available_types;
4157 fp->register_match = mips_cpu_register_match;
4158 fp->disassemble_instr = mips_cpu_disassemble_instr;
4159 fp->register_dump = mips_cpu_register_dump;
4160 fp->run = mips_cpu_run;
4161 fp->dumpinfo = mips_cpu_dumpinfo;
4162 fp->show_full_statistics = mips_cpu_show_full_statistics;
4163 fp->tlbdump = mips_cpu_tlbdump;
4164 fp->interrupt = mips_cpu_interrupt;
4165 fp->interrupt_ack = mips_cpu_interrupt_ack;
4166 return 1;
4167 }
4168
4169
4170 #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26