/[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 40 - (show annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 65511 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26