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

Contents of /upstream/0.3.1/src/cpu_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26