/[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 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 63784 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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.53 2006/08/11 17:43:30 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->is_32bit) {
540 topbit = 0x80000000;
541 fillmask = 0xffffffff00000000ULL;
542 } else if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
543 topbit <<= 43;
544 fillmask <<= 4;
545 } else {
546 topbit <<= 39;
547 }
548
549 for (i=0; i<ntlbs; i++) {
550 if (tlb[i].mask != 0 && tlb[i].mask != 0x1800) {
551 non4kpages = 1;
552 continue;
553 }
554
555 if ((tlb[i].hi & ENTRYHI_ASID) == asid &&
556 !(tlb[i].hi & TLB_G)) {
557 uint64_t vaddr0, vaddr1;
558 vaddr0 = cp->tlbs[i].hi & ~fillmask;
559 if (vaddr0 & topbit)
560 vaddr0 |= fillmask;
561 vaddr1 = vaddr0 | 0x1000; /* TODO: mask */
562
563 if (tlb[i].lo0 & ENTRYLO_V)
564 cpu->invalidate_translation_caches(cpu,
565 vaddr0, INVALIDATE_VADDR);
566 if (tlb[i].lo1 & ENTRYLO_V)
567 cpu->invalidate_translation_caches(cpu,
568 vaddr1, INVALIDATE_VADDR);
569 }
570 }
571
572 if (non4kpages) {
573 cpu->invalidate_translation_caches(cpu,
574 0, INVALIDATE_ALL);
575 }
576 }
577 }
578
579
580 /*
581 * coproc_register_read();
582 *
583 * Read a value from a MIPS coprocessor register.
584 */
585 void coproc_register_read(struct cpu *cpu,
586 struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int select)
587 {
588 int unimpl = 1;
589
590 if (cp->coproc_nr==0 && reg_nr==COP0_INDEX) unimpl = 0;
591 if (cp->coproc_nr==0 && reg_nr==COP0_RANDOM) unimpl = 0;
592 if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO0) unimpl = 0;
593 if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO1) unimpl = 0;
594 if (cp->coproc_nr==0 && reg_nr==COP0_CONTEXT) unimpl = 0;
595 if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK) unimpl = 0;
596 if (cp->coproc_nr==0 && reg_nr==COP0_WIRED) unimpl = 0;
597 if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR) unimpl = 0;
598 if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) unimpl = 0;
599 if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI) unimpl = 0;
600 if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE) unimpl = 0;
601 if (cp->coproc_nr==0 && reg_nr==COP0_STATUS) unimpl = 0;
602 if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE) unimpl = 0;
603 if (cp->coproc_nr==0 && reg_nr==COP0_EPC) unimpl = 0;
604 if (cp->coproc_nr==0 && reg_nr==COP0_PRID) unimpl = 0;
605 if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG) {
606 if (select > 0) {
607 switch (select) {
608 case 1: *ptr = cpu->cd.mips.cop0_config_select1;
609 break;
610 default:fatal("coproc_register_read(): unimplemented"
611 " config register select %i\n", select);
612 exit(1);
613 }
614 return;
615 }
616 unimpl = 0;
617 }
618 if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR) unimpl = 0;
619 if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO) unimpl = 0;
620 if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI) unimpl = 0;
621 if (cp->coproc_nr==0 && reg_nr==COP0_XCONTEXT) unimpl = 0;
622 if (cp->coproc_nr==0 && reg_nr==COP0_ERRCTL) unimpl = 0;
623 if (cp->coproc_nr==0 && reg_nr==COP0_CACHEERR) unimpl = 0;
624 if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_LO) unimpl = 0;
625 if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_HI) unimpl = 0;
626 if (cp->coproc_nr==0 && reg_nr==COP0_ERROREPC) unimpl = 0;
627 if (cp->coproc_nr==0 && reg_nr==COP0_RESERV22) {
628 /* Used by Linux on Linksys WRT54G */
629 unimpl = 0;
630 }
631 if (cp->coproc_nr==0 && reg_nr==COP0_DEBUG) unimpl = 0;
632 if (cp->coproc_nr==0 && reg_nr==COP0_PERFCNT) unimpl = 0;
633 if (cp->coproc_nr==0 && reg_nr==COP0_DESAVE) unimpl = 0;
634
635 if (cp->coproc_nr==1) unimpl = 0;
636
637 if (unimpl) {
638 fatal("cpu%i: warning: read from unimplemented coproc%i"
639 " register %i (%s)\n", cpu->cpu_id, cp->coproc_nr, reg_nr,
640 cp->coproc_nr==0? cop0_names[reg_nr] : "?");
641
642 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
643 cp->coproc_nr, 0, 0, 0);
644 return;
645 }
646
647 *ptr = cp->reg[reg_nr];
648 }
649
650
651 /*
652 * coproc_register_write();
653 *
654 * Write a value to a MIPS coprocessor register.
655 */
656 void coproc_register_write(struct cpu *cpu,
657 struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64,
658 int select)
659 {
660 int unimpl = 1;
661 int readonly = 0;
662 uint64_t tmp = *ptr;
663 uint64_t tmp2 = 0, old;
664 int inval = 0, old_asid, oldmode;
665
666 switch (cp->coproc_nr) {
667 case 0:
668 /* COPROC 0: */
669 switch (reg_nr) {
670 case COP0_INDEX:
671 case COP0_RANDOM:
672 unimpl = 0;
673 break;
674 case COP0_ENTRYLO0:
675 unimpl = 0;
676 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
677 (tmp & 0xff)!=0) {
678 /* char *symbol;
679 uint64_t offset;
680 symbol = get_symbol_name(cpu->pc, &offset);
681 fatal("YO! pc = 0x%08llx <%s> "
682 "lo=%016llx\n", (long long)
683 cpu->pc, symbol? symbol :
684 "no symbol", (long long)tmp); */
685 tmp &= (R2K3K_ENTRYLO_PFN_MASK |
686 R2K3K_ENTRYLO_N | R2K3K_ENTRYLO_D |
687 R2K3K_ENTRYLO_V | R2K3K_ENTRYLO_G);
688 } else if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
689 tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
690 ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
691 }
692 break;
693 case COP0_BADVADDR:
694 /* Hm. Irix writes to this register. (Why?) */
695 unimpl = 0;
696 break;
697 case COP0_ENTRYLO1:
698 unimpl = 0;
699 if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
700 tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
701 ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
702 }
703 break;
704 case COP0_CONTEXT:
705 old = cp->reg[COP0_CONTEXT];
706 cp->reg[COP0_CONTEXT] = tmp;
707 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
708 cp->reg[COP0_CONTEXT] &=
709 ~R2K3K_CONTEXT_BADVPN_MASK;
710 cp->reg[COP0_CONTEXT] |=
711 (old & R2K3K_CONTEXT_BADVPN_MASK);
712 } else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
713 cp->reg[COP0_CONTEXT] &=
714 ~CONTEXT_BADVPN2_MASK_R4100;
715 cp->reg[COP0_CONTEXT] |=
716 (old & CONTEXT_BADVPN2_MASK_R4100);
717 } else {
718 cp->reg[COP0_CONTEXT] &=
719 ~CONTEXT_BADVPN2_MASK;
720 cp->reg[COP0_CONTEXT] |=
721 (old & CONTEXT_BADVPN2_MASK);
722 }
723 return;
724 case COP0_PAGEMASK:
725 tmp2 = tmp >> PAGEMASK_SHIFT;
726 if (tmp2 != 0x000 &&
727 tmp2 != 0x003 &&
728 tmp2 != 0x00f &&
729 tmp2 != 0x03f &&
730 tmp2 != 0x0ff &&
731 tmp2 != 0x3ff &&
732 tmp2 != 0xfff)
733 fatal("cpu%i: trying to write an invalid"
734 " pagemask 0x%08lx to COP0_PAGEMASK\n",
735 cpu->cpu_id, (long)tmp);
736 unimpl = 0;
737 break;
738 case COP0_WIRED:
739 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
740 fatal("cpu%i: r2k/r3k wired register must "
741 "always be 8\n", cpu->cpu_id);
742 tmp = 8;
743 }
744 cp->reg[COP0_RANDOM] = cp->nr_of_tlbs-1;
745 tmp &= INDEX_MASK;
746 unimpl = 0;
747 break;
748 case COP0_COUNT:
749 if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
750 fatal("WARNING: trying to write a 64-bit value"
751 " to the COUNT register!\n");
752 tmp = (int64_t)(int32_t)tmp;
753 unimpl = 0;
754 break;
755 case COP0_COMPARE:
756 /* Clear the timer interrupt bit (bit 7): */
757 cpu->cd.mips.compare_register_set = 1;
758 mips_cpu_interrupt_ack(cpu, 7);
759 if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
760 fatal("WARNING: trying to write a 64-bit value"
761 " to the COMPARE register!\n");
762 tmp = (int64_t)(int32_t)tmp;
763 unimpl = 0;
764 break;
765 case COP0_ENTRYHI:
766 /*
767 * Translation caches must be invalidated if the
768 * ASID changes:
769 */
770 switch (cpu->cd.mips.cpu_type.mmu_model) {
771 case MMU3K:
772 old_asid = cp->reg[COP0_ENTRYHI] &
773 R2K3K_ENTRYHI_ASID_MASK;
774 if ((cp->reg[COP0_ENTRYHI] &
775 R2K3K_ENTRYHI_ASID_MASK) !=
776 (tmp & R2K3K_ENTRYHI_ASID_MASK))
777 inval = 1;
778 break;
779 default:
780 old_asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
781 if ((cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID) !=
782 (tmp & ENTRYHI_ASID))
783 inval = 1;
784 break;
785 }
786
787 if (inval)
788 invalidate_asid(cpu, old_asid);
789
790 unimpl = 0;
791 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
792 (tmp & 0x3f)!=0) {
793 /* char *symbol;
794 uint64_t offset;
795 symbol = get_symbol_name(cpu->pc,
796 &offset);
797 fatal("YO! pc = 0x%08llx <%s> "
798 "hi=%016llx\n", (long long)cpu->pc,
799 symbol? symbol :
800 "no symbol", (long long)tmp); */
801 tmp &= ~0x3f;
802 }
803 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
804 tmp &= (R2K3K_ENTRYHI_VPN_MASK |
805 R2K3K_ENTRYHI_ASID_MASK);
806 else if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
807 tmp &= (ENTRYHI_R_MASK |
808 ENTRYHI_VPN2_MASK_R10K | ENTRYHI_ASID);
809 else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
810 tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
811 0x1800 | ENTRYHI_ASID);
812 else
813 tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
814 ENTRYHI_ASID);
815 break;
816 case COP0_EPC:
817 unimpl = 0;
818 break;
819 case COP0_PRID:
820 readonly = 1;
821 break;
822 case COP0_CONFIG:
823 if (select > 0) {
824 switch (select) {
825 case 1: cpu->cd.mips.cop0_config_select1 = tmp;
826 break;
827 default:fatal("coproc_register_write(): unimpl"
828 "emented config register select "
829 "%i\n", select);
830 exit(1);
831 }
832 return;
833 }
834
835 /* fatal("COP0_CONFIG: modifying K0 bits: "
836 "0x%08x => ", cp->reg[reg_nr]); */
837 tmp = *ptr;
838 tmp &= 0x3; /* only bits 2..0 can be written */
839 cp->reg[reg_nr] &= ~(0x3); cp->reg[reg_nr] |= tmp;
840 /* fatal("0x%08x\n", cp->reg[reg_nr]); */
841 return;
842 case COP0_STATUS:
843 oldmode = cp->reg[COP0_STATUS];
844 tmp &= ~(1 << 21); /* bit 21 is read-only */
845
846 /*
847 * When isolating caches, invalidate all translations.
848 * During the isolation, a special hack in memory_rw.c
849 * prevents translation tables from being updated, so
850 * the translation caches don't have to be invalidated
851 * when switching back to normal mode.
852 */
853 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
854 (oldmode & MIPS1_ISOL_CACHES) !=
855 (tmp & MIPS1_ISOL_CACHES)) {
856 /* Invalidate everything if we are switching
857 to isolated mode: */
858 if (tmp & MIPS1_ISOL_CACHES) {
859 cpu->invalidate_translation_caches(
860 cpu, 0, INVALIDATE_ALL);
861 }
862 }
863 unimpl = 0;
864 break;
865 case COP0_CAUSE:
866 /* A write to the cause register only
867 affects IM bits 0 and 1: */
868 cp->reg[reg_nr] &= ~(0x3 << STATUS_IM_SHIFT);
869 cp->reg[reg_nr] |= (tmp & (0x3 << STATUS_IM_SHIFT));
870 return;
871 case COP0_FRAMEMASK:
872 /* TODO: R10000 */
873 unimpl = 0;
874 break;
875 case COP0_TAGDATA_LO:
876 case COP0_TAGDATA_HI:
877 /* TODO: R4300 and others? */
878 unimpl = 0;
879 break;
880 case COP0_LLADDR:
881 unimpl = 0;
882 break;
883 case COP0_WATCHLO:
884 case COP0_WATCHHI:
885 unimpl = 0;
886 break;
887 case COP0_XCONTEXT:
888 /*
889 * TODO: According to the R10000 manual, the R4400
890 * shares the PTEbase portion of the context registers
891 * (that is, xcontext and context). On R10000, they
892 * are separate registers.
893 */
894 /* debug("[ xcontext 0x%016llx ]\n", tmp); */
895 unimpl = 0;
896 break;
897
898 /* Most of these are actually TODOs: */
899 case COP0_ERROREPC:
900 case COP0_DEPC:
901 case COP0_RESERV22: /* Used by Linux on Linksys WRT54G */
902 case COP0_DESAVE:
903 case COP0_PERFCNT:
904 case COP0_ERRCTL: /* R10000 */
905 unimpl = 0;
906 break;
907 }
908 break;
909
910 case 1:
911 /* COPROC 1: */
912 unimpl = 0;
913 break;
914 }
915
916 if (unimpl) {
917 fatal("cpu%i: warning: write to unimplemented coproc%i "
918 "register %i (%s), data = 0x%016llx\n", cpu->cpu_id,
919 cp->coproc_nr, reg_nr, cp->coproc_nr==0?
920 cop0_names[reg_nr] : "?", (long long)tmp);
921
922 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
923 cp->coproc_nr, 0, 0, 0);
924 return;
925 }
926
927 if (readonly) {
928 fatal("cpu%i: warning: write to READONLY coproc%i register "
929 "%i ignored\n", cpu->cpu_id, cp->coproc_nr, reg_nr);
930 return;
931 }
932
933 cp->reg[reg_nr] = tmp;
934
935 if (!flag64)
936 cp->reg[reg_nr] = (int64_t)(int32_t)cp->reg[reg_nr];
937 }
938
939
940 /*
941 * MIPS floating-point stuff:
942 *
943 * TODO: Move this to some other file?
944 */
945 static int mips_fmt_to_ieee_fmt[32] = {
946 0, 0, 0, 0, 0, 0, 0, 0,
947 0, 0, 0, 0, 0, 0, 0, 0,
948 IEEE_FMT_S, IEEE_FMT_D, 0, 0,
949 IEEE_FMT_W, IEEE_FMT_L, /* PS (Paired Single) */ 0, 0,
950 0, 0, 0, 0, 0, 0, 0, 0 };
951
952 static char *fmtname[32] = {
953 "0", "1", "2", "3", "4", "5", "6", "7",
954 "8", "9", "10", "11", "12", "13", "14", "15",
955 "s", "d", "18", "19", "w", "l", "ps", "23",
956 "24", "25", "26", "27", "28", "29", "30", "31" };
957
958 static char *ccname[16] = {
959 "f", "un", "eq", "ueq", "olt", "ult", "ole", "ule",
960 "sf", "ngle", "seq", "ngl", "lt", "nge", "le", "ngt" };
961
962 #define FPU_OP_ADD 1
963 #define FPU_OP_SUB 2
964 #define FPU_OP_MUL 3
965 #define FPU_OP_DIV 4
966 #define FPU_OP_SQRT 5
967 #define FPU_OP_MOV 6
968 #define FPU_OP_CVT 7
969 #define FPU_OP_C 8
970 #define FPU_OP_ABS 9
971 #define FPU_OP_NEG 10
972 /* TODO: CEIL.L, CEIL.W, FLOOR.L, FLOOR.W, RECIP, ROUND.L, ROUND.W, RSQRT */
973
974
975 /*
976 * fpu_store_float_value():
977 *
978 * Stores a float value (actually a double) in fmt format.
979 */
980 static void fpu_store_float_value(struct mips_coproc *cp, int fd,
981 double nf, int fmt, int nan)
982 {
983 int ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
984 uint64_t r = ieee_store_float_value(nf, ieee_fmt, nan);
985
986 /*
987 * TODO: This is for 32-bit mode. It has to be updated later
988 * for 64-bit coprocessor functionality!
989 */
990 if (fmt == COP1_FMT_D || fmt == COP1_FMT_L) {
991 cp->reg[fd] = r & 0xffffffffULL;
992 cp->reg[(fd+1) & 31] = (r >> 32) & 0xffffffffULL;
993
994 if (cp->reg[fd] & 0x80000000ULL)
995 cp->reg[fd] |= 0xffffffff00000000ULL;
996 if (cp->reg[fd+1] & 0x80000000ULL)
997 cp->reg[fd+1] |= 0xffffffff00000000ULL;
998 } else {
999 cp->reg[fd] = r & 0xffffffffULL;
1000
1001 if (cp->reg[fd] & 0x80000000ULL)
1002 cp->reg[fd] |= 0xffffffff00000000ULL;
1003 }
1004 }
1005
1006
1007 /*
1008 * fpu_op():
1009 *
1010 * Perform a floating-point operation. For those of fs and ft that are >= 0,
1011 * those numbers are interpreted into local variables.
1012 *
1013 * Only FPU_OP_C (compare) returns anything of interest, 1 for true, 0 for
1014 * false.
1015 */
1016 static int fpu_op(struct cpu *cpu, struct mips_coproc *cp, int op, int fmt,
1017 int ft, int fs, int fd, int cond, int output_fmt)
1018 {
1019 /* Potentially two input registers, fs and ft */
1020 struct ieee_float_value float_value[2];
1021 int unordered, nan, ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1022 uint64_t fs_v = 0;
1023 double nf;
1024
1025 if (fs >= 0) {
1026 fs_v = cp->reg[fs];
1027 /* TODO: register-pair mode and plain
1028 register mode? "FR" bit? */
1029 if (fmt == COP1_FMT_D || fmt == COP1_FMT_L)
1030 fs_v = (fs_v & 0xffffffffULL) +
1031 (cp->reg[(fs + 1) & 31] << 32);
1032 ieee_interpret_float_value(fs_v, &float_value[0], ieee_fmt);
1033 }
1034 if (ft >= 0) {
1035 uint64_t v = cp->reg[ft];
1036 /* TODO: register-pair mode and
1037 plain register mode? "FR" bit? */
1038 if (fmt == COP1_FMT_D || fmt == COP1_FMT_L)
1039 v = (v & 0xffffffffULL) +
1040 (cp->reg[(ft + 1) & 31] << 32);
1041 ieee_interpret_float_value(v, &float_value[1], ieee_fmt);
1042 }
1043
1044 switch (op) {
1045 case FPU_OP_ADD:
1046 nf = float_value[0].f + float_value[1].f;
1047 /* debug(" add: %f + %f = %f\n",
1048 float_value[0].f, float_value[1].f, nf); */
1049 fpu_store_float_value(cp, fd, nf, output_fmt,
1050 float_value[0].nan || float_value[1].nan);
1051 break;
1052 case FPU_OP_SUB:
1053 nf = float_value[0].f - float_value[1].f;
1054 /* debug(" sub: %f - %f = %f\n",
1055 float_value[0].f, float_value[1].f, nf); */
1056 fpu_store_float_value(cp, fd, nf, output_fmt,
1057 float_value[0].nan || float_value[1].nan);
1058 break;
1059 case FPU_OP_MUL:
1060 nf = float_value[0].f * float_value[1].f;
1061 /* debug(" mul: %f * %f = %f\n",
1062 float_value[0].f, float_value[1].f, nf); */
1063 fpu_store_float_value(cp, fd, nf, output_fmt,
1064 float_value[0].nan || float_value[1].nan);
1065 break;
1066 case FPU_OP_DIV:
1067 nan = float_value[0].nan || float_value[1].nan;
1068 if (fabs(float_value[1].f) > 0.00000000001)
1069 nf = float_value[0].f / float_value[1].f;
1070 else {
1071 fatal("DIV by zero !!!!\n");
1072 nf = 0.0; /* TODO */
1073 nan = 1;
1074 }
1075 /* debug(" div: %f / %f = %f\n",
1076 float_value[0].f, float_value[1].f, nf); */
1077 fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1078 break;
1079 case FPU_OP_SQRT:
1080 nan = float_value[0].nan;
1081 if (float_value[0].f >= 0.0)
1082 nf = sqrt(float_value[0].f);
1083 else {
1084 fatal("SQRT by less than zero, %f !!!!\n",
1085 float_value[0].f);
1086 nf = 0.0; /* TODO */
1087 nan = 1;
1088 }
1089 /* debug(" sqrt: %f => %f\n", float_value[0].f, nf); */
1090 fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1091 break;
1092 case FPU_OP_ABS:
1093 nf = fabs(float_value[0].f);
1094 /* debug(" abs: %f => %f\n", float_value[0].f, nf); */
1095 fpu_store_float_value(cp, fd, nf, output_fmt,
1096 float_value[0].nan);
1097 break;
1098 case FPU_OP_NEG:
1099 nf = - float_value[0].f;
1100 /* debug(" neg: %f => %f\n", float_value[0].f, nf); */
1101 fpu_store_float_value(cp, fd, nf, output_fmt,
1102 float_value[0].nan);
1103 break;
1104 case FPU_OP_CVT:
1105 nf = float_value[0].f;
1106 /* debug(" mov: %f => %f\n", float_value[0].f, nf); */
1107 fpu_store_float_value(cp, fd, nf, output_fmt,
1108 float_value[0].nan);
1109 break;
1110 case FPU_OP_MOV:
1111 /* Non-arithmetic move: */
1112 /*
1113 * TODO: this is for 32-bit mode. It has to be updated later
1114 * for 64-bit coprocessor stuff.
1115 */
1116 if (output_fmt == COP1_FMT_D || output_fmt == COP1_FMT_L) {
1117 cp->reg[fd] = fs_v & 0xffffffffULL;
1118 cp->reg[(fd+1) & 31] = (fs_v >> 32) & 0xffffffffULL;
1119 if (cp->reg[fd] & 0x80000000ULL)
1120 cp->reg[fd] |= 0xffffffff00000000ULL;
1121 if (cp->reg[fd+1] & 0x80000000ULL)
1122 cp->reg[fd+1] |= 0xffffffff00000000ULL;
1123 } else {
1124 cp->reg[fd] = fs_v & 0xffffffffULL;
1125 if (cp->reg[fd] & 0x80000000ULL)
1126 cp->reg[fd] |= 0xffffffff00000000ULL;
1127 }
1128 break;
1129 case FPU_OP_C:
1130 /* debug(" c: cond=%i\n", cond); */
1131
1132 unordered = 0;
1133 if (float_value[0].nan || float_value[1].nan)
1134 unordered = 1;
1135
1136 switch (cond) {
1137 case 2: /* Equal */
1138 return (float_value[0].f == float_value[1].f);
1139 case 4: /* Ordered or Less than */
1140 return (float_value[0].f < float_value[1].f)
1141 || !unordered;
1142 case 5: /* Unordered or Less than */
1143 return (float_value[0].f < float_value[1].f)
1144 || unordered;
1145 case 6: /* Ordered or Less than or Equal */
1146 return (float_value[0].f <= float_value[1].f)
1147 || !unordered;
1148 case 7: /* Unordered or Less than or Equal */
1149 return (float_value[0].f <= float_value[1].f)
1150 || unordered;
1151 case 12:/* Less than */
1152 return (float_value[0].f < float_value[1].f);
1153 case 14:/* Less than or equal */
1154 return (float_value[0].f <= float_value[1].f);
1155
1156 /* The following are not commonly used, so I'll move these out
1157 of the if-0 on a case-by-case basis. */
1158 #if 0
1159 case 0: return 0; /* False */
1160 case 1: return 0; /* Unordered */
1161 case 3: return (float_value[0].f == float_value[1].f);
1162 /* Unordered or Equal */
1163 case 8: return 0; /* Signaling false */
1164 case 9: return 0; /* Not Greater than or Less than or Equal */
1165 case 10:return (float_value[0].f == float_value[1].f); /* Signaling Equal */
1166 case 11:return (float_value[0].f == float_value[1].f); /* Not Greater
1167 than or Less than */
1168 case 13:return !(float_value[0].f >= float_value[1].f); /* Not greater
1169 than or equal */
1170 case 15:return !(float_value[0].f > float_value[1].f); /* Not greater than */
1171 #endif
1172
1173 default:
1174 fatal("fpu_op(): unimplemented condition "
1175 "code %i. see cpu_mips_coproc.c\n", cond);
1176 }
1177 break;
1178 default:
1179 fatal("fpu_op(): unimplemented op %i\n", op);
1180 }
1181
1182 return 0;
1183 }
1184
1185
1186 /*
1187 * fpu_function():
1188 *
1189 * Returns 1 if function was implemented, 0 otherwise.
1190 * Debug trace should be printed for known instructions.
1191 */
1192 static int fpu_function(struct cpu *cpu, struct mips_coproc *cp,
1193 uint32_t function, int unassemble_only)
1194 {
1195 int fd, fs, ft, fmt, cond, cc;
1196
1197 fmt = (function >> 21) & 31;
1198 ft = (function >> 16) & 31;
1199 fs = (function >> 11) & 31;
1200 cc = (function >> 8) & 7;
1201 fd = (function >> 6) & 31;
1202 cond = (function >> 0) & 15;
1203
1204
1205 /* bc1f, bc1t, bc1fl, bc1tl: */
1206 if ((function & 0x03e00000) == 0x01000000) {
1207 int nd, tf, imm;
1208 char *instr_mnem;
1209
1210 /* cc are bits 20..18: */
1211 cc = (function >> 18) & 7;
1212 nd = (function >> 17) & 1;
1213 tf = (function >> 16) & 1;
1214 imm = function & 65535;
1215 if (imm >= 32768)
1216 imm -= 65536;
1217
1218 instr_mnem = NULL;
1219 if (nd == 0 && tf == 0) instr_mnem = "bc1f";
1220 if (nd == 0 && tf == 1) instr_mnem = "bc1t";
1221 if (nd == 1 && tf == 0) instr_mnem = "bc1fl";
1222 if (nd == 1 && tf == 1) instr_mnem = "bc1tl";
1223
1224 if (cpu->machine->instruction_trace || unassemble_only)
1225 debug("%s\t%i,0x%016llx\n", instr_mnem, cc,
1226 (long long) (cpu->pc + (imm << 2)));
1227 if (unassemble_only)
1228 return 1;
1229
1230 fatal("INTERNAL ERROR: MIPS coprocessor branches should not"
1231 " be implemented in cpu_mips_coproc.c, but in"
1232 " cpu_mips_instr.c!\n");
1233 exit(1);
1234 }
1235
1236 /* add.fmt: Floating-point add */
1237 if ((function & 0x0000003f) == 0x00000000) {
1238 if (cpu->machine->instruction_trace || unassemble_only)
1239 debug("add.%s\tr%i,r%i,r%i\n",
1240 fmtname[fmt], fd, fs, ft);
1241 if (unassemble_only)
1242 return 1;
1243
1244 fpu_op(cpu, cp, FPU_OP_ADD, fmt, ft, fs, fd, -1, fmt);
1245 return 1;
1246 }
1247
1248 /* sub.fmt: Floating-point subtract */
1249 if ((function & 0x0000003f) == 0x00000001) {
1250 if (cpu->machine->instruction_trace || unassemble_only)
1251 debug("sub.%s\tr%i,r%i,r%i\n",
1252 fmtname[fmt], fd, fs, ft);
1253 if (unassemble_only)
1254 return 1;
1255
1256 fpu_op(cpu, cp, FPU_OP_SUB, fmt, ft, fs, fd, -1, fmt);
1257 return 1;
1258 }
1259
1260 /* mul.fmt: Floating-point multiply */
1261 if ((function & 0x0000003f) == 0x00000002) {
1262 if (cpu->machine->instruction_trace || unassemble_only)
1263 debug("mul.%s\tr%i,r%i,r%i\n",
1264 fmtname[fmt], fd, fs, ft);
1265 if (unassemble_only)
1266 return 1;
1267
1268 fpu_op(cpu, cp, FPU_OP_MUL, fmt, ft, fs, fd, -1, fmt);
1269 return 1;
1270 }
1271
1272 /* div.fmt: Floating-point divide */
1273 if ((function & 0x0000003f) == 0x00000003) {
1274 if (cpu->machine->instruction_trace || unassemble_only)
1275 debug("div.%s\tr%i,r%i,r%i\n",
1276 fmtname[fmt], fd, fs, ft);
1277 if (unassemble_only)
1278 return 1;
1279
1280 fpu_op(cpu, cp, FPU_OP_DIV, fmt, ft, fs, fd, -1, fmt);
1281 return 1;
1282 }
1283
1284 /* sqrt.fmt: Floating-point square-root */
1285 if ((function & 0x001f003f) == 0x00000004) {
1286 if (cpu->machine->instruction_trace || unassemble_only)
1287 debug("sqrt.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1288 if (unassemble_only)
1289 return 1;
1290
1291 fpu_op(cpu, cp, FPU_OP_SQRT, fmt, -1, fs, fd, -1, fmt);
1292 return 1;
1293 }
1294
1295 /* abs.fmt: Floating-point absolute value */
1296 if ((function & 0x001f003f) == 0x00000005) {
1297 if (cpu->machine->instruction_trace || unassemble_only)
1298 debug("abs.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1299 if (unassemble_only)
1300 return 1;
1301
1302 fpu_op(cpu, cp, FPU_OP_ABS, fmt, -1, fs, fd, -1, fmt);
1303 return 1;
1304 }
1305
1306 /* mov.fmt: Floating-point (non-arithmetic) move */
1307 if ((function & 0x0000003f) == 0x00000006) {
1308 if (cpu->machine->instruction_trace || unassemble_only)
1309 debug("mov.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1310 if (unassemble_only)
1311 return 1;
1312
1313 fpu_op(cpu, cp, FPU_OP_MOV, fmt, -1, fs, fd, -1, fmt);
1314 return 1;
1315 }
1316
1317 /* neg.fmt: Floating-point negate */
1318 if ((function & 0x001f003f) == 0x00000007) {
1319 if (cpu->machine->instruction_trace || unassemble_only)
1320 debug("neg.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1321 if (unassemble_only)
1322 return 1;
1323
1324 fpu_op(cpu, cp, FPU_OP_NEG, fmt, -1, fs, fd, -1, fmt);
1325 return 1;
1326 }
1327
1328 /* trunc.l.fmt: Truncate */
1329 if ((function & 0x001f003f) == 0x00000009) {
1330 if (cpu->machine->instruction_trace || unassemble_only)
1331 debug("trunc.l.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1332 if (unassemble_only)
1333 return 1;
1334
1335 /* TODO: not CVT? */
1336
1337 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_L);
1338 return 1;
1339 }
1340
1341 /* trunc.w.fmt: Truncate */
1342 if ((function & 0x001f003f) == 0x0000000d) {
1343 if (cpu->machine->instruction_trace || unassemble_only)
1344 debug("trunc.w.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1345 if (unassemble_only)
1346 return 1;
1347
1348 /* TODO: not CVT? */
1349
1350 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_W);
1351 return 1;
1352 }
1353
1354 /* c.cond.fmt: Floating-point compare */
1355 if ((function & 0x000000f0) == 0x00000030) {
1356 int cond_true;
1357 int bit;
1358
1359 if (cpu->machine->instruction_trace || unassemble_only)
1360 debug("c.%s.%s\tcc%i,r%i,r%i\n", ccname[cond],
1361 fmtname[fmt], cc, fs, ft);
1362 if (unassemble_only)
1363 return 1;
1364
1365 cond_true = fpu_op(cpu, cp, FPU_OP_C, fmt,
1366 ft, fs, -1, cond, fmt);
1367
1368 /*
1369 * Both the FCCR and FCSR contain condition code bits:
1370 * FCCR: bits 7..0
1371 * FCSR: bits 31..25 and 23
1372 */
1373 cp->fcr[MIPS_FPU_FCCR] &= ~(1 << cc);
1374 if (cond_true)
1375 cp->fcr[MIPS_FPU_FCCR] |= (1 << cc);
1376
1377 if (cc == 0) {
1378 bit = 1 << MIPS_FCSR_FCC0_SHIFT;
1379 cp->fcr[MIPS_FPU_FCSR] &= ~bit;
1380 if (cond_true)
1381 cp->fcr[MIPS_FPU_FCSR] |= bit;
1382 } else {
1383 bit = 1 << (MIPS_FCSR_FCC1_SHIFT + cc-1);
1384 cp->fcr[MIPS_FPU_FCSR] &= ~bit;
1385 if (cond_true)
1386 cp->fcr[MIPS_FPU_FCSR] |= bit;
1387 }
1388
1389 return 1;
1390 }
1391
1392 /* cvt.s.fmt: Convert to single floating-point */
1393 if ((function & 0x001f003f) == 0x00000020) {
1394 if (cpu->machine->instruction_trace || unassemble_only)
1395 debug("cvt.s.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1396 if (unassemble_only)
1397 return 1;
1398
1399 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_S);
1400 return 1;
1401 }
1402
1403 /* cvt.d.fmt: Convert to double floating-point */
1404 if ((function & 0x001f003f) == 0x00000021) {
1405 if (cpu->machine->instruction_trace || unassemble_only)
1406 debug("cvt.d.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1407 if (unassemble_only)
1408 return 1;
1409
1410 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_D);
1411 return 1;
1412 }
1413
1414 /* cvt.w.fmt: Convert to word fixed-point */
1415 if ((function & 0x001f003f) == 0x00000024) {
1416 if (cpu->machine->instruction_trace || unassemble_only)
1417 debug("cvt.w.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1418 if (unassemble_only)
1419 return 1;
1420
1421 fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_W);
1422 return 1;
1423 }
1424
1425 return 0;
1426 }
1427
1428
1429 /*
1430 * coproc_tlbpr():
1431 *
1432 * 'tlbp' and 'tlbr'.
1433 */
1434 void coproc_tlbpr(struct cpu *cpu, int readflag)
1435 {
1436 struct mips_coproc *cp = cpu->cd.mips.coproc[0];
1437 int i, found, g_bit;
1438 uint64_t vpn2, xmask;
1439
1440 /* Read: */
1441 if (readflag) {
1442 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1443 i = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK) >>
1444 R2K3K_INDEX_SHIFT;
1445 if (i >= cp->nr_of_tlbs) {
1446 /* TODO: exception? */
1447 fatal("[ warning: tlbr from index %i (too "
1448 "high) ]\n", i);
1449 return;
1450 }
1451
1452 cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi;
1453 cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;
1454 } else {
1455 /* R4000: */
1456 i = cp->reg[COP0_INDEX] & INDEX_MASK;
1457 if (i >= cp->nr_of_tlbs) /* TODO: exception */
1458 return;
1459
1460 cp->reg[COP0_PAGEMASK] = cp->tlbs[i].mask;
1461 cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi;
1462 cp->reg[COP0_ENTRYLO1] = cp->tlbs[i].lo1;
1463 cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;
1464
1465 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1466 /* R4100 don't have the G bit in entryhi */
1467 } else {
1468 /* R4000 etc: */
1469 cp->reg[COP0_ENTRYHI] &= ~TLB_G;
1470 g_bit = cp->tlbs[i].hi & TLB_G;
1471
1472 cp->reg[COP0_ENTRYLO0] &= ~ENTRYLO_G;
1473 cp->reg[COP0_ENTRYLO1] &= ~ENTRYLO_G;
1474 if (g_bit) {
1475 cp->reg[COP0_ENTRYLO0] |= ENTRYLO_G;
1476 cp->reg[COP0_ENTRYLO1] |= ENTRYLO_G;
1477 }
1478 }
1479 }
1480
1481 return;
1482 }
1483
1484 /* Probe: */
1485 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1486 vpn2 = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
1487 found = -1;
1488 for (i=0; i<cp->nr_of_tlbs; i++)
1489 if ( ((cp->tlbs[i].hi & R2K3K_ENTRYHI_ASID_MASK) ==
1490 (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK))
1491 || cp->tlbs[i].lo0 & R2K3K_ENTRYLO_G)
1492 if ((cp->tlbs[i].hi & R2K3K_ENTRYHI_VPN_MASK)
1493 == vpn2) {
1494 found = i;
1495 break;
1496 }
1497 } else {
1498 /* R4000 and R10000: */
1499 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1500 xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K;
1501 else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
1502 xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800;
1503 else
1504 xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK;
1505 vpn2 = cp->reg[COP0_ENTRYHI] & xmask;
1506 found = -1;
1507 for (i=0; i<cp->nr_of_tlbs; i++) {
1508 int gbit = cp->tlbs[i].hi & TLB_G;
1509 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
1510 gbit = (cp->tlbs[i].lo0 & ENTRYLO_G) &&
1511 (cp->tlbs[i].lo1 & ENTRYLO_G);
1512
1513 if ( ((cp->tlbs[i].hi & ENTRYHI_ASID) ==
1514 (cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID)) || gbit) {
1515 uint64_t a = vpn2 & ~cp->tlbs[i].mask;
1516 uint64_t b = (cp->tlbs[i].hi & xmask) &
1517 ~cp->tlbs[i].mask;
1518 if (a == b) {
1519 found = i;
1520 break;
1521 }
1522 }
1523 }
1524 }
1525 if (found == -1)
1526 cp->reg[COP0_INDEX] = INDEX_P;
1527 else {
1528 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1529 cp->reg[COP0_INDEX] = found << R2K3K_INDEX_SHIFT;
1530 else
1531 cp->reg[COP0_INDEX] = found;
1532 }
1533
1534 /* Sign extend the index register: */
1535 if ((cp->reg[COP0_INDEX] >> 32) == 0 &&
1536 cp->reg[COP0_INDEX] & 0x80000000)
1537 cp->reg[COP0_INDEX] |=
1538 0xffffffff00000000ULL;
1539 }
1540
1541
1542 /*
1543 * coproc_tlbwri():
1544 *
1545 * MIPS TLB write random (tlbwr) and write indexed (tlbwi) instructions.
1546 */
1547 void coproc_tlbwri(struct cpu *cpu, int randomflag)
1548 {
1549 struct mips_coproc *cp = cpu->cd.mips.coproc[0];
1550 int index, g_bit;
1551 uint64_t oldvaddr;
1552
1553 if (randomflag) {
1554 if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1555 index = ((cp->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
1556 >> R2K3K_RANDOM_SHIFT) - 1;
1557 /* R3000 always has 8 wired entries: */
1558 if (index < 8)
1559 index = cp->nr_of_tlbs - 1;
1560 cp->reg[COP0_RANDOM] = index << R2K3K_RANDOM_SHIFT;
1561 } else {
1562 cp->reg[COP0_RANDOM] = cp->reg[COP0_WIRED] + (random()
1563 % (cp->nr_of_tlbs - cp->reg[COP0_WIRED]));
1564 index = cp->reg[COP0_RANDOM] & RANDOM_MASK;
1565 }
1566 } else {
1567 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1568 index = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
1569 >> R2K3K_INDEX_SHIFT;
1570 else
1571 index = cp->reg[COP0_INDEX] & INDEX_MASK;
1572 }
1573
1574 if (index >= cp->nr_of_tlbs) {
1575 fatal("warning: tlb index %i too high (max is %i)\n",
1576 index, cp->nr_of_tlbs - 1);
1577 /* TODO: cause an exception? */
1578 return;
1579 }
1580
1581
1582 #if 0
1583 /* Debug dump of the previous entry at that index: */
1584 fatal("{ old TLB entry at index %02x:", index);
1585 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1586 fatal(" hi=%08"PRIx32, (uint32_t)cp->tlbs[index].hi);
1587 fatal(" lo=%08"PRIx32, (uint32_t)cp->tlbs[index].lo0);
1588 } else {
1589 if (cpu->is_32bit) {
1590 fatal(" mask=%08"PRIx32,(uint32_t)cp->tlbs[index].mask);
1591 fatal(" hi=%08"PRIx32, (uint32_t)cp->tlbs[index].hi);
1592 fatal(" lo0=%08"PRIx32, (uint32_t)cp->tlbs[index].lo0);
1593 fatal(" lo1=%08"PRIx32, (uint32_t)cp->tlbs[index].lo1);
1594 } else {
1595 fatal(" mask=%016"PRIx64, cp->tlbs[index].mask);
1596 fatal(" hi=%016"PRIx64, cp->tlbs[index].hi);
1597 fatal(" lo0=%016"PRIx64, cp->tlbs[index].lo0);
1598 fatal(" lo1=%016"PRIx64, cp->tlbs[index].lo1);
1599 }
1600 }
1601 fatal(" }\n");
1602 #endif
1603
1604 /*
1605 * Any virtual address translation for the old TLB entry must be
1606 * invalidated first:
1607 *
1608 * (Only Valid entries need to be invalidated, and only those that
1609 * are either Global, or have the same ASID as the new entry will
1610 * have. No other address translations should be active anyway.)
1611 */
1612
1613 switch (cpu->cd.mips.cpu_type.mmu_model) {
1614
1615 case MMU3K:
1616 oldvaddr = cp->tlbs[index].hi & R2K3K_ENTRYHI_VPN_MASK;
1617 oldvaddr = (int32_t) oldvaddr;
1618
1619 if (cp->tlbs[index].lo0 & R2K3K_ENTRYLO_V &&
1620 (cp->tlbs[index].lo0 & R2K3K_ENTRYLO_G ||
1621 (cp->tlbs[index].hi & R2K3K_ENTRYHI_ASID_MASK) ==
1622 (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK) ))
1623 cpu->invalidate_translation_caches(cpu, oldvaddr,
1624 INVALIDATE_VADDR);
1625 break;
1626
1627 default:if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1628 oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;
1629 /* 44 addressable bits: */
1630 if (oldvaddr & 0x80000000000ULL)
1631 oldvaddr |= 0xfffff00000000000ULL;
1632 } else if (cpu->is_32bit) {
1633 /* MIPS32 etc.: */
1634 oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1635 oldvaddr = (int32_t)oldvaddr;
1636 } else {
1637 /* Assume MMU4K */
1638 oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1639 /* 40 addressable bits: */
1640 if (oldvaddr & 0x8000000000ULL)
1641 oldvaddr |= 0xffffff0000000000ULL;
1642 }
1643
1644 #if 0
1645 /* TODO: FIX THIS! It shouldn't be needed! */
1646 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1647 #else
1648 /*
1649 * TODO: non-4KB page sizes!
1650 */
1651 if (cp->tlbs[index].lo0 & ENTRYLO_V)
1652 cpu->invalidate_translation_caches(cpu, oldvaddr,
1653 INVALIDATE_VADDR);
1654 if (cp->tlbs[index].lo1 & ENTRYLO_V)
1655 cpu->invalidate_translation_caches(cpu, oldvaddr|0x1000,
1656 INVALIDATE_VADDR);
1657 #endif
1658 }
1659
1660 #if 0
1661 /*
1662 * Check for duplicate entries. (There should not be two mappings
1663 * from one virtual address to physical addresses.)
1664 *
1665 * TODO: Do this for MMU3K and R4100 too.
1666 *
1667 * TODO: Make this detection more robust.
1668 */
1669 if (cpu->cd.mips.cpu_type.mmu_model != MMU3K &&
1670 cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
1671 uint64_t vaddr1, vaddr2;
1672 int i;
1673 unsigned int asid;
1674
1675 vaddr1 = cp->reg[COP0_ENTRYHI] & ENTRYHI_VPN2_MASK_R10K;
1676 asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
1677 /* Since this is just a warning, it's probably not necessary
1678 to use R4000 masks etc. */
1679
1680 for (i=0; i<cp->nr_of_tlbs; i++) {
1681 if (i == index && !randomflag)
1682 continue;
1683
1684 if (!(cp->tlbs[i].hi & TLB_G) &&
1685 (cp->tlbs[i].hi & ENTRYHI_ASID) != asid)
1686 continue;
1687
1688 vaddr2 = cp->tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
1689 if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 &
1690 ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V)))
1691 fatal("\n[ WARNING! tlbw%s to index 0x%02x "
1692 "vaddr=0x%llx (asid 0x%02x) is already in"
1693 " the TLB (entry 0x%02x) ! ]\n\n",
1694 randomflag? "r" : "i", index,
1695 (long long)vaddr1, asid, i);
1696 }
1697 }
1698 #endif
1699
1700 /* Write the new entry: */
1701
1702 if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1703 uint32_t vaddr, paddr;
1704 int wf = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_D? 1 : 0;
1705 unsigned char *memblock = NULL;
1706
1707 cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
1708 cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
1709
1710 vaddr = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
1711 paddr = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_PFN_MASK;
1712
1713 memblock = memory_paddr_to_hostaddr(cpu->mem, paddr, 0);
1714
1715 /* Invalidate any code translation, if we are writing
1716 a Dirty page to the TLB: */
1717 if (wf) {
1718 cpu->invalidate_code_translation(cpu, paddr,
1719 INVALIDATE_PADDR);
1720 }
1721
1722 if (cp->reg[COP0_STATUS] & MIPS1_ISOL_CACHES) {
1723 fatal("Wow! Interesting case; tlbw* while caches"
1724 " are isolated. TODO\n");
1725 /* Don't update the translation table in this
1726 case... */
1727 exit(1);
1728 }
1729
1730 /* If we have a memblock (host page) for the physical
1731 page, then add a translation for it immediately: */
1732 if (memblock != NULL &&
1733 cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_V)
1734 cpu->update_translation_table(cpu, vaddr, memblock,
1735 wf, paddr);
1736 } else {
1737 /* R4000 etc.: */
1738 unsigned char *memblock = NULL;
1739 int pfn_shift = 12, vpn_shift = 12;
1740 int wf0, wf1, mask;
1741 uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp;
1742
1743 cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];
1744 cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
1745 cp->tlbs[index].lo1 = cp->reg[COP0_ENTRYLO1];
1746 cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
1747
1748 wf0 = cp->tlbs[index].lo0 & ENTRYLO_D;
1749 wf1 = cp->tlbs[index].lo1 & ENTRYLO_D;
1750
1751 mask = cp->reg[COP0_PAGEMASK];
1752 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1753 pfn_shift = 10;
1754 mask |= 0x07ff;
1755 } else {
1756 mask |= 0x1fff;
1757 }
1758 switch (mask) {
1759 case 0x00007ff:
1760 if (cp->tlbs[index].lo0 & ENTRYLO_V ||
1761 cp->tlbs[index].lo1 & ENTRYLO_V) {
1762 fatal("1KB pages don't work with dyntrans.\n");
1763 exit(1);
1764 }
1765 vpn_shift = 10;
1766 break;
1767 case 0x0001fff: break;
1768 case 0x0007fff: vpn_shift = 14; break;
1769 case 0x001ffff: vpn_shift = 16; break;
1770 case 0x007ffff: vpn_shift = 18; break;
1771 case 0x01fffff: vpn_shift = 20; break;
1772 case 0x07fffff: vpn_shift = 22; break;
1773 case 0x1ffffff: vpn_shift = 24; break;
1774 case 0x7ffffff: vpn_shift = 26; break;
1775 default:fatal("Unimplemented MASK = 0x%016x\n", mask);
1776 exit(1);
1777 }
1778
1779 paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK)
1780 >> ENTRYLO_PFN_SHIFT) << pfn_shift;
1781 paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK)
1782 >> ENTRYLO_PFN_SHIFT) << pfn_shift;
1783
1784 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1785 vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;
1786 /* 44 addressable bits: */
1787 if (vaddr0 & 0x80000000000ULL)
1788 vaddr0 |= 0xfffff00000000000ULL;
1789 } else if (cpu->is_32bit) {
1790 /* MIPS32 etc.: */
1791 vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1792 vaddr0 = (int32_t)vaddr0;
1793 } else {
1794 /* Assume MMU4K */
1795 vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1796 /* 40 addressable bits: */
1797 if (vaddr0 & 0x8000000000ULL)
1798 vaddr0 |= 0xffffff0000000000ULL;
1799 }
1800
1801 vaddr1 = vaddr0 | (1 << vpn_shift);
1802
1803 g_bit = (cp->reg[COP0_ENTRYLO0] &
1804 cp->reg[COP0_ENTRYLO1]) & ENTRYLO_G;
1805
1806 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1807 /* NOTE: The VR4131 (and possibly others) don't have
1808 a Global bit in entryhi */
1809 cp->tlbs[index].hi &= ~cp->reg[COP0_PAGEMASK];
1810 } else {
1811 cp->tlbs[index].lo0 &= ~ENTRYLO_G;
1812 cp->tlbs[index].lo1 &= ~ENTRYLO_G;
1813
1814 cp->tlbs[index].hi &= ~TLB_G;
1815 if (g_bit)
1816 cp->tlbs[index].hi |= TLB_G;
1817 }
1818
1819 /*
1820 * Invalidate any code translations, if we are writing Dirty
1821 * pages to the TLB: (TODO: 4KB hardcoded... ugly)
1822 */
1823 for (ptmp = 0; ptmp < (1 << pfn_shift); ptmp += 0x1000) {
1824 if (wf0)
1825 cpu->invalidate_code_translation(cpu,
1826 paddr0 + ptmp, INVALIDATE_PADDR);
1827 if (wf1)
1828 cpu->invalidate_code_translation(cpu,
1829 paddr1 + ptmp, INVALIDATE_PADDR);
1830 }
1831
1832 /*
1833 * If we have a memblock (host page) for the physical page,
1834 * then add a translation for it immediately, to save some
1835 * time. (It would otherwise be added later on anyway,
1836 * because of a translation miss.)
1837 *
1838 * NOTE/TODO: This is only for 4KB pages so far. It would
1839 * be too expensive to add e.g. 16MB pages like
1840 * this.
1841 */
1842 memblock = memory_paddr_to_hostaddr(cpu->mem, paddr0, 0);
1843 if (memblock != NULL && cp->reg[COP0_ENTRYLO0] & ENTRYLO_V)
1844 cpu->update_translation_table(cpu, vaddr0, memblock,
1845 wf0, paddr0);
1846 memblock = memory_paddr_to_hostaddr(cpu->mem, paddr1, 0);
1847 if (memblock != NULL && cp->reg[COP0_ENTRYLO1] & ENTRYLO_V)
1848 cpu->update_translation_table(cpu, vaddr1, memblock,
1849 wf1, paddr1);
1850 }
1851 }
1852
1853
1854 /*
1855 * coproc_eret():
1856 *
1857 * Return from exception. (R4000 etc.)
1858 */
1859 void coproc_eret(struct cpu *cpu)
1860 {
1861 if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1862 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1863 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1864 } else {
1865 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1866 cpu->delay_slot = 0;
1867 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1868 }
1869
1870 cpu->cd.mips.rmw = 0; /* the "LL bit" */
1871 }
1872
1873
1874 /*
1875 * coproc_function():
1876 *
1877 * Execute a coprocessor specific instruction. cp must be != NULL.
1878 * Debug trace should be printed for known instructions, if
1879 * unassemble_only is non-zero. (This will NOT execute the instruction.)
1880 *
1881 * TODO: This is a mess and should be restructured (again).
1882 */
1883 void coproc_function(struct cpu *cpu, struct mips_coproc *cp, int cpnr,
1884 uint32_t function, int unassemble_only, int running)
1885 {
1886 int co_bit, op, rt, rd, fs, copz;
1887 uint64_t tmpvalue;
1888
1889 if (cp == NULL) {
1890 if (unassemble_only) {
1891 debug("cop%i\t0x%08x (coprocessor not available)\n",
1892 cpnr, (int)function);
1893 return;
1894 }
1895 fatal("[ pc=0x%016llx cop%i\t0x%08x (coprocessor not "
1896 "available)\n", (long long)cpu->pc, cpnr, (int)function);
1897 return;
1898 }
1899
1900 /* No FPU? */
1901 if (cpnr == 1 && (cpu->cd.mips.cpu_type.flags & NOFPU)) {
1902 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1903 return;
1904 }
1905
1906 /* For quick reference: */
1907 copz = (function >> 21) & 31;
1908 rt = (function >> 16) & 31;
1909 rd = (function >> 11) & 31;
1910
1911 if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21))
1912 || ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) {
1913 if (unassemble_only) {
1914 debug("%s%i\t%s,", copz==COPz_DMFCz? "dmfc" : "mfc",
1915 cpnr, regnames[rt]);
1916 if (cpnr == 0)
1917 debug("%s", cop0_names[rd]);
1918 else
1919 debug("r%i", rd);
1920 if (function & 7)
1921 debug(",%i", (int)(function & 7));
1922 debug("\n");
1923 return;
1924 }
1925 coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr],
1926 rd, &tmpvalue, function & 7);
1927 cpu->cd.mips.gpr[rt] = tmpvalue;
1928 if (copz == COPz_MFCz) {
1929 /* Sign-extend: */
1930 cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
1931 if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
1932 cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
1933 }
1934 return;
1935 }
1936
1937 if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21))
1938 || ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) {
1939 if (unassemble_only) {
1940 debug("%s%i\t%s,", copz==COPz_DMTCz? "dmtc" : "mtc",
1941 cpnr, regnames[rt]);
1942 if (cpnr == 0)
1943 debug("%s", cop0_names[rd]);
1944 else
1945 debug("r%i", rd);
1946 if (function & 7)
1947 debug(",%i", (int)(function & 7));
1948 debug("\n");
1949 return;
1950 }
1951 tmpvalue = cpu->cd.mips.gpr[rt];
1952 if (copz == COPz_MTCz) {
1953 /* Sign-extend: */
1954 tmpvalue &= 0xffffffffULL;
1955 if (tmpvalue & 0x80000000ULL)
1956 tmpvalue |= 0xffffffff00000000ULL;
1957 }
1958 coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd,
1959 &tmpvalue, copz == COPz_DMTCz, function & 7);
1960 return;
1961 }
1962
1963 if (cpnr <= 1 && (((function & 0x03e007ff) == (COPz_CFCz << 21))
1964 || ((function & 0x03e007ff) == (COPz_CTCz << 21)))) {
1965 switch (copz) {
1966 case COPz_CFCz: /* Copy from FPU control register */
1967 rt = (function >> 16) & 31;
1968 fs = (function >> 11) & 31;
1969 if (unassemble_only) {
1970 debug("cfc%i\t%s,r%i\n", cpnr,
1971 regnames[rt], fs);
1972 return;
1973 }
1974 cpu->cd.mips.gpr[rt] = (int32_t)cp->fcr[fs];
1975 /* TODO: implement delay for gpr[rt]
1976 (for MIPS I,II,III only) */
1977 return;
1978 case COPz_CTCz: /* Copy to FPU control register */
1979 rt = (function >> 16) & 31;
1980 fs = (function >> 11) & 31;
1981 if (unassemble_only) {
1982 debug("ctc%i\t%s,r%i\n", cpnr,
1983 regnames[rt], fs);
1984 return;
1985 }
1986
1987 switch (cpnr) {
1988 case 0: /* System coprocessor */
1989 fatal("[ warning: unimplemented ctc%i, "
1990 "0x%08x -> ctl reg %i ]\n", cpnr,
1991 (int)cpu->cd.mips.gpr[rt], fs);
1992 break;
1993 case 1: /* FPU */
1994 if (fs == 0)
1995 fatal("[ Attempt to write to FPU "
1996 "control register 0 (?) ]\n");
1997 else {
1998 uint64_t tmp = cpu->cd.mips.gpr[rt];
1999 cp->fcr[fs] = tmp;
2000
2001 /* TODO: writing to control register 31
2002 should cause exceptions, depending
2003 on status bits! */
2004
2005 switch (fs) {
2006 case MIPS_FPU_FCCR:
2007 cp->fcr[MIPS_FPU_FCSR] =
2008 (cp->fcr[MIPS_FPU_FCSR] &
2009 0x017fffffULL) | ((tmp & 1)
2010 << MIPS_FCSR_FCC0_SHIFT)
2011 | (((tmp & 0xfe) >> 1) <<
2012 MIPS_FCSR_FCC1_SHIFT);
2013 break;
2014 case MIPS_FPU_FCSR:
2015 cp->fcr[MIPS_FPU_FCCR] =
2016 (cp->fcr[MIPS_FPU_FCCR] &
2017 0xffffff00ULL) | ((tmp >>
2018 MIPS_FCSR_FCC0_SHIFT) & 1) |
2019 (((tmp >>
2020 MIPS_FCSR_FCC1_SHIFT)
2021 & 0x7f) << 1);
2022 break;
2023 default:
2024 ;
2025 }
2026 }
2027 break;
2028 }
2029
2030 /* TODO: implement delay for gpr[rt]
2031 (for MIPS I,II,III only) */
2032 return;
2033 default:
2034 ;
2035 }
2036 }
2037
2038 /* Math (Floating point) coprocessor calls: */
2039 if (cpnr==1) {
2040 if (fpu_function(cpu, cp, function, unassemble_only))
2041 return;
2042 }
2043
2044
2045 /* Ugly R5900 hacks: */
2046 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2047 if ((function & 0xfffff) == COP0_EI) {
2048 if (unassemble_only) {
2049 debug("ei\n");
2050 return;
2051 }
2052 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |=
2053 R5900_STATUS_EIE;
2054 return;
2055 }
2056
2057 if ((function & 0xfffff) == COP0_DI) {
2058 if (unassemble_only) {
2059 debug("di\n");
2060 return;
2061 }
2062 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &=
2063 ~R5900_STATUS_EIE;
2064 return;
2065 }
2066 }
2067
2068 co_bit = (function >> 25) & 1;
2069
2070 /* TLB operations and other things: */
2071 if (cp->coproc_nr == 0) {
2072 if (!unassemble_only) {
2073 fatal("FATAL INTERNAL ERROR: Should be implemented"
2074 " with dyntrans instead.\n");
2075 exit(1);
2076 }
2077
2078 op = (function) & 0xff;
2079 switch (co_bit) {
2080 case 1:
2081 switch (op) {
2082 case COP0_TLBR: /* Read indexed TLB entry */
2083 debug("tlbr\n");
2084 return;
2085 case COP0_TLBWI: /* Write indexed */
2086 case COP0_TLBWR: /* Write random */
2087 if (op == COP0_TLBWI)
2088 debug("tlbwi");
2089 else
2090 debug("tlbwr");
2091 if (!running) {
2092 debug("\n");
2093 return;
2094 }
2095 debug("\tindex=%08llx",
2096 (long long)cp->reg[COP0_INDEX]);
2097 debug(", random=%08llx",
2098 (long long)cp->reg[COP0_RANDOM]);
2099 debug(", mask=%016llx",
2100 (long long)cp->reg[COP0_PAGEMASK]);
2101 debug(", hi=%016llx",
2102 (long long)cp->reg[COP0_ENTRYHI]);
2103 debug(", lo0=%016llx",
2104 (long long)cp->reg[COP0_ENTRYLO0]);
2105 debug(", lo1=%016llx\n",
2106 (long long)cp->reg[COP0_ENTRYLO1]);
2107 return;
2108 case COP0_TLBP: /* Probe TLB for
2109 matching entry */
2110 debug("tlbp\n");
2111 return;
2112 case COP0_RFE: /* R2000/R3000 only:
2113 Return from Exception */
2114 debug("rfe\n");
2115 return;
2116 case COP0_ERET: /* R4000: Return from exception */
2117 debug("eret\n");
2118 return;
2119 case COP0_DERET:
2120 debug("deret\n");
2121 return;
2122 case COP0_WAIT:
2123 {
2124 int code = (function >> 6) & 0x7ffff;
2125 debug("wait");
2126 if (code > 0)
2127 debug("\t0x%x", code);
2128 debug("\n");
2129 }
2130 return;
2131 case COP0_STANDBY:
2132 debug("standby\n");
2133 return;
2134 case COP0_SUSPEND:
2135 debug("suspend\n");
2136 return;
2137 case COP0_HIBERNATE:
2138 debug("hibernate\n");
2139 return;
2140 default:
2141 ;
2142 }
2143 default:
2144 ;
2145 }
2146 }
2147
2148 /* TODO: coprocessor R2020 on DECstation? */
2149 if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x0100ffff) {
2150 if (unassemble_only) {
2151 debug("decstation_r2020_writeback\n");
2152 return;
2153 }
2154 /* TODO */
2155 return;
2156 }
2157
2158 if (unassemble_only) {
2159 debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);
2160 return;
2161 }
2162
2163 fatal("cpu%i: UNIMPLEMENTED coproc%i function %08"PRIx32" "
2164 "(pc = %016"PRIx64")\n", cpu->cpu_id, cp->coproc_nr,
2165 (uint32_t)function, cpu->pc);
2166
2167 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0);
2168 }
2169
2170 #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26