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

Contents of /trunk/src/cpus/cpu_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (show annotations)
Mon Oct 8 16:19:01 2007 UTC (12 years, 9 months ago) by dpavlin
File MIME type: text/plain
File size: 119314 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.988 2005/10/11 03:53:57 debug Exp $

==============  RELEASE 0.3.6  ==============

20051008	The bug was not because of faulty ARM documentation after all,
		but it was related to those parts of the code.
		Fixing the RTC (dev_mc146818) to work with CATS.
20051009	Rewriting the R() function; now there are 8192 automatically
		generated smaller functions doing the same thing, but hopefully
		faster. This also fixes some bugs which were triggered when
		trying to compile GXemul inside itself. :-)
		Adding a dummy dev_lpt.
20051010	Small hack to not update virtual translation tables if memory
		accesses are done with the NO_EXCEPTION flag; a time reduction
		of almost a factor 2 for a full NetBSD/cats install. :-)
20051011	Passing -A as the default boot arg for CATS (works fine with
		OpenBSD/cats).

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

  ViewVC Help
Powered by ViewVC 1.1.26