/[gxemul]/trunk/src/cpus/cpu_mips_coproc.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_coproc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 65601 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


1 /*
2 * Copyright (C) 2003-2006 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_coproc.c,v 1.49 2006/07/21 20:39:40 debug Exp $
29 *
30 * Emulation of MIPS coprocessors.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <math.h>
37
38 #include "cop0.h"
39 #include "cpu.h"
40 #include "cpu_mips.h"
41 #include "emul.h"
42 #include "float_emul.h"
43 #include "machine.h"
44 #include "memory.h"
45 #include "mips_cpu_types.h"
46 #include "misc.h"
47 #include "opcodes_mips.h"
48
49
50 #ifndef ENABLE_MIPS
51
52
53 struct mips_coproc *mips_coproc_new(struct cpu *cpu, int coproc_nr)
54 { return NULL; }
55
56 void mips_coproc_tlb_set_entry(struct cpu *cpu, int entrynr, int size,
57 uint64_t vaddr, uint64_t paddr0, uint64_t paddr1,
58 int valid0, int valid1, int dirty0, int dirty1, int global, int asid,
59 int cachealgo0, int cachealgo1) { }
60
61
62 #else /* ENABLE_MIPS */
63
64
65 extern volatile int single_step;
66
67 static char *cop0_names[] = COP0_NAMES;
68 static char *regnames[] = MIPS_REGISTER_NAMES;
69
70
71 /*
72 * initialize_cop0_config():
73 *
74 * Helper function, called from mips_coproc_new().
75 */
76 static void initialize_cop0_config(struct cpu *cpu, struct mips_coproc *c)
77 {
78 const int m16 = 0; /* TODO: MIPS16 support */
79 int IB, DB, SB, IC, DC, SC, IA, DA;
80
81 /* Generic case for MIPS32/64: */
82 if (cpu->cd.mips.cpu_type.isa_level == 32 ||
83 cpu->cd.mips.cpu_type.isa_level == 64) {
84 /* According to the MIPS64 (5K) User's Manual: */
85 c->reg[COP0_CONFIG] =
86 ( (uint32_t)1 << 31)/* Config 1 present bit */
87 | ( 0 << 20) /* ISD: instruction scheduling
88 disable (=1) */
89 | ( 0 << 17) /* DID: dual issue disable */
90 | ( 0 << 16) /* BM: burst mode */
91 | ((cpu->byte_order == EMUL_BIG_ENDIAN? 1 : 0) << 15)
92 /* endian mode */
93 | ((cpu->cd.mips.cpu_type.isa_level == 64? 2 : 0) << 13)
94 /* 0=MIPS32, 1=64S, 2=64 */
95 | ( 0 << 10) /* Architecture revision */
96 | ( 1 << 7) /* MMU type: 1=TLB, 3=FMT */
97 | ( 2 << 0) /* kseg0 cache coherency algorithm */
98 ;
99 /* Config select 1: caches etc. TODO: Don't use
100 cpu->machine for this stuff! */
101 IB = cpu->machine->cache_picache_linesize - 1;
102 IB = IB < 0? 0 : (IB > 7? 7 : IB);
103 DB = cpu->machine->cache_pdcache_linesize - 1;
104 DB = DB < 0? 0 : (DB > 7? 7 : DB);
105 IC = cpu->machine->cache_picache -
106 cpu->machine->cache_picache_linesize - 7;
107 DC = cpu->machine->cache_pdcache -
108 cpu->machine->cache_pdcache_linesize - 7;
109 IA = cpu->cd.mips.cpu_type.piways - 1;
110 DA = cpu->cd.mips.cpu_type.pdways - 1;
111 cpu->cd.mips.cop0_config_select1 =
112 ((cpu->cd.mips.cpu_type.nr_of_tlb_entries - 1) << 25)
113 | (IC << 22) /* IS: I-cache sets per way */
114 | (IB << 19) /* IL: I-cache line-size */
115 | (IA << 16) /* IA: I-cache assoc. (ways-1) */
116 | (DC << 13) /* DS: D-cache sets per way */
117 | (DB << 10) /* DL: D-cache line-size */
118 | (DA << 7) /* DA: D-cache assoc. (ways-1) */
119 | (16 * 0) /* Existance of PerformanceCounters */
120 | ( 8 * 0) /* Existance of Watch Registers */
121 | ( 4 * m16) /* Existance of MIPS16 */
122 | ( 2 * 0) /* Existance of EJTAG */
123 | ( 1 * 1) /* Existance of FPU */
124 ;
125
126 return;
127 }
128
129 switch (cpu->cd.mips.cpu_type.rev) {
130 case MIPS_R2000:
131 case MIPS_R3000:
132 /* No config register. */
133 break;
134 case MIPS_R4000: /* according to the R4000 manual */
135 case MIPS_R4600:
136 IB = cpu->machine->cache_picache_linesize - 4;
137 IB = IB < 0? 0 : (IB > 1? 1 : IB);
138 DB = cpu->machine->cache_pdcache_linesize - 4;
139 DB = DB < 0? 0 : (DB > 1? 1 : DB);
140 SB = cpu->machine->cache_secondary_linesize - 4;
141 SB = SB < 0? 0 : (SB > 3? 3 : SB);
142 IC = cpu->machine->cache_picache - 12;
143 IC = IC < 0? 0 : (IC > 7? 7 : IC);
144 DC = cpu->machine->cache_pdcache - 12;
145 DC = DC < 0? 0 : (DC > 7? 7 : DC);
146 SC = cpu->machine->cache_secondary? 0 : 1;
147 c->reg[COP0_CONFIG] =
148 ( 0 << 31) /* Master/Checker present bit */
149 | (0x00 << 28) /* EC: system clock divisor,
150 0x00 = '2' */
151 | (0x00 << 24) /* EP */
152 | ( SB << 22) /* SB */
153 | (0x00 << 21) /* SS: 0 = mixed i/d scache */
154 | (0x00 << 20) /* SW */
155 | (0x00 << 18) /* EW: 0=64-bit */
156 | ( SC << 17) /* SC: 0=secondary cache present,
157 1=non-present */
158 | (0x00 << 16) /* SM: (todo) */
159 | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
160 /* endian mode */
161 | (0x01 << 14) /* ECC: 0=enabled, 1=disabled */
162 | (0x00 << 13) /* EB: (todo) */
163 | (0x00 << 12) /* 0 (resered) */
164 | ( IC << 9) /* IC: I-cache = 2^(12+IC) bytes
165 (1 = 8KB, 4=64K) */
166 | ( DC << 6) /* DC: D-cache = 2^(12+DC) bytes
167 (1 = 8KB, 4=64K) */
168 | ( IB << 5) /* IB: I-cache line size (0=16,
169 1=32) */
170 | ( DB << 4) /* DB: D-cache line size (0=16,
171 1=32) */
172 | ( 0 << 3) /* CU: todo */
173 | ( 0 << 0) /* kseg0 coherency algorithm
174 (TODO) */
175 ;
176 break;
177 case MIPS_R4100: /* According to the VR4131 manual: */
178 IB = cpu->machine->cache_picache_linesize - 4;
179 IB = IB < 0? 0 : (IB > 1? 1 : IB);
180 DB = cpu->machine->cache_pdcache_linesize - 4;
181 DB = DB < 0? 0 : (DB > 1? 1 : DB);
182 IC = cpu->machine->cache_picache - 10;
183 IC = IC < 0? 0 : (IC > 7? 7 : IC);
184 DC = cpu->machine->cache_pdcache - 10;
185 DC = DC < 0? 0 : (DC > 7? 7 : DC);
186 c->reg[COP0_CONFIG] =
187 ( 0 << 31) /* IS: Instruction Streaming bit */
188 | (0x01 << 28) /* EC: system clock divisor,
189 0x01 = 2 */
190 | (0x00 << 24) /* EP */
191 | (0x00 << 23) /* AD: Accelerate data mode
192 (0=VR4000-compatible) */
193 | ( m16 << 20) /* M16: MIPS16 support */
194 | ( 1 << 17) /* '1' */
195 | (0x00 << 16) /* BP: 'Branch forecast'
196 (0 = enabled) */
197 | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
198 /* endian mode */
199 | ( 2 << 13) /* '2' hardcoded on VR4131 */
200 | ( 1 << 12) /* CS: Cache size mode
201 (1 on VR4131) */
202 | ( IC << 9) /* IC: I-cache = 2^(10+IC) bytes
203 (0 = 1KB, 4=16K) */
204 | ( DC << 6) /* DC: D-cache = 2^(10+DC) bytes
205 (0 = 1KB, 4=16K) */
206 | ( IB << 5) /* IB: I-cache line size (0=16,
207 1=32) */
208 | ( DB << 4) /* DB: D-cache line size (0=16,
209 1=32) */
210 | ( 0 << 0) /* kseg0 coherency algorithm (TODO) */
211 ;
212 break;
213 case MIPS_R5000:
214 case MIPS_RM5200: /* rm5200 is just a wild guess */
215 /* These are just guesses: (the comments are wrong) */
216 c->reg[COP0_CONFIG] =
217 ( 0 << 31) /* Master/Checker present bit */
218 | (0x00 << 28) /* EC: system clock divisor,
219 0x00 = '2' */
220 | (0x00 << 24) /* EP */
221 | (0x00 << 22) /* SB */
222 | (0x00 << 21) /* SS */
223 | (0x00 << 20) /* SW */
224 | (0x00 << 18) /* EW: 0=64-bit */
225 | (0x01 << 17) /* SC: 0=secondary cache present,
226 1=non-present */
227 | (0x00 << 16) /* SM: (todo) */
228 | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
229 /* endian mode */
230 | (0x01 << 14) /* ECC: 0=enabled, 1=disabled */
231 | (0x00 << 13) /* EB: (todo) */
232 | (0x00 << 12) /* 0 (resered) */
233 | ( 3 << 9) /* IC: I-cache = 2^(12+IC) bytes
234 (1 = 8KB, 4=64K) */
235 | ( 3 << 6) /* DC: D-cache = 2^(12+DC) bytes
236 (1 = 8KB, 4=64K) */
237 | ( 1 << 5) /* IB: I-cache line size (0=16,
238 1=32) */
239 | ( 1 << 4) /* DB: D-cache line size (0=16,
240 1=32) */
241 | ( 0 << 3) /* CU: todo */
242 | ( 2 << 0) /* kseg0 coherency algorithm
243 (TODO) */
244 ;
245 break;
246 case MIPS_R10000:
247 case MIPS_R12000:
248 case MIPS_R14000:
249 IC = cpu->machine->cache_picache - 12;
250 IC = IC < 0? 0 : (IC > 7? 7 : IC);
251 DC = cpu->machine->cache_pdcache - 12;
252 DC = DC < 0? 0 : (DC > 7? 7 : DC);
253 SC = cpu->machine->cache_secondary - 19;
254 SC = SC < 0? 0 : (SC > 7? 7 : SC);
255 /* According to the R10000 User's Manual: */
256 c->reg[COP0_CONFIG] =
257 ( IC << 29) /* Primary instruction cache size
258 (3 = 32KB) */
259 | ( DC << 26) /* Primary data cache size (3 =
260 32KB) */
261 | ( 0 << 19) /* SCClkDiv */
262 | ( SC << 16) /* SCSize, secondary cache size.
263 0 = 512KB. powers of two */
264 | ( 0 << 15) /* MemEnd */
265 | ( 0 << 14) /* SCCorEn */
266 | ( 1 << 13) /* SCBlkSize. 0=16 words,
267 1=32 words */
268 | ( 0 << 9) /* SysClkDiv */
269 | ( 0 << 7) /* PrcReqMax */
270 | ( 0 << 6) /* PrcElmReq */
271 | ( 0 << 5) /* CohPrcReqTar */
272 | ( 0 << 3) /* Device number */
273 | ( 2 << 0) /* Cache coherency algorithm for
274 kseg0 */
275 ;
276 break;
277 case MIPS_R5900:
278 /*
279 * R5900 is supposed to have the following (according
280 * to NetBSD/playstation2):
281 * cpu0: 16KB/64B 2-way set-associative L1 Instruction
282 * cache, 48 TLB entries
283 * cpu0: 8KB/64B 2-way set-associative write-back L1
284 * Data cache
285 * The following settings are just guesses:
286 * (comments are incorrect)
287 */
288 c->reg[COP0_CONFIG] =
289 ( 0 << 31) /* Master/Checker present bit */
290 | (0x00 << 28) /* EC: system clock divisor,
291 0x00 = '2' */
292 | (0x00 << 24) /* EP */
293 | (0x00 << 22) /* SB */
294 | (0x00 << 21) /* SS */
295 | (0x00 << 20) /* SW */
296 | (0x00 << 18) /* EW: 0=64-bit */
297 | (0x01 << 17) /* SC: 0=secondary cache present,
298 1=non-present */
299 | (0x00 << 16) /* SM: (todo) */
300 | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
301 /* endian mode */
302 | (0x01 << 14) /* ECC: 0=enabled, 1=disabled */
303 | (0x00 << 13) /* EB: (todo) */
304 | (0x00 << 12) /* 0 (resered) */
305 | ( 3 << 9) /* IC: I-cache = 2^(12+IC) bytes
306 (1 = 8KB, 4=64K) */
307 | ( 3 << 6) /* DC: D-cache = 2^(12+DC) bytes
308 (1 = 8KB, 4=64K) */
309 | ( 1 << 5) /* IB: I-cache line size (0=16,
310 1=32) */
311 | ( 1 << 4) /* DB: D-cache line size (0=16,
312 1=32) */
313 | ( 0 << 3) /* CU: todo */
314 | ( 0 << 0) /* kseg0 coherency algorithm
315 (TODO) */
316 ;
317 break;
318 default:fatal("Internal error: No initialization code for"
319 " config0? cpu rev = 0x%x", cpu->cd.mips.cpu_type.rev);
320 exit(1);
321 }
322 }
323
324
325 /*
326 * initialize_cop1():
327 *
328 * Helper function, called from mips_coproc_new().
329 */
330 static void initialize_cop1(struct cpu *cpu, struct mips_coproc *c)
331 {
332 int fpu_rev;
333 uint64_t other_stuff = 0;
334
335 switch (cpu->cd.mips.cpu_type.rev & 0xff) {
336 case MIPS_R2000: fpu_rev = MIPS_R2010; break;
337 case MIPS_R3000: fpu_rev = MIPS_R3010;
338 other_stuff |= 0x40; /* or 0x30? TODO */
339 break;
340 case MIPS_R6000: fpu_rev = MIPS_R6010; break;
341 case MIPS_R4000: fpu_rev = MIPS_R4010; break;
342 case MIPS_4Kc: /* TODO: Is this the same as 5Kc? */
343 case MIPS_5Kc: other_stuff = COP1_REVISION_DOUBLE
344 | COP1_REVISION_SINGLE;
345 case MIPS_R5000:
346 case MIPS_RM5200: fpu_rev = cpu->cd.mips.cpu_type.rev;
347 other_stuff |= 0x10;
348 /* or cpu->cd.mips.cpu_type.sub ? TODO */
349 break;
350 case MIPS_R10000: fpu_rev = MIPS_R10000; break;
351 case MIPS_R12000: fpu_rev = 0x9; break;
352 default: fpu_rev = MIPS_SOFT;
353 }
354
355 c->fcr[COP1_REVISION] = (fpu_rev << 8) | other_stuff;
356
357 #if 0
358 /* These are mentioned in the MIPS64 documentation: */
359 + (1 << 16) /* single */
360 + (1 << 17) /* double */
361 + (1 << 18) /* paired-single */
362 + (1 << 19) /* 3d */
363 #endif
364 }
365
366
367 /*
368 * mips_coproc_new():
369 *
370 * Create a new MIPS coprocessor object.
371 */
372 struct mips_coproc *mips_coproc_new(struct cpu *cpu, int coproc_nr)
373 {
374 struct mips_coproc *c;
375
376 c = malloc(sizeof(struct mips_coproc));
377 if (c == NULL) {
378 fprintf(stderr, "out of memory\n");
379 exit(1);
380 }
381
382 memset(c, 0, sizeof(struct mips_coproc));
383 c->coproc_nr = coproc_nr;
384
385 if (coproc_nr == 0) {
386 c->nr_of_tlbs = cpu->cd.mips.cpu_type.nr_of_tlb_entries;
387 c->tlbs = zeroed_alloc(c->nr_of_tlbs * sizeof(struct mips_tlb));
388
389 /*
390 * Start with nothing in the status register. This makes sure
391 * that we are running in kernel mode with all interrupts
392 * disabled.
393 */
394 c->reg[COP0_STATUS] = 0;
395
396 /* For userland emulation, enable all four coprocessors: */
397 if (cpu->machine->userland_emul)
398 c->reg[COP0_STATUS] |=
399 ((uint32_t)0xf << STATUS_CU_SHIFT);
400
401 /* Hm. Enable coprocessors 0 and 1 even if we're not just
402 emulating userland? TODO: Think about this. */
403 /* if (cpu->machine->prom_emulation) */
404 c->reg[COP0_STATUS] |=
405 ((uint32_t)0x3 << STATUS_CU_SHIFT);
406
407 if (!cpu->machine->prom_emulation)
408 c->reg[COP0_STATUS] |= STATUS_BEV;
409
410 /* Ugly hack for R5900/TX79/C790: */
411 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900)
412 c->reg[COP0_STATUS] |= R5900_STATUS_EIE;
413
414 /* Default pagesize = 4 KB (i.e. dualpage = 8KB) */
415 c->reg[COP0_PAGEMASK] = 0x1fff;
416
417 /* Note: .rev may contain the company ID as well! */
418 c->reg[COP0_PRID] =
419 (0x00 << 24) /* Company Options */
420 | (0x00 << 16) /* Company ID */
421 | (cpu->cd.mips.cpu_type.rev << 8) /* Processor ID */
422 | (cpu->cd.mips.cpu_type.sub) /* Revision */
423 ;
424
425 c->reg[COP0_WIRED] = 0;
426
427 initialize_cop0_config(cpu, c);
428
429 /* Make sure the status register is sign-extended nicely: */
430 c->reg[COP0_STATUS] = (int32_t)c->reg[COP0_STATUS];
431 }
432
433 if (coproc_nr == 1)
434 initialize_cop1(cpu, c);
435
436 return c;
437 }
438
439
440 /*
441 * mips_coproc_tlb_set_entry():
442 *
443 * Used by machine setup code, if a specific machine emulation starts up
444 * with hardcoded virtual to physical mappings.
445 */
446 void mips_coproc_tlb_set_entry(struct cpu *cpu, int entrynr, int size,
447 uint64_t vaddr, uint64_t paddr0, uint64_t paddr1,
448 int valid0, int valid1, int dirty0, int dirty1, int global, int asid,
449 int cachealgo0, int cachealgo1)
450 {
451 if (entrynr < 0 || entrynr >= cpu->cd.mips.coproc[0]->nr_of_tlbs) {
452 printf("mips_coproc_tlb_set_entry(): invalid entry nr: %i\n",
453 entrynr);
454 exit(1);
455 }
456
457 switch (cpu->cd.mips.cpu_type.mmu_model) {
458 case MMU3K:
459 if (size != 4096) {
460 printf("mips_coproc_tlb_set_entry(): invalid pagesize "
461 "(%i) for MMU3K\n", size);
462 exit(1);
463 }
464 cpu->cd.mips.coproc[0]->tlbs[entrynr].hi =
465 (vaddr & R2K3K_ENTRYHI_VPN_MASK) |
466 ((asid << R2K3K_ENTRYHI_ASID_SHIFT) &
467 R2K3K_ENTRYHI_ASID_MASK);
468 cpu->cd.mips.coproc[0]->tlbs[entrynr].lo0 =
469 (paddr0 & R2K3K_ENTRYLO_PFN_MASK) |
470 (cachealgo0? R2K3K_ENTRYLO_N : 0) |
471 (dirty0? R2K3K_ENTRYLO_D : 0) |
472 (valid0? R2K3K_ENTRYLO_V : 0) |
473 (global? R2K3K_ENTRYLO_G : 0);
474 break;
475 default:
476 /* MMU4K and MMU10K, etc: */
477 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
478 cpu->cd.mips.coproc[0]->tlbs[entrynr].hi =
479 (vaddr & ENTRYHI_VPN2_MASK_R10K) |
480 (vaddr & ENTRYHI_R_MASK) |
481 (asid & ENTRYHI_ASID) |
482 (global? TLB_G : 0);
483 else
484 cpu->cd.mips.coproc[0]->tlbs[entrynr].hi =
485 (vaddr & ENTRYHI_VPN2_MASK) |
486 (vaddr & ENTRYHI_R_MASK) |
487 (asid & ENTRYHI_ASID) |
488 (global? TLB_G : 0);
489 /* NOTE: The pagemask size is for a "dual" page: */
490 cpu->cd.mips.coproc[0]->tlbs[entrynr].mask =
491 (2*size - 1) & ~0x1fff;
492 cpu->cd.mips.coproc[0]->tlbs[entrynr].lo0 =
493 (((paddr0 >> 12) << ENTRYLO_PFN_SHIFT) &
494 ENTRYLO_PFN_MASK) |
495 (dirty0? ENTRYLO_D : 0) |
496 (valid0? ENTRYLO_V : 0) |
497 (global? ENTRYLO_G : 0) |
498 ((cachealgo0 << ENTRYLO_C_SHIFT) & ENTRYLO_C_MASK);
499 cpu->cd.mips.coproc[0]->tlbs[entrynr].lo1 =
500 (((paddr1 >> 12) << ENTRYLO_PFN_SHIFT) &
501 ENTRYLO_PFN_MASK) |
502 (dirty1? ENTRYLO_D : 0) |
503 (valid1? ENTRYLO_V : 0) |
504 (global? ENTRYLO_G : 0) |
505 ((cachealgo1 << ENTRYLO_C_SHIFT) & ENTRYLO_C_MASK);
506 /* TODO: R4100, 1KB pages etc */
507 }
508 }
509
510
511 /*
512 * invalidate_asid():
513 *
514 * Go through all entries in the TLB. If an entry has a matching asid, is
515 * valid, and is not global (i.e. the ASID matters), then its virtual address
516 * translation is invalidated.
517 *
518 * Note: In the R3000 case, the asid argument is shifted 6 bits.
519 */
520 static void invalidate_asid(struct cpu *cpu, int asid)
521 {
522 struct mips_coproc *cp = cpu->cd.mips.coproc[0];
523 int i, ntlbs = cp->nr_of_tlbs;
524 struct mips_tlb *tlb = cp->tlbs;
525
526 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
527 for (i=0; i<ntlbs; i++)
528 if ((tlb[i].hi & R2K3K_ENTRYHI_ASID_MASK) == asid
529 && (tlb[i].lo0 & R2K3K_ENTRYLO_V)
530 && !(tlb[i].lo0 & R2K3K_ENTRYLO_G)) {
531 cpu->invalidate_translation_caches(cpu,
532 tlb[i].hi & R2K3K_ENTRYHI_VPN_MASK,
533 INVALIDATE_VADDR);
534 }
535 } else {
536 int non4kpages = 0;
537 uint64_t topbit = 1, fillmask = 0xffffff0000000000ULL;
538
539 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
540 topbit <<= 43;
541 fillmask <<= 4;
542 } else {
543 topbit <<= 39;
544 }
545
546 for (i=0; i<ntlbs; i++) {
547 if (tlb[i].mask != 0 && tlb[i].mask != 0x1800) {
548 non4kpages = 1;
549 continue;
550 }
551
552 if ((tlb[i].hi & ENTRYHI_ASID) == asid &&
553 !(tlb[i].hi & TLB_G)) {
554 uint64_t vaddr0, vaddr1;
555 vaddr0 = cp->tlbs[i].hi & ~fillmask;
556 if (vaddr0 & topbit)
557 vaddr0 |= fillmask;
558 vaddr1 = vaddr0 | 0x1000; /* TODO: mask */
559
560 if (tlb[i].lo0 & ENTRYLO_V)
561 cpu->invalidate_translation_caches(cpu,
562 vaddr0, INVALIDATE_VADDR);
563 if (tlb[i].lo1 & ENTRYLO_V)
564 cpu->invalidate_translation_caches(cpu,
565 vaddr1, INVALIDATE_VADDR);
566 }
567 }
568
569 if (non4kpages) {
570 cpu->invalidate_translation_caches(cpu,
571 0, INVALIDATE_ALL);
572 }
573 }
574 }
575
576
577 /*
578 * coproc_register_read();
579 *
580 * Read a value from a MIPS coprocessor register.
581 */
582 void coproc_register_read(struct cpu *cpu,
583 struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int select)
584 {
585 int unimpl = 1;
586
587 if (cp->coproc_nr==0 && reg_nr==COP0_INDEX) unimpl = 0;
588 if (cp->coproc_nr==0 && reg_nr==COP0_RANDOM) unimpl = 0;
589 if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO0) unimpl = 0;
590 if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO1) unimpl = 0;
591 if (cp->coproc_nr==0 && reg_nr==COP0_CONTEXT) unimpl = 0;
592 if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK) unimpl = 0;
593 if (cp->coproc_nr==0 && reg_nr==COP0_WIRED) unimpl = 0;
594 if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR) unimpl = 0;
595 if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) unimpl = 0;
596 if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI) unimpl = 0;
597 if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE) unimpl = 0;
598 if (cp->coproc_nr==0 && reg_nr==COP0_STATUS) unimpl = 0;
599 if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE) unimpl = 0;
600 if (cp->coproc_nr==0 && reg_nr==COP0_EPC) unimpl = 0;
601 if (cp->coproc_nr==0 && reg_nr==COP0_PRID) unimpl = 0;
602 if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG) {
603 if (select > 0) {
604 switch (select) {
605 case 1: *ptr = cpu->cd.mips.cop0_config_select1;
606 break;
607 default:fatal("coproc_register_read(): unimplemented"
608 " config register select %i\n", select);
609 exit(1);
610 }
611 return;
612 }
613 unimpl = 0;
614 }
615 if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR) unimpl = 0;
616 if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO) unimpl = 0;
617 if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI) unimpl = 0;
618 if (cp->coproc_nr==0 && reg_nr==COP0_XCONTEXT) unimpl = 0;
619 if (cp->coproc_nr==0 && reg_nr==COP0_ERRCTL) unimpl = 0;
620 if (cp->coproc_nr==0 && reg_nr==COP0_CACHEERR) unimpl = 0;
621 if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_LO) unimpl = 0;
622 if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_HI) unimpl = 0;
623 if (cp->coproc_nr==0 && reg_nr==COP0_ERROREPC) unimpl = 0;
624 if (cp->coproc_nr==0 && reg_nr==COP0_RESERV22) {
625 /* Used by Linux on Linksys WRT54G */
626 unimpl = 0;
627 }
628 if (cp->coproc_nr==0 && reg_nr==COP0_DEBUG) unimpl = 0;
629 if (cp->coproc_nr==0 && reg_nr==COP0_PERFCNT) unimpl = 0;
630 if (cp->coproc_nr==0 && reg_nr==COP0_DESAVE) unimpl = 0;
631
632 if (cp->coproc_nr==1) unimpl = 0;
633
634 if (unimpl) {
635 fatal("cpu%i: warning: read from unimplemented coproc%i"
636 " register %i (%s)\n", cpu->cpu_id, cp->coproc_nr, reg_nr,
637 cp->coproc_nr==0? cop0_names[reg_nr] : "?");
638
639 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
640 cp->coproc_nr, 0, 0, 0);
641 return;
642 }
643
644 *ptr = cp->reg[reg_nr];
645 }
646
647
648 /*
649 * coproc_register_write();
650 *
651 * Write a value to a MIPS coprocessor register.
652 */
653 void coproc_register_write(struct cpu *cpu,
654 struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64,
655 int select)
656 {
657 int unimpl = 1;
658 int readonly = 0;
659 uint64_t tmp = *ptr;
660 uint64_t tmp2 = 0, old;
661 int inval = 0, old_asid, oldmode;
662
663 switch (cp->coproc_nr) {
664 case 0:
665 /* COPROC 0: */
666 switch (reg_nr) {
667 case COP0_INDEX:
668 case COP0_RANDOM:
669 unimpl = 0;
670 break;
671 case COP0_ENTRYLO0:
672 unimpl = 0;
673 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
674 (tmp & 0xff)!=0) {
675 /* char *symbol;
676 uint64_t offset;
677 symbol = get_symbol_name(cpu->pc, &offset);
678 fatal("YO! pc = 0x%08llx <%s> "
679 "lo=%016llx\n", (long long)
680 cpu->pc, symbol? symbol :
681 "no symbol", (long long)tmp); */
682 tmp &= (R2K3K_ENTRYLO_PFN_MASK |
683 R2K3K_ENTRYLO_N | R2K3K_ENTRYLO_D |
684 R2K3K_ENTRYLO_V | R2K3K_ENTRYLO_G);
685 } else if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
686 tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
687 ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
688 }
689 break;
690 case COP0_BADVADDR:
691 /* Hm. Irix writes to this register. (Why?) */
692 unimpl = 0;
693 break;
694 case COP0_ENTRYLO1:
695 unimpl = 0;
696 if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
697 tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
698 ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
699 }
700 break;
701 case COP0_CONTEXT:
702 old = cp->reg[COP0_CONTEXT];
703 cp->reg[COP0_CONTEXT] = tmp;
704 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
705 cp->reg[COP0_CONTEXT] &=
706 ~R2K3K_CONTEXT_BADVPN_MASK;
707 cp->reg[COP0_CONTEXT] |=
708 (old & R2K3K_CONTEXT_BADVPN_MASK);
709 } else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
710 cp->reg[COP0_CONTEXT] &=
711 ~CONTEXT_BADVPN2_MASK_R4100;
712 cp->reg[COP0_CONTEXT] |=
713 (old & CONTEXT_BADVPN2_MASK_R4100);
714 } else {
715 cp->reg[COP0_CONTEXT] &=
716 ~CONTEXT_BADVPN2_MASK;
717 cp->reg[COP0_CONTEXT] |=
718 (old & CONTEXT_BADVPN2_MASK);
719 }
720 return;
721 case COP0_PAGEMASK:
722 tmp2 = tmp >> PAGEMASK_SHIFT;
723 if (tmp2 != 0x000 &&
724 tmp2 != 0x003 &&
725 tmp2 != 0x00f &&
726 tmp2 != 0x03f &&
727 tmp2 != 0x0ff &&
728 tmp2 != 0x3ff &&
729 tmp2 != 0xfff)
730 fatal("cpu%i: trying to write an invalid"
731 " pagemask 0x%08lx to COP0_PAGEMASK\n",
732 cpu->cpu_id, (long)tmp);
733 unimpl = 0;
734 break;
735 case COP0_WIRED:
736 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
737 fatal("cpu%i: r2k/r3k wired register must "
738 "always be 8\n", cpu->cpu_id);
739 tmp = 8;
740 }
741 cp->reg[COP0_RANDOM] = cp->nr_of_tlbs-1;
742 tmp &= INDEX_MASK;
743 unimpl = 0;
744 break;
745 case COP0_COUNT:
746 if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
747 fatal("WARNING: trying to write a 64-bit value"
748 " to the COUNT register!\n");
749 tmp = (int64_t)(int32_t)tmp;
750 unimpl = 0;
751 break;
752 case COP0_COMPARE:
753 /* Clear the timer interrupt bit (bit 7): */
754 cpu->cd.mips.compare_register_set = 1;
755 mips_cpu_interrupt_ack(cpu, 7);
756 if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
757 fatal("WARNING: trying to write a 64-bit value"
758 " to the COMPARE register!\n");
759 tmp = (int64_t)(int32_t)tmp;
760 unimpl = 0;
761 break;
762 case COP0_ENTRYHI:
763 /*
764 * Translation caches must be invalidated if the
765 * ASID changes:
766 */
767 switch (cpu->cd.mips.cpu_type.mmu_model) {
768 case MMU3K:
769 old_asid = cp->reg[COP0_ENTRYHI] &
770 R2K3K_ENTRYHI_ASID_MASK;
771 if ((cp->reg[COP0_ENTRYHI] &
772 R2K3K_ENTRYHI_ASID_MASK) !=
773 (tmp & R2K3K_ENTRYHI_ASID_MASK))
774 inval = 1;
775 break;
776 default:
777 old_asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
778 if ((cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID) !=
779 (tmp & ENTRYHI_ASID))
780 inval = 1;
781 break;
782 }
783
784 if (inval)
785 invalidate_asid(cpu, old_asid);
786
787 unimpl = 0;
788 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
789 (tmp & 0x3f)!=0) {
790 /* char *symbol;
791 uint64_t offset;
792 symbol = get_symbol_name(cpu->pc,
793 &offset);
794 fatal("YO! pc = 0x%08llx <%s> "
795 "hi=%016llx\n", (long long)cpu->pc,
796 symbol? symbol :
797 "no symbol", (long long)tmp); */
798 tmp &= ~0x3f;
799 }
800 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
801 tmp &= (R2K3K_ENTRYHI_VPN_MASK |
802 R2K3K_ENTRYHI_ASID_MASK);
803 else if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
804 tmp &= (ENTRYHI_R_MASK |
805 ENTRYHI_VPN2_MASK_R10K | ENTRYHI_ASID);
806 else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
807 tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
808 0x1800 | ENTRYHI_ASID);
809 else
810 tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
811 ENTRYHI_ASID);
812 break;
813 case COP0_EPC:
814 unimpl = 0;
815 break;
816 case COP0_PRID:
817 readonly = 1;
818 break;
819 case COP0_CONFIG:
820 if (select > 0) {
821 switch (select) {
822 case 1: cpu->cd.mips.cop0_config_select1 = tmp;
823 break;
824 default:fatal("coproc_register_write(): unimpl"
825 "emented config register select "
826 "%i\n", select);
827 exit(1);
828 }
829 return;
830 }
831
832 /* fatal("COP0_CONFIG: modifying K0 bits: "
833 "0x%08x => ", cp->reg[reg_nr]); */
834 tmp = *ptr;
835 tmp &= 0x3; /* only bits 2..0 can be written */
836 cp->reg[reg_nr] &= ~(0x3); cp->reg[reg_nr] |= tmp;
837 /* fatal("0x%08x\n", cp->reg[reg_nr]); */
838 return;
839 case COP0_STATUS:
840 oldmode = cp->reg[COP0_STATUS];
841 tmp &= ~(1 << 21); /* bit 21 is read-only */
842
843 /*
844 * When isolating caches, invalidate all translations.
845 * During the isolation, a special hack in memory_rw.c
846 * prevents translation tables from being updated, so
847 * the translation caches don't have to be invalidated
848 * when switching back to normal mode.
849 */
850 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
851 (oldmode & MIPS1_ISOL_CACHES) !=
852 (tmp & MIPS1_ISOL_CACHES)) {
853 /* Invalidate everything if we are switching
854 to isolated mode: */
855 if (tmp & MIPS1_ISOL_CACHES) {
856 cpu->invalidate_translation_caches(
857 cpu, 0, INVALIDATE_ALL);
858 }
859 }
860 unimpl = 0;
861 break;
862 case COP0_CAUSE:
863 /* A write to the cause register only
864 affects IM bits 0 and 1: */
865 cp->reg[reg_nr] &= ~(0x3 << STATUS_IM_SHIFT);
866 cp->reg[reg_nr] |= (tmp & (0x3 << STATUS_IM_SHIFT));
867 return;
868 case COP0_FRAMEMASK:
869 /* TODO: R10000 */
870 unimpl = 0;
871 break;
872 case COP0_TAGDATA_LO:
873 case COP0_TAGDATA_HI:
874 /* TODO: R4300 and others? */
875 unimpl = 0;
876 break;
877 case COP0_LLADDR:
878 unimpl = 0;
879 break;
880 case COP0_WATCHLO:
881 case COP0_WATCHHI:
882 unimpl = 0;
883 break;
884 case COP0_XCONTEXT:
885 /*
886 * TODO: According to the R10000 manual, the R4400
887 * shares the PTEbase portion of the context registers
888 * (that is, xcontext and context). On R10000, they
889 * are separate registers.
890 */
891 /* debug("[ xcontext 0x%016llx ]\n", tmp); */
892 unimpl = 0;
893 break;
894
895 /* Most of these are actually TODOs: */
896 case COP0_ERROREPC:
897 case COP0_DEPC:
898 case COP0_RESERV22: /* Used by Linux on Linksys WRT54G */
899 case COP0_DESAVE:
900 case COP0_PERFCNT:
901 case COP0_ERRCTL: /* R10000 */
902 unimpl = 0;
903 break;
904 }
905 break;
906
907 case 1:
908 /* COPROC 1: */
909 unimpl = 0;
910 break;
911 }
912
913 if (unimpl) {
914 fatal("cpu%i: warning: write to unimplemented coproc%i "
915 "register %i (%s), data = 0x%016llx\n", cpu->cpu_id,
916 cp->coproc_nr, reg_nr, cp->coproc_nr==0?
917 cop0_names[reg_nr] : "?", (long long)tmp);
918
919 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
920 cp->coproc_nr, 0, 0, 0);
921 return;
922 }
923
924 if (readonly) {
925 fatal("cpu%i: warning: write to READONLY coproc%i register "
926 "%i ignored\n", cpu->cpu_id, cp->coproc_nr, reg_nr);
927 return;
928 }
929
930 cp->reg[reg_nr] = tmp;
931
932 if (!flag64)
933 cp->reg[reg_nr] = (int64_t)(int32_t)cp->reg[reg_nr];
934 }
935
936
937 /*
938 * MIPS floating-point stuff:
939 *
940 * TODO: Move this to some other file?
941 */
942 static int mips_fmt_to_ieee_fmt[32] = {
943 0, 0, 0, 0, 0, 0, 0, 0,
944 0, 0, 0, 0, 0, 0, 0, 0,
945 IEEE_FMT_S, IEEE_FMT_D, 0, 0,
946 IEEE_FMT_W, IEEE_FMT_L, /* PS (Paired Single) */ 0, 0,
947 0, 0, 0, 0, 0, 0, 0, 0 };
948
949 static char *fmtname[32] = {
950 "0", "1", "2", "3", "4", "5", "6", "7",
951 "8", "9", "10", "11", "12", "13", "14", "15",
952 "s", "d", "18", "19", "w", "l", "ps", "23",
953 "24", "25", "26", "27", "28", "29", "30", "31" };
954
955 static char *ccname[16] = {
956 "f", "un", "eq", "ueq", "olt", "ult", "ole", "ule",
957 "sf", "ngle", "seq", "ngl", "lt", "nge", "le", "ngt" };
958
959 #define FPU_OP_ADD 1
960 #define FPU_OP_SUB 2
961 #define FPU_OP_MUL 3
962 #define FPU_OP_DIV 4
963 #define FPU_OP_SQRT 5
964 #define FPU_OP_MOV 6
965 #define FPU_OP_CVT 7
966 #define FPU_OP_C 8
967 #define FPU_OP_ABS 9
968 #define FPU_OP_NEG 10
969 /* TODO: CEIL.L, CEIL.W, FLOOR.L, FLOOR.W, RECIP, ROUND.L, ROUND.W, RSQRT */
970
971
972 /*
973 * fpu_store_float_value():
974 *
975 * Stores a float value (actually a double) in fmt format.
976 */
977 static void fpu_store_float_value(struct mips_coproc *cp, int fd,
978 double nf, int fmt, int nan)
979 {
980 int ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
981 uint64_t r = ieee_store_float_value(nf, ieee_fmt, nan);
982
983 /*
984 * TODO: This is for 32-bit mode. It has to be updated later
985 * for 64-bit coprocessor functionality!
986 */
987 if (fmt == COP1_FMT_D || fmt == COP1_FMT_L) {
988 cp->reg[fd] = r & 0xffffffffULL;
989 cp->reg[(fd+1) & 31] = (r >> 32) & 0xffffffffULL;
990
991 if (cp->reg[fd] & 0x80000000ULL)
992 cp->reg[fd] |= 0xffffffff00000000ULL;
993 if (cp->reg[fd+1] & 0x80000000ULL)
994 cp->reg[fd+1] |= 0xffffffff00000000ULL;
995 } else {
996 cp->reg[fd] = r & 0xffffffffULL;
997
998 if (cp->reg[fd] & 0x80000000ULL)
999 cp->reg[fd] |= 0xffffffff00000000ULL;
1000 }
1001 }
1002
1003
1004 /*
1005 * fpu_op():
1006 *
1007 * Perform a floating-point operation. For those of fs and ft that are >= 0,
1008 * those numbers are interpreted into local variables.
1009 *
1010 * Only FPU_OP_C (compare) returns anything of interest, 1 for true, 0 for
1011 * false.
1012 */
1013 static int fpu_op(struct cpu *cpu, struct mips_coproc *cp, int op, int fmt,
1014 int ft, int fs, int fd, int cond, int output_fmt)
1015 {
1016 /* Potentially two input registers, fs and ft */
1017 struct ieee_float_value float_value[2];
1018 int unordered, nan, ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1019 uint64_t fs_v = 0;
1020 double nf;
1021
1022 if (fs >= 0) {
1023 fs_v = cp->reg[fs];
1024 /* TODO: register-pair mode and plain
1025 register mode? "FR" bit? */
1026 if (fmt == COP1_FMT_D || fmt == COP1_FMT_L)
1027 fs_v = (fs_v & 0xffffffffULL) +
1028 (cp->reg[(fs + 1) & 31] << 32);
1029 ieee_interpret_float_value(fs_v, &float_value[0], ieee_fmt);
1030 }
1031 if (ft >= 0) {
1032 uint64_t v = cp->reg[ft];
1033 /* TODO: register-pair mode and
1034 plain register mode? "FR" bit? */
1035 if (fmt == COP1_FMT_D || fmt == COP1_FMT_L)
1036 v = (v & 0xffffffffULL) +
1037 (cp->reg[(ft + 1) & 31] << 32);
1038 ieee_interpret_float_value(v, &float_value[1], ieee_fmt);
1039 }
1040
1041 switch (op) {
1042 case FPU_OP_ADD:
1043 nf = float_value[0].f + float_value[1].f;
1044 /* debug(" add: %f + %f = %f\n",
1045 float_value[0].f, float_value[1].f, nf); */
1046 fpu_store_float_value(cp, fd, nf, output_fmt,
1047 float_value[0].nan || float_value[1].nan);
1048 break;
1049 case FPU_OP_SUB:
1050 nf = float_value[0].f - float_value[1].f;
1051 /* debug(" sub: %f - %f = %f\n",
1052 float_value[0].f, float_value[1].f, nf); */
1053 fpu_store_float_value(cp, fd, nf, output_fmt,
1054 float_value[0].nan || float_value[1].nan);
1055 break;
1056 case FPU_OP_MUL:
1057 nf = float_value[0].f * float_value[1].f;
1058 /* debug(" mul: %f * %f = %f\n",
1059 float_value[0].f, float_value[1].f, nf); */
1060 fpu_store_float_value(cp, fd, nf, output_fmt,
1061 float_value[0].nan || float_value[1].nan);
1062 break;
1063 case FPU_OP_DIV:
1064 nan = float_value[0].nan || float_value[1].nan;
1065 if (fabs(float_value[1].f) > 0.00000000001)
1066 nf = float_value[0].f / float_value[1].f;
1067 else {
1068 fatal("DIV by zero !!!!\n");
1069 nf = 0.0; /* TODO */
1070 nan = 1;
1071 }
1072 /* debug(" div: %f / %f = %f\n",
1073 float_value[0].f, float_value[1].f, nf); */
1074 fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1075 break;
1076 case FPU_OP_SQRT:
1077 nan = float_value[0].nan;
1078 if (float_value[0].f >= 0.0)
1079 nf = sqrt(float_value[0].f);
1080 else {
1081 fatal("SQRT by less than zero, %f !!!!\n",
1082 float_value[0].f);
1083 nf = 0.0; /* TODO */
1084 nan = 1;
1085 }
1086 /* debug(" sqrt: %f => %f\n", float_value[0].f, nf); */
1087 fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1088 break;
1089 case FPU_OP_ABS:
1090 nf = fabs(float_value[0].f);
1091 /* debug(" abs: %f => %f\n", float_value[0].f, nf); */
1092 fpu_store_float_value(cp, fd, nf, output_fmt,
1093 float_value[0].nan);
1094 break;
1095 case FPU_OP_NEG:
1096 nf = - float_value[0].f;
1097 /* debug(" neg: %f => %f\n", float_value[0].f, nf); */
1098 fpu_store_float_value(cp, fd, nf, output_fmt,
1099 float_value[0].nan);
1100 break;
1101 case FPU_OP_CVT:
1102 nf = float_value[0].f;
1103 /* debug(" mov: %f => %f\n", float_value[0].f, nf); */
1104 fpu_store_float_value(cp, fd, nf, output_fmt,
1105 float_value[0].nan);
1106 break;
1107 case FPU_OP_MOV:
1108 /* Non-arithmetic move: */
1109 /*
1110 * TODO: this is for 32-bit mode. It has to be updated later
1111 * for 64-bit coprocessor stuff.
1112 */
1113 if (output_fmt == COP1_FMT_D || output_fmt == COP1_FMT_L) {
1114 cp->reg[fd] = fs_v & 0xffffffffULL;
1115 cp->reg[(fd+1) & 31] = (fs_v >> 32) & 0xffffffffULL;
1116 if (cp->reg[fd] & 0x80000000ULL)
1117 cp->reg[fd] |= 0xffffffff00000000ULL;
1118 if (cp->reg[fd+1] & 0x80000000ULL)
1119 cp->reg[fd+1] |= 0xffffffff00000000ULL;
1120 } else {
1121 cp->reg[fd] = fs_v & 0xffffffffULL;
1122 if (cp->reg[fd] & 0x80000000ULL)
1123 cp->reg[fd] |= 0xffffffff00000000ULL;
1124 }
1125 break;
1126 case FPU_OP_C:
1127 /* debug(" c: cond=%i\n", cond); */
1128
1129 unordered = 0;
1130 if (float_value[0].nan || float_value[1].nan)
1131 unordered = 1;
1132
1133 switch (cond) {
1134 case 2: /* Equal */
1135 return (float_value[0].f == float_value[1].f);
1136 case 4: /* Ordered or Less than */
1137 return (float_value[0].f < float_value[1].f)
1138 || !unordered;
1139 case 5: /* Unordered or Less than */
1140 return (float_value[0].f < float_value[1].f)
1141 || unordered;
1142 case 6: /* Ordered or Less than or Equal */
1143 return (float_value[0].f <= float_value[1].f)
1144 || !unordered;
1145 case 7: /* Unordered or Less than or Equal */
1146 return (float_value[0].f <= float_value[1].f)
1147 || unordered;
1148 case 12:/* Less than */
1149 return (float_value[0].f < float_value[1].f);
1150 case 14:/* Less than or equal */
1151 return (float_value[0].f <= float_value[1].f);
1152
1153 /* The following are not commonly used, so I'll move these out
1154 of the if-0 on a case-by-case basis. */
1155 #if 0
1156 case 0: return 0; /* False */
1157 case 1: return 0; /* Unordered */
1158 case 3: return (float_value[0].f == float_value[1].f);
1159 /* Unordered or Equal */
1160 case 8: return 0; /* Signaling false */
1161 case 9: return 0; /* Not Greater than or Less than or Equal */
1162 case 10:return (float_value[0].f == float_value[1].f); /* Signaling Equal */
1163 case 11:return (float_value[0].f == float_value[1].f); /* Not Greater
1164 than or Less than */
1165 case 13:return !(float_value[0].f >= float_value[1].f); /* Not greater
1166 than or equal */
1167 case 15:return !(float_value[0].f > float_value[1].f); /* Not greater than */
1168 #endif
1169
1170 default:
1171 fatal("fpu_op(): unimplemented condition "
1172 "code %i. see cpu_mips_coproc.c\n", cond);
1173 }
1174 break;
1175 default:
1176 fatal("fpu_op(): unimplemented op %i\n", op);
1177 }
1178
1179 return 0;
1180 }
1181
1182
1183 /*
1184 * fpu_function():
1185 *
1186 * Returns 1 if function was implemented, 0 otherwise.
1187 * Debug trace should be printed for known instructions.
1188 */
1189 static int fpu_function(struct cpu *cpu, struct mips_coproc *cp,
1190 uint32_t function, int unassemble_only)
1191 {
1192 int fd, fs, ft, fmt, cond, cc;
1193
1194 fmt = (function >> 21) & 31;
1195 ft = (function >> 16) & 31;
1196 fs = (function >> 11) & 31;
1197 cc = (function >> 8) & 7;
1198 fd = (function >> 6) & 31;
1199 cond = (function >> 0) & 15;
1200
1201
1202 /* bc1f, bc1t, bc1fl, bc1tl: */
1203 if ((function & 0x03e00000) == 0x01000000) {
1204 int nd, tf, imm, cond_true;
1205 char *instr_mnem;
1206
1207 /* cc are bits 20..18: */
1208 cc = (function >> 18) & 7;
1209 nd = (function >> 17) & 1;
1210 tf = (function >> 16) & 1;
1211 imm = function & 65535;
1212 if (imm >= 32768)
1213 imm -= 65536;
1214
1215 instr_mnem = NULL;
1216 if (nd == 0 && tf == 0) instr_mnem = "bc1f";
1217 if (nd == 0 && tf == 1) instr_mnem = "bc1t";
1218 if (nd == 1 && tf == 0) instr_mnem = "bc1fl";
1219 if (nd == 1 && tf == 1) instr_mnem = "bc1tl";
1220
1221 if (cpu->machine->instruction_trace || unassemble_only)
1222 debug("%s\t%i,0x%016llx\n", instr_mnem, cc,
1223 (long long) (cpu->pc + (imm << 2)));
1224 if (unassemble_only)
1225 return 1;
1226
1227 if (cpu->delay_slot) {
1228 fatal("%s: jump inside a jump's delay slot, "
1229 "or similar. TODO\n", instr_mnem);
1230 cpu->running = 0;
1231 return 1;
1232 }
1233
1234 /* Both the FCCR and FCSR contain condition code bits... */
1235 if (cc == 0)
1236 cond_true = (cp->fcr[MIPS_FPU_FCSR] >>
1237 MIPS_FCSR_FCC0_SHIFT) & 1;
1238 else
1239 cond_true = (cp->fcr[MIPS_FPU_FCSR] >>
1240 (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1241
1242 if (!tf)
1243 cond_true = !cond_true;
1244
1245 if (cond_true) {
1246 cpu->delay_slot = TO_BE_DELAYED;
1247 cpu->delay_jmpaddr = cpu->pc + (imm << 2);
1248 } else {
1249 /* "likely": */
1250 if (nd) {
1251 /* nullify the delay slot */
1252 cpu->cd.mips.nullify_next = 1;
1253 }
1254 }
1255
1256 return 1;
1257 }
1258
1259 /* add.fmt: Floating-point add */
1260 if ((function & 0x0000003f) == 0x00000000) {
1261 if (cpu->machine->instruction_trace || unassemble_only)
1262 debug("add.%s\tr%i,r%i,r%i\n",
1263 fmtname[fmt], fd, fs, ft);
1264 if (unassemble_only)
1265 return 1;
1266
1267 fpu_op(cpu, cp, FPU_OP_ADD, fmt, ft, fs, fd, -1, fmt);
1268 return 1;
1269 }
1270
1271 /* sub.fmt: Floating-point subtract */
1272 if ((function & 0x0000003f) == 0x00000001) {
1273 if (cpu->machine->instruction_trace || unassemble_only)
1274 debug("sub.%s\tr%i,r%i,r%i\n",
1275 fmtname[fmt], fd, fs, ft);
1276 if (unassemble_only)
1277 return 1;
1278
1279 fpu_op(cpu, cp, FPU_OP_SUB, fmt, ft, fs, fd, -1, fmt);
1280 return 1;
1281 }
1282
1283 /* mul.fmt: Floating-point multiply */
1284 if ((function & 0x0000003f) == 0x00000002) {
1285 if (cpu->machine->instruction_trace || unassemble_only)
1286 debug("mul.%s\tr%i,r%i,r%i\n",
1287 fmtname[fmt], fd, fs, ft);
1288 if (unassemble_only)
1289 return 1;
1290
1291 fpu_op(cpu, cp, FPU_OP_MUL, fmt, ft, fs, fd, -1, fmt);
1292 return 1;
1293 }
1294
1295 /* div.fmt: Floating-point divide */
1296 if ((function & 0x0000003f) == 0x00000003) {
1297 if (cpu->machine->instruction_trace || unassemble_only)
1298 debug("div.%s\tr%i,r%i,r%i\n",
1299 fmtname[fmt], fd, fs, ft);
1300 if (unassemble_only)
1301 return 1;
1302
1303 fpu_op(cpu, cp, FPU_OP_DIV, fmt, ft, fs, fd, -1, fmt);
1304 return 1;
1305 }
1306
1307 /* sqrt.fmt: Floating-point square-root */
1308 if ((function & 0x001f003f) == 0x00000004) {
1309 if (cpu->machine->instruction_trace || unassemble_only)
1310 debug("sqrt.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1311 if (unassemble_only)
1312 return 1;
1313
1314 fpu_op(cpu, cp, FPU_OP_SQRT, fmt, -1, fs, fd, -1, fmt);
1315 return 1;
1316 }
1317
1318 /* abs.fmt: Floating-point absolute value */
1319 if ((function & 0x001f003f) == 0x00000005) {
1320 if (cpu->machine->instruction_trace || unassemble_only)
1321 debug("abs.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1322 if (unassemble_only)
1323 return 1;
1324
1325 fpu_op(cpu, cp, FPU_OP_ABS, fmt, -1, fs, fd, -1, fmt);
1326 return 1;
1327 }
1328
1329 /* mov.fmt: Floating-point (non-arithmetic) move */
1330 if ((function & 0x0000003f) == 0x00000006) {
1331 if (cpu->machine->instruction_trace || unassemble_only)
1332 debug("mov.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1333 if (unassemble_only)
1334 return 1;
1335
1336 fpu_op(cpu, cp, FPU_OP_MOV, fmt, -1, fs, fd, -1, fmt);
1337 return 1;
1338 }
1339
1340 /* neg.fmt: Floating-point negate */
1341 if ((function & 0x001f003f) == 0x00000007) {
1342 if (cpu->machine->instruction_trace || unassemble_only)
1343 debug("neg.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1344 if (unassemble_only)
1345 return 1;
1346
1347 fpu_op(cpu, cp, FPU_OP_NEG, fmt, -1, fs, fd, -1, fmt);
1348 return 1;
1349 }
1350
1351 /* trunc.l.fmt: Truncate */
1352 if ((function & 0x001f003f) == 0x00000009) {
1353 if (cpu->machine->instruction_trace || unassemble_only)
1354 debug("trunc.l.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1355 if (unassemble_only)
1356 return 1;
1357
1358 /* TODO: not CVT? */
1359
1360 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_L);
1361 return 1;
1362 }
1363
1364 /* trunc.w.fmt: Truncate */
1365 if ((function & 0x001f003f) == 0x0000000d) {
1366 if (cpu->machine->instruction_trace || unassemble_only)
1367 debug("trunc.w.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1368 if (unassemble_only)
1369 return 1;
1370
1371 /* TODO: not CVT? */
1372
1373 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_W);
1374 return 1;
1375 }
1376
1377 /* c.cond.fmt: Floating-point compare */
1378 if ((function & 0x000000f0) == 0x00000030) {
1379 int cond_true;
1380 int bit;
1381
1382 if (cpu->machine->instruction_trace || unassemble_only)
1383 debug("c.%s.%s\tcc%i,r%i,r%i\n", ccname[cond],
1384 fmtname[fmt], cc, fs, ft);
1385 if (unassemble_only)
1386 return 1;
1387
1388 cond_true = fpu_op(cpu, cp, FPU_OP_C, fmt,
1389 ft, fs, -1, cond, fmt);
1390
1391 /*
1392 * Both the FCCR and FCSR contain condition code bits:
1393 * FCCR: bits 7..0
1394 * FCSR: bits 31..25 and 23
1395 */
1396 cp->fcr[MIPS_FPU_FCCR] &= ~(1 << cc);
1397 if (cond_true)
1398 cp->fcr[MIPS_FPU_FCCR] |= (1 << cc);
1399
1400 if (cc == 0) {
1401 bit = 1 << MIPS_FCSR_FCC0_SHIFT;
1402 cp->fcr[MIPS_FPU_FCSR] &= ~bit;
1403 if (cond_true)
1404 cp->fcr[MIPS_FPU_FCSR] |= bit;
1405 } else {
1406 bit = 1 << (MIPS_FCSR_FCC1_SHIFT + cc-1);
1407 cp->fcr[MIPS_FPU_FCSR] &= ~bit;
1408 if (cond_true)
1409 cp->fcr[MIPS_FPU_FCSR] |= bit;
1410 }
1411
1412 return 1;
1413 }
1414
1415 /* cvt.s.fmt: Convert to single floating-point */
1416 if ((function & 0x001f003f) == 0x00000020) {
1417 if (cpu->machine->instruction_trace || unassemble_only)
1418 debug("cvt.s.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1419 if (unassemble_only)
1420 return 1;
1421
1422 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_S);
1423 return 1;
1424 }
1425
1426 /* cvt.d.fmt: Convert to double floating-point */
1427 if ((function & 0x001f003f) == 0x00000021) {
1428 if (cpu->machine->instruction_trace || unassemble_only)
1429 debug("cvt.d.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1430 if (unassemble_only)
1431 return 1;
1432
1433 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_D);
1434 return 1;
1435 }
1436
1437 /* cvt.w.fmt: Convert to word fixed-point */
1438 if ((function & 0x001f003f) == 0x00000024) {
1439 if (cpu->machine->instruction_trace || unassemble_only)
1440 debug("cvt.w.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1441 if (unassemble_only)
1442 return 1;
1443
1444 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_W);
1445 return 1;
1446 }
1447
1448 return 0;
1449 }
1450
1451
1452 /*
1453 * coproc_tlbpr():
1454 *
1455 * 'tlbp' and 'tlbr'.
1456 */
1457 void coproc_tlbpr(struct cpu *cpu, int readflag)
1458 {
1459 struct mips_coproc *cp = cpu->cd.mips.coproc[0];
1460 int i, found, g_bit;
1461 uint64_t vpn2, xmask;
1462
1463 /* Read: */
1464 if (readflag) {
1465 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1466 i = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK) >>
1467 R2K3K_INDEX_SHIFT;
1468 if (i >= cp->nr_of_tlbs) {
1469 /* TODO: exception? */
1470 fatal("warning: tlbr from index %i (too "
1471 "high)\n", i);
1472 return;
1473 }
1474
1475 /*
1476 * TODO: Hm. Earlier I had an & ~0x3f on the high
1477 * assignment and an & ~0xff on the lo0 assignment.
1478 * I wonder why.
1479 */
1480
1481 cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi; /* & ~0x3f; */
1482 cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;/* & ~0xff; */
1483 } else {
1484 /* R4000: */
1485 i = cp->reg[COP0_INDEX] & INDEX_MASK;
1486 if (i >= cp->nr_of_tlbs) /* TODO: exception */
1487 return;
1488
1489 cp->reg[COP0_PAGEMASK] = cp->tlbs[i].mask;
1490 cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi;
1491 cp->reg[COP0_ENTRYLO1] = cp->tlbs[i].lo1;
1492 cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;
1493
1494 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1495 /* R4100 don't have the G bit in entryhi */
1496 } else {
1497 /* R4000 etc: */
1498 cp->reg[COP0_ENTRYHI] &= ~TLB_G;
1499 g_bit = cp->tlbs[i].hi & TLB_G;
1500
1501 cp->reg[COP0_ENTRYLO0] &= ~ENTRYLO_G;
1502 cp->reg[COP0_ENTRYLO1] &= ~ENTRYLO_G;
1503 if (g_bit) {
1504 cp->reg[COP0_ENTRYLO0] |= ENTRYLO_G;
1505 cp->reg[COP0_ENTRYLO1] |= ENTRYLO_G;
1506 }
1507 }
1508 }
1509
1510 return;
1511 }
1512
1513 /* Probe: */
1514 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1515 vpn2 = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
1516 found = -1;
1517 for (i=0; i<cp->nr_of_tlbs; i++)
1518 if ( ((cp->tlbs[i].hi & R2K3K_ENTRYHI_ASID_MASK) ==
1519 (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK))
1520 || cp->tlbs[i].lo0 & R2K3K_ENTRYLO_G)
1521 if ((cp->tlbs[i].hi & R2K3K_ENTRYHI_VPN_MASK)
1522 == vpn2) {
1523 found = i;
1524 break;
1525 }
1526 } else {
1527 /* R4000 and R10000: */
1528 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1529 xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K;
1530 else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
1531 xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800;
1532 else
1533 xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK;
1534 vpn2 = cp->reg[COP0_ENTRYHI] & xmask;
1535 found = -1;
1536 for (i=0; i<cp->nr_of_tlbs; i++) {
1537 int gbit = cp->tlbs[i].hi & TLB_G;
1538 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
1539 gbit = (cp->tlbs[i].lo0 & ENTRYLO_G) &&
1540 (cp->tlbs[i].lo1 & ENTRYLO_G);
1541
1542 if ( ((cp->tlbs[i].hi & ENTRYHI_ASID) ==
1543 (cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID)) || gbit) {
1544 uint64_t a = vpn2 & ~cp->tlbs[i].mask;
1545 uint64_t b = (cp->tlbs[i].hi & xmask) &
1546 ~cp->tlbs[i].mask;
1547 if (a == b) {
1548 found = i;
1549 break;
1550 }
1551 }
1552 }
1553 }
1554 if (found == -1)
1555 cp->reg[COP0_INDEX] = INDEX_P;
1556 else {
1557 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1558 cp->reg[COP0_INDEX] = found << R2K3K_INDEX_SHIFT;
1559 else
1560 cp->reg[COP0_INDEX] = found;
1561 }
1562
1563 /* Sign extend the index register: */
1564 if ((cp->reg[COP0_INDEX] >> 32) == 0 &&
1565 cp->reg[COP0_INDEX] & 0x80000000)
1566 cp->reg[COP0_INDEX] |=
1567 0xffffffff00000000ULL;
1568 }
1569
1570
1571 /*
1572 * coproc_tlbwri():
1573 *
1574 * MIPS TLB write random (tlbwr) and write indexed (tlbwi) instructions.
1575 */
1576 void coproc_tlbwri(struct cpu *cpu, int randomflag)
1577 {
1578 struct mips_coproc *cp = cpu->cd.mips.coproc[0];
1579 int index, g_bit;
1580 uint64_t oldvaddr;
1581
1582 if (randomflag) {
1583 if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1584 index = ((cp->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
1585 >> R2K3K_RANDOM_SHIFT) - 1;
1586 /* R3000 always has 8 wired entries: */
1587 if (index < 8)
1588 index = cp->nr_of_tlbs - 1;
1589 cp->reg[COP0_RANDOM] = index << R2K3K_RANDOM_SHIFT;
1590 } else {
1591 cp->reg[COP0_RANDOM] = cp->reg[COP0_WIRED] + (random()
1592 % (cp->nr_of_tlbs - cp->reg[COP0_WIRED]));
1593 index = cp->reg[COP0_RANDOM] & RANDOM_MASK;
1594 }
1595 } else {
1596 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1597 index = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
1598 >> R2K3K_INDEX_SHIFT;
1599 else
1600 index = cp->reg[COP0_INDEX] & INDEX_MASK;
1601 }
1602
1603 if (index >= cp->nr_of_tlbs) {
1604 fatal("warning: tlb index %i too high (max is %i)\n",
1605 index, cp->nr_of_tlbs - 1);
1606 /* TODO: cause an exception? */
1607 return;
1608 }
1609
1610
1611 #if 0
1612 /* Debug dump of the previous entry at that index: */
1613 fatal("{ old TLB entry at index %02x:", index);
1614 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1615 fatal(" hi=%08"PRIx32, (uint32_t)cp->tlbs[index].hi);
1616 fatal(" lo=%08"PRIx32, (uint32_t)cp->tlbs[index].lo0);
1617 } else {
1618 if (cpu->is_32bit) {
1619 fatal(" mask=%08"PRIx32,(uint32_t)cp->tlbs[index].mask);
1620 fatal(" hi=%08"PRIx32, (uint32_t)cp->tlbs[index].hi);
1621 fatal(" lo0=%08"PRIx32, (uint32_t)cp->tlbs[index].lo0);
1622 fatal(" lo1=%08"PRIx32, (uint32_t)cp->tlbs[index].lo1);
1623 } else {
1624 fatal(" mask=%016"PRIx64, cp->tlbs[index].mask);
1625 fatal(" hi=%016"PRIx64, cp->tlbs[index].hi);
1626 fatal(" lo0=%016"PRIx64, cp->tlbs[index].lo0);
1627 fatal(" lo1=%016"PRIx64, cp->tlbs[index].lo1);
1628 }
1629 }
1630 fatal(" }\n");
1631 #endif
1632
1633 /*
1634 * Any virtual address translation for the old TLB entry must be
1635 * invalidated first:
1636 *
1637 * (Only Valid entries need to be invalidated, and only those that
1638 * are either Global, or have the same ASID as the new entry will
1639 * have. No other address translations should be active anyway.)
1640 */
1641
1642 switch (cpu->cd.mips.cpu_type.mmu_model) {
1643
1644 case MMU3K:
1645 oldvaddr = cp->tlbs[index].hi & R2K3K_ENTRYHI_VPN_MASK;
1646 oldvaddr = (int32_t) oldvaddr;
1647
1648 if (cp->tlbs[index].lo0 & R2K3K_ENTRYLO_V &&
1649 (cp->tlbs[index].lo0 & R2K3K_ENTRYLO_G ||
1650 (cp->tlbs[index].hi & R2K3K_ENTRYHI_ASID_MASK) ==
1651 (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK) ))
1652 cpu->invalidate_translation_caches(cpu, oldvaddr,
1653 INVALIDATE_VADDR);
1654 break;
1655
1656 default:if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1657 oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;
1658 /* 44 addressable bits: */
1659 if (oldvaddr & 0x80000000000ULL)
1660 oldvaddr |= 0xfffff00000000000ULL;
1661 } else if (cpu->is_32bit) {
1662 /* MIPS32 etc.: */
1663 oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1664 oldvaddr = (int32_t)oldvaddr;
1665 } else {
1666 /* Assume MMU4K */
1667 oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1668 /* 40 addressable bits: */
1669 if (oldvaddr & 0x8000000000ULL)
1670 oldvaddr |= 0xffffff0000000000ULL;
1671 }
1672
1673 #if 0
1674 /* TODO: FIX THIS! It shouldn't be needed! */
1675 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1676 #else
1677 /*
1678 * TODO: non-4KB page sizes!
1679 */
1680 if (cp->tlbs[index].lo0 & ENTRYLO_V)
1681 cpu->invalidate_translation_caches(cpu, oldvaddr,
1682 INVALIDATE_VADDR);
1683 if (cp->tlbs[index].lo1 & ENTRYLO_V)
1684 cpu->invalidate_translation_caches(cpu, oldvaddr|0x1000,
1685 INVALIDATE_VADDR);
1686 #endif
1687 }
1688
1689 #if 0
1690 /*
1691 * Check for duplicate entries. (There should not be two mappings
1692 * from one virtual address to physical addresses.)
1693 *
1694 * TODO: Do this for MMU3K and R4100 too.
1695 *
1696 * TODO: Make this detection more robust.
1697 */
1698 if (cpu->cd.mips.cpu_type.mmu_model != MMU3K &&
1699 cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
1700 uint64_t vaddr1, vaddr2;
1701 int i;
1702 unsigned int asid;
1703
1704 vaddr1 = cp->reg[COP0_ENTRYHI] & ENTRYHI_VPN2_MASK_R10K;
1705 asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
1706 /* Since this is just a warning, it's probably not necessary
1707 to use R4000 masks etc. */
1708
1709 for (i=0; i<cp->nr_of_tlbs; i++) {
1710 if (i == index && !randomflag)
1711 continue;
1712
1713 if (!(cp->tlbs[i].hi & TLB_G) &&
1714 (cp->tlbs[i].hi & ENTRYHI_ASID) != asid)
1715 continue;
1716
1717 vaddr2 = cp->tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
1718 if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 &
1719 ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V)))
1720 fatal("\n[ WARNING! tlbw%s to index 0x%02x "
1721 "vaddr=0x%llx (asid 0x%02x) is already in"
1722 " the TLB (entry 0x%02x) ! ]\n\n",
1723 randomflag? "r" : "i", index,
1724 (long long)vaddr1, asid, i);
1725 }
1726 }
1727 #endif
1728
1729 /* Write the new entry: */
1730
1731 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1732 uint32_t vaddr, paddr;
1733 int wf = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_D? 1 : 0;
1734 unsigned char *memblock = NULL;
1735
1736 cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
1737 cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
1738
1739 vaddr = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
1740 paddr = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_PFN_MASK;
1741
1742 memblock = memory_paddr_to_hostaddr(cpu->mem, paddr, 0);
1743
1744 /* Invalidate any code translation, if we are writing
1745 a Dirty page to the TLB: */
1746 if (wf) {
1747 cpu->invalidate_code_translation(cpu, paddr,
1748 INVALIDATE_PADDR);
1749 }
1750
1751 if (cp->reg[COP0_STATUS] & MIPS1_ISOL_CACHES) {
1752 fatal("Wow! Interesting case; tlbw* while caches"
1753 " are isolated. TODO\n");
1754 /* Don't update the translation table in this
1755 case... */
1756 exit(1);
1757 }
1758
1759 /* If we have a memblock (host page) for the physical
1760 page, then add a translation for it immediately: */
1761 if (memblock != NULL &&
1762 cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_V)
1763 cpu->update_translation_table(cpu, vaddr, memblock,
1764 wf, paddr);
1765 } else {
1766 /* R4000 etc.: */
1767 unsigned char *memblock = NULL;
1768 int pfn_shift = 12, vpn_shift = 12;
1769 int wf0, wf1, mask;
1770 uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp;
1771
1772 cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];
1773 cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
1774 cp->tlbs[index].lo1 = cp->reg[COP0_ENTRYLO1];
1775 cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
1776
1777 wf0 = cp->tlbs[index].lo0 & ENTRYLO_D;
1778 wf1 = cp->tlbs[index].lo1 & ENTRYLO_D;
1779
1780 mask = cp->reg[COP0_PAGEMASK];
1781 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1782 pfn_shift = 10;
1783 mask |= 0x07ff;
1784 } else {
1785 mask |= 0x1fff;
1786 }
1787 switch (mask) {
1788 case 0x00007ff:
1789 if (cp->tlbs[index].lo0 & ENTRYLO_V ||
1790 cp->tlbs[index].lo1 & ENTRYLO_V) {
1791 fatal("1KB pages don't work with dyntrans.\n");
1792 exit(1);
1793 }
1794 vpn_shift = 10;
1795 break;
1796 case 0x0001fff: break;
1797 case 0x0007fff: vpn_shift = 14; break;
1798 case 0x001ffff: vpn_shift = 16; break;
1799 case 0x007ffff: vpn_shift = 18; break;
1800 case 0x01fffff: vpn_shift = 20; break;
1801 case 0x07fffff: vpn_shift = 22; break;
1802 case 0x1ffffff: vpn_shift = 24; break;
1803 case 0x7ffffff: vpn_shift = 26; break;
1804 default:fatal("Unimplemented MASK = 0x%016x\n", mask);
1805 exit(1);
1806 }
1807
1808 paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK)
1809 >> ENTRYLO_PFN_SHIFT) << pfn_shift;
1810 paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK)
1811 >> ENTRYLO_PFN_SHIFT) << pfn_shift;
1812
1813 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1814 vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;
1815 /* 44 addressable bits: */
1816 if (vaddr0 & 0x80000000000ULL)
1817 vaddr0 |= 0xfffff00000000000ULL;
1818 } else if (cpu->is_32bit) {
1819 /* MIPS32 etc.: */
1820 vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1821 vaddr0 = (int32_t)vaddr0;
1822 } else {
1823 /* Assume MMU4K */
1824 vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1825 /* 40 addressable bits: */
1826 if (vaddr0 & 0x8000000000ULL)
1827 vaddr0 |= 0xffffff0000000000ULL;
1828 }
1829
1830 vaddr1 = vaddr0 | (1 << vpn_shift);
1831
1832 g_bit = (cp->reg[COP0_ENTRYLO0] &
1833 cp->reg[COP0_ENTRYLO1]) & ENTRYLO_G;
1834
1835 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1836 /* NOTE: The VR4131 (and possibly others) don't have
1837 a Global bit in entryhi */
1838 cp->tlbs[index].hi &= ~cp->reg[COP0_PAGEMASK];
1839 } else {
1840 cp->tlbs[index].lo0 &= ~ENTRYLO_G;
1841 cp->tlbs[index].lo1 &= ~ENTRYLO_G;
1842
1843 cp->tlbs[index].hi &= ~TLB_G;
1844 if (g_bit)
1845 cp->tlbs[index].hi |= TLB_G;
1846 }
1847
1848 /*
1849 * Invalidate any code translations, if we are writing Dirty
1850 * pages to the TLB: (TODO: 4KB hardcoded... ugly)
1851 */
1852 for (ptmp = 0; ptmp < (1 << pfn_shift); ptmp += 0x1000) {
1853 if (wf0)
1854 cpu->invalidate_code_translation(cpu,
1855 paddr0 + ptmp, INVALIDATE_PADDR);
1856 if (wf1)
1857 cpu->invalidate_code_translation(cpu,
1858 paddr1 + ptmp, INVALIDATE_PADDR);
1859 }
1860
1861 /*
1862 * If we have a memblock (host page) for the physical page,
1863 * then add a translation for it immediately, to save some
1864 * time. (It would otherwise be added later on anyway,
1865 * because of a translation miss.)
1866 *
1867 * NOTE/TODO: This is only for 4KB pages so far. It would
1868 * be too expensive to add e.g. 16MB pages like
1869 * this.
1870 */
1871 memblock = memory_paddr_to_hostaddr(cpu->mem, paddr0, 0);
1872 if (memblock != NULL && cp->reg[COP0_ENTRYLO0] & ENTRYLO_V)
1873 cpu->update_translation_table(cpu, vaddr0, memblock,
1874 wf0, paddr0);
1875 memblock = memory_paddr_to_hostaddr(cpu->mem, paddr1, 0);
1876 if (memblock != NULL && cp->reg[COP0_ENTRYLO1] & ENTRYLO_V)
1877 cpu->update_translation_table(cpu, vaddr1, memblock,
1878 wf1, paddr1);
1879 }
1880 }
1881
1882
1883 /*
1884 * coproc_eret():
1885 *
1886 * Return from exception. (R4000 etc.)
1887 */
1888 void coproc_eret(struct cpu *cpu)
1889 {
1890 if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1891 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1892 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1893 } else {
1894 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1895 cpu->delay_slot = 0;
1896 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1897 }
1898
1899 cpu->cd.mips.rmw = 0; /* the "LL bit" */
1900 }
1901
1902
1903 /*
1904 * coproc_function():
1905 *
1906 * Execute a coprocessor specific instruction. cp must be != NULL.
1907 * Debug trace should be printed for known instructions, if
1908 * unassemble_only is non-zero. (This will NOT execute the instruction.)
1909 *
1910 * TODO: This is a mess and should be restructured (again).
1911 */
1912 void coproc_function(struct cpu *cpu, struct mips_coproc *cp, int cpnr,
1913 uint32_t function, int unassemble_only, int running)
1914 {
1915 int co_bit, op, rt, rd, fs, copz;
1916 uint64_t tmpvalue;
1917
1918 if (cp == NULL) {
1919 if (unassemble_only) {
1920 debug("cop%i\t0x%08x (coprocessor not available)\n",
1921 cpnr, (int)function);
1922 return;
1923 }
1924 fatal("[ pc=0x%016llx cop%i\t0x%08x (coprocessor not "
1925 "available)\n", (long long)cpu->pc, cpnr, (int)function);
1926 return;
1927 }
1928
1929 /* No FPU? */
1930 if (cpnr == 1 && (cpu->cd.mips.cpu_type.flags & NOFPU)) {
1931 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1932 return;
1933 }
1934
1935 /* For quick reference: */
1936 copz = (function >> 21) & 31;
1937 rt = (function >> 16) & 31;
1938 rd = (function >> 11) & 31;
1939
1940 if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21))
1941 || ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) {
1942 if (unassemble_only) {
1943 debug("%s%i\t%s,", copz==COPz_DMFCz? "dmfc" : "mfc",
1944 cpnr, regnames[rt]);
1945 if (cpnr == 0)
1946 debug("%s", cop0_names[rd]);
1947 else
1948 debug("r%i", rd);
1949 if (function & 7)
1950 debug(",%i", (int)(function & 7));
1951 debug("\n");
1952 return;
1953 }
1954 coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr],
1955 rd, &tmpvalue, function & 7);
1956 cpu->cd.mips.gpr[rt] = tmpvalue;
1957 if (copz == COPz_MFCz) {
1958 /* Sign-extend: */
1959 cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
1960 if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
1961 cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
1962 }
1963 return;
1964 }
1965
1966 if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21))
1967 || ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) {
1968 if (unassemble_only) {
1969 debug("%s%i\t%s,", copz==COPz_DMTCz? "dmtc" : "mtc",
1970 cpnr, regnames[rt]);
1971 if (cpnr == 0)
1972 debug("%s", cop0_names[rd]);
1973 else
1974 debug("r%i", rd);
1975 if (function & 7)
1976 debug(",%i", (int)(function & 7));
1977 debug("\n");
1978 return;
1979 }
1980 tmpvalue = cpu->cd.mips.gpr[rt];
1981 if (copz == COPz_MTCz) {
1982 /* Sign-extend: */
1983 tmpvalue &= 0xffffffffULL;
1984 if (tmpvalue & 0x80000000ULL)
1985 tmpvalue |= 0xffffffff00000000ULL;
1986 }
1987 coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd,
1988 &tmpvalue, copz == COPz_DMTCz, function & 7);
1989 return;
1990 }
1991
1992 if (cpnr <= 1 && (((function & 0x03e007ff) == (COPz_CFCz << 21))
1993 || ((function & 0x03e007ff) == (COPz_CTCz << 21)))) {
1994 switch (copz) {
1995 case COPz_CFCz: /* Copy from FPU control register */
1996 rt = (function >> 16) & 31;
1997 fs = (function >> 11) & 31;
1998 if (unassemble_only) {
1999 debug("cfc%i\t%s,r%i\n", cpnr,
2000 regnames[rt], fs);
2001 return;
2002 }
2003 cpu->cd.mips.gpr[rt] = (int32_t)cp->fcr[fs];
2004 /* TODO: implement delay for gpr[rt]
2005 (for MIPS I,II,III only) */
2006 return;
2007 case COPz_CTCz: /* Copy to FPU control register */
2008 rt = (function >> 16) & 31;
2009 fs = (function >> 11) & 31;
2010 if (unassemble_only) {
2011 debug("ctc%i\t%s,r%i\n", cpnr,
2012 regnames[rt], fs);
2013 return;
2014 }
2015
2016 switch (cpnr) {
2017 case 0: /* System coprocessor */
2018 fatal("[ warning: unimplemented ctc%i, "
2019 "0x%08x -> ctl reg %i ]\n", cpnr,
2020 (int)cpu->cd.mips.gpr[rt], fs);
2021 break;
2022 case 1: /* FPU */
2023 if (fs == 0)
2024 fatal("[ Attempt to write to FPU "
2025 "control register 0 (?) ]\n");
2026 else {
2027 uint64_t tmp = cpu->cd.mips.gpr[rt];
2028 cp->fcr[fs] = tmp;
2029
2030 /* TODO: writing to control register 31
2031 should cause exceptions, depending
2032 on status bits! */
2033
2034 switch (fs) {
2035 case MIPS_FPU_FCCR:
2036 cp->fcr[MIPS_FPU_FCSR] =
2037 (cp->fcr[MIPS_FPU_FCSR] &
2038 0x017fffffULL) | ((tmp & 1)
2039 << MIPS_FCSR_FCC0_SHIFT)
2040 | (((tmp & 0xfe) >> 1) <<
2041 MIPS_FCSR_FCC1_SHIFT);
2042 break;
2043 case MIPS_FPU_FCSR:
2044 cp->fcr[MIPS_FPU_FCCR] =
2045 (cp->fcr[MIPS_FPU_FCCR] &
2046 0xffffff00ULL) | ((tmp >>
2047 MIPS_FCSR_FCC0_SHIFT) & 1) |
2048 (((tmp >>
2049 MIPS_FCSR_FCC1_SHIFT)
2050 & 0x7f) << 1);
2051 break;
2052 default:
2053 ;
2054 }
2055 }
2056 break;
2057 }
2058
2059 /* TODO: implement delay for gpr[rt]
2060 (for MIPS I,II,III only) */
2061 return;
2062 default:
2063 ;
2064 }
2065 }
2066
2067 /* Math (Floating point) coprocessor calls: */
2068 if (cpnr==1) {
2069 if (fpu_function(cpu, cp, function, unassemble_only))
2070 return;
2071 }
2072
2073
2074 /* Ugly R5900 hacks: */
2075 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2076 if ((function & 0xfffff) == COP0_EI) {
2077 if (unassemble_only) {
2078 debug("ei\n");
2079 return;
2080 }
2081 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |=
2082 R5900_STATUS_EIE;
2083 return;
2084 }
2085
2086 if ((function & 0xfffff) == COP0_DI) {
2087 if (unassemble_only) {
2088 debug("di\n");
2089 return;
2090 }
2091 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &=
2092 ~R5900_STATUS_EIE;
2093 return;
2094 }
2095 }
2096
2097 co_bit = (function >> 25) & 1;
2098
2099 /* TLB operations and other things: */
2100 if (cp->coproc_nr == 0) {
2101 op = (function) & 0xff;
2102 switch (co_bit) {
2103 case 1:
2104 switch (op) {
2105 case COP0_TLBR: /* Read indexed TLB entry */
2106 if (unassemble_only) {
2107 debug("tlbr\n");
2108 return;
2109 }
2110 coproc_tlbpr(cpu, 1);
2111 return;
2112 case COP0_TLBWI: /* Write indexed */
2113 case COP0_TLBWR: /* Write random */
2114 if (unassemble_only) {
2115 if (op == COP0_TLBWI)
2116 debug("tlbwi");
2117 else
2118 debug("tlbwr");
2119 if (!running) {
2120 debug("\n");
2121 return;
2122 }
2123 debug("\tindex=%08llx",
2124 (long long)cp->reg[COP0_INDEX]);
2125 debug(", random=%08llx",
2126 (long long)cp->reg[COP0_RANDOM]);
2127 debug(", mask=%016llx",
2128 (long long)cp->reg[COP0_PAGEMASK]);
2129 debug(", hi=%016llx",
2130 (long long)cp->reg[COP0_ENTRYHI]);
2131 debug(", lo0=%016llx",
2132 (long long)cp->reg[COP0_ENTRYLO0]);
2133 debug(", lo1=%016llx\n",
2134 (long long)cp->reg[COP0_ENTRYLO1]);
2135 return;
2136 }
2137 coproc_tlbwri(cpu, op == COP0_TLBWR);
2138 return;
2139 case COP0_TLBP: /* Probe TLB for
2140 matching entry */
2141 if (unassemble_only) {
2142 debug("tlbp\n");
2143 return;
2144 }
2145 coproc_tlbpr(cpu, 0);
2146 return;
2147 case COP0_RFE: /* R2000/R3000 only:
2148 Return from Exception */
2149 if (unassemble_only) {
2150 debug("rfe\n");
2151 return;
2152 }
2153 fatal("Internal error (rfe): Should be "
2154 "implemented in dyntrans instead.\n");
2155 exit(1);
2156 case COP0_ERET: /* R4000: Return from exception */
2157 if (unassemble_only) {
2158 debug("eret\n");
2159 return;
2160 }
2161 fatal("Internal error (eret): Should be "
2162 "implemented in dyntrans instead.\n");
2163 exit(1);
2164 case COP0_DERET:
2165 if (unassemble_only) {
2166 debug("deret\n");
2167 return;
2168 }
2169 /*
2170 * According to the MIPS64 manual, deret
2171 * loads PC from the DEPC cop0 register, and
2172 * jumps there immediately. No delay slot.
2173 *
2174 * TODO: This instruction is only available
2175 * if the processor is in debug mode. (What
2176 * does that mean?) TODO: This instruction
2177 * is undefined in a delay slot.
2178 */
2179 cpu->pc = cp->reg[COP0_DEPC];
2180 cpu->delay_slot = 0;
2181 cp->reg[COP0_STATUS] &= ~STATUS_EXL;
2182 return;
2183 case COP0_STANDBY:
2184 if (unassemble_only) {
2185 debug("standby\n");
2186 return;
2187 }
2188 /* TODO: Hm. Do something here? */
2189 return;
2190 case COP0_SUSPEND:
2191 if (unassemble_only) {
2192 debug("suspend\n");
2193 return;
2194 }
2195 /* TODO: Hm. Do something here? */
2196 return;
2197 case COP0_HIBERNATE:
2198 if (unassemble_only) {
2199 debug("hibernate\n");
2200 return;
2201 }
2202 /* TODO: Hm. Do something here? */
2203 return;
2204 default:
2205 ;
2206 }
2207 default:
2208 ;
2209 }
2210 }
2211
2212 /* TODO: coprocessor R2020 on DECstation? */
2213 if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x0100ffff) {
2214 if (unassemble_only) {
2215 debug("decstation_r2020_writeback\n");
2216 return;
2217 }
2218 /* TODO */
2219 return;
2220 }
2221
2222 /* TODO: RM5200 idle (?) */
2223 if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x02000020) {
2224 if (unassemble_only) {
2225 debug("idle(?)\n"); /* TODO */
2226 return;
2227 }
2228
2229 /* Idle? TODO */
2230 return;
2231 }
2232
2233 if (unassemble_only) {
2234 debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);
2235 return;
2236 }
2237
2238 fatal("cpu%i: UNIMPLEMENTED coproc%i function %08"PRIx32" "
2239 "(pc = %016"PRIx64")\n", cpu->cpu_id, cp->coproc_nr,
2240 (uint32_t)function, cpu->pc);
2241
2242 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0);
2243 }
2244
2245 #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26