/[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

Annotation of /trunk/src/cpus/cpu_mips_coproc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (hide annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 76719 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


1 dpavlin 14 /*
2     * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 22 * $Id: cpu_mips_coproc.c,v 1.10 2005/12/26 12:32:10 debug Exp $
29 dpavlin 14 *
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 "bintrans.h"
39     #include "cop0.h"
40     #include "cpu.h"
41     #include "cpu_mips.h"
42     #include "emul.h"
43 dpavlin 20 #include "float_emul.h"
44 dpavlin 14 #include "machine.h"
45     #include "memory.h"
46     #include "mips_cpu_types.h"
47     #include "misc.h"
48     #include "opcodes_mips.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     /* FPU control registers: */
73     #define FPU_FCIR 0
74     #define FPU_FCCR 25
75     #define FPU_FCSR 31
76     #define FCSR_FCC0_SHIFT 23
77     #define FCSR_FCC1_SHIFT 25
78    
79    
80     /*
81     * initialize_cop0_config():
82     *
83     * Helper function, called from mips_coproc_new().
84     */
85     static void initialize_cop0_config(struct cpu *cpu, struct mips_coproc *c)
86     {
87     #ifdef ENABLE_MIPS16
88     const int m16 = 1;
89     #else
90     const int m16 = 0;
91     #endif
92     int cpu_type, IB, DB, SB, IC, DC, SC, IA, DA;
93    
94     /* Default values: */
95     c->reg[COP0_CONFIG] =
96     ( 0 << 31) /* config1 present */
97 dpavlin 18 | (0x00 << 16) /* implementation dependent */
98 dpavlin 14 | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
99     /* endian mode */
100     | ( 2 << 13) /* 0 = MIPS32,
101     1 = MIPS64 with 32-bit segments,
102     2 = MIPS64 with all segments,
103     3 = reserved */
104     | ( 0 << 10) /* architecture revision level,
105     0 = "Revision 1", other
106     values are reserved */
107     | ( 1 << 7) /* MMU type: 0 = none,
108     1 = Standard TLB,
109     2 = Standard BAT,
110     3 = fixed mapping, 4-7=reserved */
111     | ( 0 << 0) /* kseg0 coherency algorithm
112     (TODO) */
113     ;
114    
115     cpu_type = cpu->cd.mips.cpu_type.rev & 0xff;
116    
117     /* AU1x00 are treated as 4Kc (MIPS32 cores): */
118     if ((cpu->cd.mips.cpu_type.rev & 0xffff) == 0x0301)
119     cpu_type = MIPS_4Kc;
120    
121     switch (cpu_type) {
122     case MIPS_R4000: /* according to the R4000 manual */
123     case MIPS_R4600:
124     IB = cpu->machine->cache_picache_linesize - 4;
125     IB = IB < 0? 0 : (IB > 1? 1 : IB);
126     DB = cpu->machine->cache_pdcache_linesize - 4;
127     DB = DB < 0? 0 : (DB > 1? 1 : DB);
128     SB = cpu->machine->cache_secondary_linesize - 4;
129     SB = SB < 0? 0 : (SB > 3? 3 : SB);
130     IC = cpu->machine->cache_picache - 12;
131     IC = IC < 0? 0 : (IC > 7? 7 : IC);
132     DC = cpu->machine->cache_pdcache - 12;
133     DC = DC < 0? 0 : (DC > 7? 7 : DC);
134     SC = cpu->machine->cache_secondary? 0 : 1;
135     c->reg[COP0_CONFIG] =
136     ( 0 << 31) /* Master/Checker present bit */
137     | (0x00 << 28) /* EC: system clock divisor,
138     0x00 = '2' */
139     | (0x00 << 24) /* EP */
140     | ( SB << 22) /* SB */
141     | (0x00 << 21) /* SS: 0 = mixed i/d scache */
142     | (0x00 << 20) /* SW */
143     | (0x00 << 18) /* EW: 0=64-bit */
144     | ( SC << 17) /* SC: 0=secondary cache present,
145     1=non-present */
146     | (0x00 << 16) /* SM: (todo) */
147     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
148     /* endian mode */
149     | (0x01 << 14) /* ECC: 0=enabled, 1=disabled */
150     | (0x00 << 13) /* EB: (todo) */
151     | (0x00 << 12) /* 0 (resered) */
152     | ( IC << 9) /* IC: I-cache = 2^(12+IC) bytes
153     (1 = 8KB, 4=64K) */
154     | ( DC << 6) /* DC: D-cache = 2^(12+DC) bytes
155     (1 = 8KB, 4=64K) */
156     | ( IB << 5) /* IB: I-cache line size (0=16,
157     1=32) */
158     | ( DB << 4) /* DB: D-cache line size (0=16,
159     1=32) */
160     | ( 0 << 3) /* CU: todo */
161     | ( 0 << 0) /* kseg0 coherency algorithm
162     (TODO) */
163     ;
164     break;
165     case MIPS_R4100: /* According to the VR4131 manual: */
166     IB = cpu->machine->cache_picache_linesize - 4;
167     IB = IB < 0? 0 : (IB > 1? 1 : IB);
168     DB = cpu->machine->cache_pdcache_linesize - 4;
169     DB = DB < 0? 0 : (DB > 1? 1 : DB);
170     IC = cpu->machine->cache_picache - 10;
171     IC = IC < 0? 0 : (IC > 7? 7 : IC);
172     DC = cpu->machine->cache_pdcache - 10;
173     DC = DC < 0? 0 : (DC > 7? 7 : DC);
174     c->reg[COP0_CONFIG] =
175     ( 0 << 31) /* IS: Instruction Streaming bit */
176     | (0x01 << 28) /* EC: system clock divisor,
177     0x01 = 2 */
178     | (0x00 << 24) /* EP */
179     | (0x00 << 23) /* AD: Accelerate data mode
180     (0=VR4000-compatible) */
181     | ( m16 << 20) /* M16: MIPS16 support */
182     | ( 1 << 17) /* '1' */
183     | (0x00 << 16) /* BP: 'Branch forecast'
184     (0 = enabled) */
185     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
186     /* endian mode */
187     | ( 2 << 13) /* '2' hardcoded on VR4131 */
188     | ( 1 << 12) /* CS: Cache size mode
189     (1 on VR4131) */
190     | ( IC << 9) /* IC: I-cache = 2^(10+IC) bytes
191     (0 = 1KB, 4=16K) */
192     | ( DC << 6) /* DC: D-cache = 2^(10+DC) bytes
193     (0 = 1KB, 4=16K) */
194     | ( IB << 5) /* IB: I-cache line size (0=16,
195     1=32) */
196     | ( DB << 4) /* DB: D-cache line size (0=16,
197     1=32) */
198     | ( 0 << 0) /* kseg0 coherency algorithm (TODO) */
199     ;
200     break;
201     case MIPS_R5000:
202     case MIPS_RM5200: /* rm5200 is just a wild guess */
203     /* These are just guesses: (the comments are wrong) */
204     c->reg[COP0_CONFIG] =
205     ( 0 << 31) /* Master/Checker present bit */
206     | (0x00 << 28) /* EC: system clock divisor,
207     0x00 = '2' */
208     | (0x00 << 24) /* EP */
209     | (0x00 << 22) /* SB */
210     | (0x00 << 21) /* SS */
211     | (0x00 << 20) /* SW */
212     | (0x00 << 18) /* EW: 0=64-bit */
213     | (0x01 << 17) /* SC: 0=secondary cache present,
214     1=non-present */
215     | (0x00 << 16) /* SM: (todo) */
216     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
217     /* endian mode */
218     | (0x01 << 14) /* ECC: 0=enabled, 1=disabled */
219     | (0x00 << 13) /* EB: (todo) */
220     | (0x00 << 12) /* 0 (resered) */
221     | ( 3 << 9) /* IC: I-cache = 2^(12+IC) bytes
222     (1 = 8KB, 4=64K) */
223     | ( 3 << 6) /* DC: D-cache = 2^(12+DC) bytes
224     (1 = 8KB, 4=64K) */
225     | ( 1 << 5) /* IB: I-cache line size (0=16,
226     1=32) */
227     | ( 1 << 4) /* DB: D-cache line size (0=16,
228     1=32) */
229     | ( 0 << 3) /* CU: todo */
230     | ( 2 << 0) /* kseg0 coherency algorithm
231     (TODO) */
232     ;
233     break;
234     case MIPS_R10000:
235     case MIPS_R12000:
236     case MIPS_R14000:
237     IC = cpu->machine->cache_picache - 12;
238     IC = IC < 0? 0 : (IC > 7? 7 : IC);
239     DC = cpu->machine->cache_pdcache - 12;
240     DC = DC < 0? 0 : (DC > 7? 7 : DC);
241     SC = cpu->machine->cache_secondary - 19;
242     SC = SC < 0? 0 : (SC > 7? 7 : SC);
243     /* According to the R10000 User's Manual: */
244     c->reg[COP0_CONFIG] =
245     ( IC << 29) /* Primary instruction cache size
246     (3 = 32KB) */
247     | ( DC << 26) /* Primary data cache size (3 =
248     32KB) */
249     | ( 0 << 19) /* SCClkDiv */
250     | ( SC << 16) /* SCSize, secondary cache size.
251     0 = 512KB. powers of two */
252     | ( 0 << 15) /* MemEnd */
253     | ( 0 << 14) /* SCCorEn */
254     | ( 1 << 13) /* SCBlkSize. 0=16 words,
255     1=32 words */
256     | ( 0 << 9) /* SysClkDiv */
257     | ( 0 << 7) /* PrcReqMax */
258     | ( 0 << 6) /* PrcElmReq */
259     | ( 0 << 5) /* CohPrcReqTar */
260     | ( 0 << 3) /* Device number */
261     | ( 2 << 0) /* Cache coherency algorithm for
262     kseg0 */
263     ;
264     break;
265     case MIPS_R5900:
266     /*
267     * R5900 is supposed to have the following (according
268     * to NetBSD/playstation2):
269     * cpu0: 16KB/64B 2-way set-associative L1 Instruction
270     * cache, 48 TLB entries
271     * cpu0: 8KB/64B 2-way set-associative write-back L1
272     * Data cache
273     * The following settings are just guesses:
274     * (comments are incorrect)
275     */
276     c->reg[COP0_CONFIG] =
277     ( 0 << 31) /* Master/Checker present bit */
278     | (0x00 << 28) /* EC: system clock divisor,
279     0x00 = '2' */
280     | (0x00 << 24) /* EP */
281     | (0x00 << 22) /* SB */
282     | (0x00 << 21) /* SS */
283     | (0x00 << 20) /* SW */
284     | (0x00 << 18) /* EW: 0=64-bit */
285     | (0x01 << 17) /* SC: 0=secondary cache present,
286     1=non-present */
287     | (0x00 << 16) /* SM: (todo) */
288     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
289     /* endian mode */
290     | (0x01 << 14) /* ECC: 0=enabled, 1=disabled */
291     | (0x00 << 13) /* EB: (todo) */
292     | (0x00 << 12) /* 0 (resered) */
293     | ( 3 << 9) /* IC: I-cache = 2^(12+IC) bytes
294     (1 = 8KB, 4=64K) */
295     | ( 3 << 6) /* DC: D-cache = 2^(12+DC) bytes
296     (1 = 8KB, 4=64K) */
297     | ( 1 << 5) /* IB: I-cache line size (0=16,
298     1=32) */
299     | ( 1 << 4) /* DB: D-cache line size (0=16,
300     1=32) */
301     | ( 0 << 3) /* CU: todo */
302     | ( 0 << 0) /* kseg0 coherency algorithm
303     (TODO) */
304     ;
305     break;
306     case MIPS_4Kc:
307     case MIPS_5Kc:
308     /* According to the MIPS64 (5K) User's Manual: */
309     c->reg[COP0_CONFIG] =
310     ( (uint32_t)1 << 31)/* Config 1 present bit */
311     | ( 0 << 20) /* ISD: instruction scheduling
312     disable (=1) */
313     | ( 0 << 17) /* DID: dual issue disable */
314     | ( 0 << 16) /* BM: burst mode */
315     | ((cpu->byte_order == EMUL_BIG_ENDIAN? 1 : 0) << 15)
316     /* endian mode */
317     | ((cpu_type == MIPS_5Kc? 2 : 0) << 13)
318     /* 0=MIPS32, 1=64S, 2=64 */
319     | ( 0 << 10) /* Architecture revision */
320     | ( 1 << 7) /* MMU type: 1=TLB, 3=FMT */
321     | ( 2 << 0) /* kseg0 cache coherency algorithm */
322     ;
323     /* Config select 1: caches etc. TODO: Don't use
324     cpu->machine for this stuff! */
325     IB = cpu->machine->cache_picache_linesize - 1;
326     IB = IB < 0? 0 : (IB > 7? 7 : IB);
327     DB = cpu->machine->cache_pdcache_linesize - 1;
328     DB = DB < 0? 0 : (DB > 7? 7 : DB);
329     IC = cpu->machine->cache_picache -
330     cpu->machine->cache_picache_linesize - 7;
331     DC = cpu->machine->cache_pdcache -
332     cpu->machine->cache_pdcache_linesize - 7;
333     IA = cpu->cd.mips.cpu_type.piways - 1;
334     DA = cpu->cd.mips.cpu_type.pdways - 1;
335     cpu->cd.mips.cop0_config_select1 =
336     ((cpu->cd.mips.cpu_type.nr_of_tlb_entries - 1) << 25)
337     | (IC << 22) /* IS: I-cache sets per way */
338     | (IB << 19) /* IL: I-cache line-size */
339     | (IA << 16) /* IA: I-cache assoc. (ways-1) */
340     | (DC << 13) /* DS: D-cache sets per way */
341     | (DB << 10) /* DL: D-cache line-size */
342     | (DA << 7) /* DA: D-cache assoc. (ways-1) */
343     | (16 * 0) /* Existance of PerformanceCounters */
344     | ( 8 * 0) /* Existance of Watch Registers */
345     | ( 4 * m16) /* Existance of MIPS16 */
346     | ( 2 * 0) /* Existance of EJTAG */
347     | ( 1 * 1) /* Existance of FPU */
348     ;
349     break;
350     default:
351     ;
352     }
353     }
354    
355    
356     /*
357     * initialize_cop1():
358     *
359     * Helper function, called from mips_coproc_new().
360     */
361     static void initialize_cop1(struct cpu *cpu, struct mips_coproc *c)
362     {
363     int fpu_rev;
364     uint64_t other_stuff = 0;
365    
366     switch (cpu->cd.mips.cpu_type.rev & 0xff) {
367     case MIPS_R2000: fpu_rev = MIPS_R2010; break;
368     case MIPS_R3000: fpu_rev = MIPS_R3010;
369     other_stuff |= 0x40; /* or 0x30? TODO */
370     break;
371     case MIPS_R6000: fpu_rev = MIPS_R6010; break;
372     case MIPS_R4000: fpu_rev = MIPS_R4010; break;
373     case MIPS_4Kc: /* TODO: Is this the same as 5Kc? */
374     case MIPS_5Kc: other_stuff = COP1_REVISION_DOUBLE
375     | COP1_REVISION_SINGLE;
376     case MIPS_R5000:
377     case MIPS_RM5200: fpu_rev = cpu->cd.mips.cpu_type.rev;
378     other_stuff |= 0x10;
379     /* or cpu->cd.mips.cpu_type.sub ? TODO */
380     break;
381     case MIPS_R10000: fpu_rev = MIPS_R10000; break;
382     case MIPS_R12000: fpu_rev = 0x9; break;
383     default: fpu_rev = MIPS_SOFT;
384     }
385    
386     c->fcr[COP1_REVISION] = (fpu_rev << 8) | other_stuff;
387    
388     #if 0
389     /* These are mentioned in the MIPS64 documentation: */
390     + (1 << 16) /* single */
391     + (1 << 17) /* double */
392     + (1 << 18) /* paired-single */
393     + (1 << 19) /* 3d */
394     #endif
395     }
396    
397    
398     /*
399     * mips_coproc_new():
400     *
401     * Create a new MIPS coprocessor object.
402     */
403     struct mips_coproc *mips_coproc_new(struct cpu *cpu, int coproc_nr)
404     {
405     struct mips_coproc *c;
406    
407     c = malloc(sizeof(struct mips_coproc));
408     if (c == NULL) {
409     fprintf(stderr, "out of memory\n");
410     exit(1);
411     }
412    
413     memset(c, 0, sizeof(struct mips_coproc));
414     c->coproc_nr = coproc_nr;
415    
416     if (coproc_nr == 0) {
417     c->nr_of_tlbs = cpu->cd.mips.cpu_type.nr_of_tlb_entries;
418 dpavlin 20 c->tlbs = zeroed_alloc(c->nr_of_tlbs * sizeof(struct mips_tlb));
419 dpavlin 14
420     /*
421     * Start with nothing in the status register. This makes sure
422     * that we are running in kernel mode with all interrupts
423     * disabled.
424     */
425     c->reg[COP0_STATUS] = 0;
426    
427     /* For userland emulation, enable all four coprocessors: */
428     if (cpu->machine->userland_emul)
429     c->reg[COP0_STATUS] |=
430     ((uint32_t)0xf << STATUS_CU_SHIFT);
431    
432     /* Hm. Enable coprocessors 0 and 1 even if we're not just
433     emulating userland? TODO: Think about this. */
434     /* if (cpu->machine->prom_emulation) */
435     c->reg[COP0_STATUS] |=
436     ((uint32_t)0x3 << STATUS_CU_SHIFT);
437    
438     if (!cpu->machine->prom_emulation)
439     c->reg[COP0_STATUS] |= STATUS_BEV;
440    
441     /* Default pagesize = 4 KB. */
442     c->reg[COP0_PAGEMASK] = 0x1fff;
443    
444     /* Note: .rev may contain the company ID as well! */
445     c->reg[COP0_PRID] =
446     (0x00 << 24) /* Company Options */
447     | (0x00 << 16) /* Company ID */
448     | (cpu->cd.mips.cpu_type.rev << 8) /* Processor ID */
449     | (cpu->cd.mips.cpu_type.sub) /* Revision */
450     ;
451    
452     c->reg[COP0_WIRED] = 0;
453    
454     initialize_cop0_config(cpu, c);
455    
456     /* Make sure the status register is sign-extended nicely: */
457     c->reg[COP0_STATUS] = (int64_t)(int32_t)c->reg[COP0_STATUS];
458     }
459    
460     if (coproc_nr == 1)
461     initialize_cop1(cpu, c);
462    
463     return c;
464     }
465    
466    
467     /*
468     * mips_coproc_tlb_set_entry():
469     *
470     * Used by machine setup code, if a specific machine emulation starts up
471     * with hardcoded virtual to physical mappings.
472     */
473     void mips_coproc_tlb_set_entry(struct cpu *cpu, int entrynr, int size,
474     uint64_t vaddr, uint64_t paddr0, uint64_t paddr1,
475     int valid0, int valid1, int dirty0, int dirty1, int global, int asid,
476     int cachealgo0, int cachealgo1)
477     {
478     if (entrynr < 0 || entrynr >= cpu->cd.mips.coproc[0]->nr_of_tlbs) {
479     printf("mips_coproc_tlb_set_entry(): invalid entry nr: %i\n",
480     entrynr);
481     exit(1);
482     }
483    
484     switch (cpu->cd.mips.cpu_type.mmu_model) {
485     case MMU3K:
486     if (size != 4096) {
487     printf("mips_coproc_tlb_set_entry(): invalid pagesize "
488     "(%i) for MMU3K\n", size);
489     exit(1);
490     }
491     cpu->cd.mips.coproc[0]->tlbs[entrynr].hi =
492     (vaddr & R2K3K_ENTRYHI_VPN_MASK) |
493     ((asid << R2K3K_ENTRYHI_ASID_SHIFT) &
494     R2K3K_ENTRYHI_ASID_MASK);
495     cpu->cd.mips.coproc[0]->tlbs[entrynr].lo0 =
496     (paddr0 & R2K3K_ENTRYLO_PFN_MASK) |
497     (cachealgo0? R2K3K_ENTRYLO_N : 0) |
498     (dirty0? R2K3K_ENTRYLO_D : 0) |
499     (valid0? R2K3K_ENTRYLO_V : 0) |
500     (global? R2K3K_ENTRYLO_G : 0);
501     break;
502     default:
503     /* MMU4K and MMU10K, etc: */
504     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
505     cpu->cd.mips.coproc[0]->tlbs[entrynr].hi =
506     (vaddr & ENTRYHI_VPN2_MASK_R10K) |
507     (vaddr & ENTRYHI_R_MASK) |
508     (asid & ENTRYHI_ASID) |
509     (global? TLB_G : 0);
510     else
511     cpu->cd.mips.coproc[0]->tlbs[entrynr].hi =
512     (vaddr & ENTRYHI_VPN2_MASK) |
513     (vaddr & ENTRYHI_R_MASK) |
514     (asid & ENTRYHI_ASID) |
515     (global? TLB_G : 0);
516     /* NOTE: The pagemask size is for a "dual" page: */
517     cpu->cd.mips.coproc[0]->tlbs[entrynr].mask =
518     (2*size - 1) & ~0x1fff;
519     cpu->cd.mips.coproc[0]->tlbs[entrynr].lo0 =
520     (((paddr0 >> 12) << ENTRYLO_PFN_SHIFT) &
521     ENTRYLO_PFN_MASK) |
522     (dirty0? ENTRYLO_D : 0) |
523     (valid0? ENTRYLO_V : 0) |
524     (global? ENTRYLO_G : 0) |
525     ((cachealgo0 << ENTRYLO_C_SHIFT) & ENTRYLO_C_MASK);
526     cpu->cd.mips.coproc[0]->tlbs[entrynr].lo1 =
527     (((paddr1 >> 12) << ENTRYLO_PFN_SHIFT) &
528     ENTRYLO_PFN_MASK) |
529     (dirty1? ENTRYLO_D : 0) |
530     (valid1? ENTRYLO_V : 0) |
531     (global? ENTRYLO_G : 0) |
532     ((cachealgo1 << ENTRYLO_C_SHIFT) & ENTRYLO_C_MASK);
533     /* TODO: R4100, 1KB pages etc */
534     }
535     }
536    
537    
538     /*
539     * old_update_translation_table():
540     */
541     static void old_update_translation_table(struct cpu *cpu, uint64_t vaddr_page,
542     unsigned char *host_page, int writeflag, uint64_t paddr_page)
543     {
544     int a, b, index;
545     struct vth32_table *tbl1;
546     void *p_r, *p_w;
547     uint32_t p_paddr;
548    
549     /* This table stuff only works for 32-bit mode: */
550     if (vaddr_page & 0x80000000ULL) {
551     if ((vaddr_page >> 32) != 0xffffffffULL)
552     return;
553     } else {
554     if ((vaddr_page >> 32) != 0)
555     return;
556     }
557    
558     a = (vaddr_page >> 22) & 0x3ff;
559     b = (vaddr_page >> 12) & 0x3ff;
560     index = (vaddr_page >> 12) & 0xfffff;
561    
562     /* printf("vaddr = %08x, a = %03x, b = %03x\n",
563     (int)vaddr_page,a, b); */
564    
565     tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];
566     /* printf("tbl1 = %p\n", tbl1); */
567     if (tbl1 == cpu->cd.mips.vaddr_to_hostaddr_nulltable) {
568     /* Allocate a new table1: */
569     /* printf("ALLOCATING a new table1, 0x%08x - "
570     "0x%08x\n", a << 22, (a << 22) + 0x3fffff); */
571     if (cpu->cd.mips.next_free_vth_table == NULL) {
572     tbl1 = malloc(sizeof(struct vth32_table));
573     if (tbl1 == NULL) {
574     fprintf(stderr, "out of mem\n");
575     exit(1);
576     }
577     memset(tbl1, 0, sizeof(struct vth32_table));
578     } else {
579     tbl1 = cpu->cd.mips.next_free_vth_table;
580     cpu->cd.mips.next_free_vth_table = tbl1->next_free;
581     tbl1->next_free = NULL;
582     }
583     cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a] = tbl1;
584     if (tbl1->refcount != 0) {
585     printf("INTERNAL ERROR in coproc.c\n");
586     exit(1);
587     }
588     }
589     p_r = tbl1->haddr_entry[b*2];
590     p_w = tbl1->haddr_entry[b*2+1];
591     p_paddr = tbl1->paddr_entry[b];
592     /* printf(" p_r=%p p_w=%p\n", p_r, p_w); */
593     if (p_r == NULL && p_paddr == 0 &&
594     (host_page != NULL || paddr_page != 0)) {
595     tbl1->refcount ++;
596     /* printf("ADDING %08x -> %p wf=%i (refcount is "
597     "now %i)\n", (int)vaddr_page, host_page,
598     writeflag, tbl1->refcount); */
599     }
600     if (writeflag == -1) {
601     /* Forced downgrade to read-only: */
602     tbl1->haddr_entry[b*2 + 1] = NULL;
603 dpavlin 22 if (cpu->cd.mips.host_OLD_store ==
604 dpavlin 14 cpu->cd.mips.host_store_orig)
605 dpavlin 22 cpu->cd.mips.host_OLD_store[index] = NULL;
606 dpavlin 14 } else if (writeflag==0 && p_w != NULL && host_page != NULL) {
607     /* Don't degrade a page from writable to readonly. */
608     } else {
609     if (host_page != NULL) {
610     tbl1->haddr_entry[b*2] = host_page;
611 dpavlin 22 if (cpu->cd.mips.host_OLD_load ==
612 dpavlin 14 cpu->cd.mips.host_load_orig)
613 dpavlin 22 cpu->cd.mips.host_OLD_load[index] = host_page;
614 dpavlin 14 if (writeflag) {
615     tbl1->haddr_entry[b*2+1] = host_page;
616 dpavlin 22 if (cpu->cd.mips.host_OLD_store ==
617 dpavlin 14 cpu->cd.mips.host_store_orig)
618 dpavlin 22 cpu->cd.mips.host_OLD_store[index] =
619 dpavlin 14 host_page;
620     } else {
621     tbl1->haddr_entry[b*2+1] = NULL;
622 dpavlin 22 if (cpu->cd.mips.host_OLD_store ==
623 dpavlin 14 cpu->cd.mips.host_store_orig)
624 dpavlin 22 cpu->cd.mips.host_OLD_store[index] =
625     NULL;
626 dpavlin 14 }
627     } else {
628     tbl1->haddr_entry[b*2] = NULL;
629     tbl1->haddr_entry[b*2+1] = NULL;
630 dpavlin 22 if (cpu->cd.mips.host_OLD_store ==
631 dpavlin 14 cpu->cd.mips.host_store_orig) {
632 dpavlin 22 cpu->cd.mips.host_OLD_load[index] = NULL;
633     cpu->cd.mips.host_OLD_store[index] = NULL;
634 dpavlin 14 }
635     }
636     tbl1->paddr_entry[b] = paddr_page;
637     }
638     tbl1->bintrans_chunks[b] = NULL;
639     }
640    
641    
642     /*
643 dpavlin 22 * mips_OLD_update_translation_table():
644 dpavlin 14 */
645 dpavlin 22 void mips_OLD_update_translation_table(struct cpu *cpu, uint64_t vaddr_page,
646 dpavlin 14 unsigned char *host_page, int writeflag, uint64_t paddr_page)
647     {
648     if (!cpu->machine->bintrans_enable)
649     return;
650    
651     if (writeflag > 0)
652     bintrans_invalidate(cpu, paddr_page);
653    
654     if (cpu->machine->old_bintrans_enable) {
655     old_update_translation_table(cpu, vaddr_page, host_page,
656     writeflag, paddr_page);
657     return;
658     }
659    
660     /* TODO */
661     /* printf("update_translation_table(): TODO\n"); */
662     }
663    
664    
665     /*
666     * invalidate_table_entry():
667     */
668     static void invalidate_table_entry(struct cpu *cpu, uint64_t vaddr)
669     {
670     int a, b, index;
671     struct vth32_table *tbl1;
672     void *p_r, *p_w;
673     uint32_t p_paddr;
674    
675     if (!cpu->machine->old_bintrans_enable) {
676     /* printf("invalidate_table_entry(): New: TODO\n"); */
677     return;
678     }
679    
680     /* This table stuff only works for 32-bit mode: */
681     if (vaddr & 0x80000000ULL) {
682     if ((vaddr >> 32) != 0xffffffffULL) {
683     fatal("invalidate_table_entry(): vaddr = 0x%016llx\n",
684     (long long)vaddr);
685     return;
686     }
687     } else {
688     if ((vaddr >> 32) != 0) {
689     fatal("invalidate_table_entry(): vaddr = 0x%016llx\n",
690     (long long)vaddr);
691     return;
692     }
693     }
694    
695     a = (vaddr >> 22) & 0x3ff;
696     b = (vaddr >> 12) & 0x3ff;
697     index = (vaddr >> 12) & 0xfffff;
698    
699     /* printf("vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b); */
700    
701     tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];
702     /* printf("tbl1 = %p\n", tbl1); */
703     p_r = tbl1->haddr_entry[b*2];
704     p_w = tbl1->haddr_entry[b*2+1];
705     p_paddr = tbl1->paddr_entry[b];
706     tbl1->bintrans_chunks[b] = NULL;
707     /* printf("B: p_r=%p p_w=%p\n", p_r,p_w); */
708     cpu->cd.mips.host_load_orig[index] = NULL;
709     cpu->cd.mips.host_store_orig[index] = NULL;
710     if (p_r != NULL || p_paddr != 0) {
711     /* printf("Found a mapping, "
712     "vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b); */
713     tbl1->haddr_entry[b*2] = NULL;
714     tbl1->haddr_entry[b*2+1] = NULL;
715     tbl1->paddr_entry[b] = 0;
716     tbl1->refcount --;
717     if (tbl1->refcount == 0) {
718     cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a] =
719     cpu->cd.mips.vaddr_to_hostaddr_nulltable;
720     /* "free" tbl1: */
721     tbl1->next_free = cpu->cd.mips.next_free_vth_table;
722     cpu->cd.mips.next_free_vth_table = tbl1;
723     }
724     }
725     }
726    
727    
728     /*
729     * clear_all_chunks_from_all_tables():
730     */
731     void clear_all_chunks_from_all_tables(struct cpu *cpu)
732     {
733     int a, b;
734     struct vth32_table *tbl1;
735    
736     if (!cpu->machine->old_bintrans_enable) {
737     printf("clear_all_chunks_from_all_tables(): New: TODO\n");
738     return;
739     }
740    
741     for (a=0; a<0x400; a++) {
742     tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];
743     if (tbl1 != cpu->cd.mips.vaddr_to_hostaddr_nulltable) {
744     for (b=0; b<0x400; b++) {
745     int index;
746    
747     tbl1->haddr_entry[b*2] = NULL;
748     tbl1->haddr_entry[b*2+1] = NULL;
749     tbl1->paddr_entry[b] = 0;
750     tbl1->bintrans_chunks[b] = NULL;
751    
752 dpavlin 22 if (cpu->cd.mips.host_OLD_store ==
753 dpavlin 14 cpu->cd.mips.host_store_orig) {
754     index = (a << 10) + b;
755 dpavlin 22 cpu->cd.mips.host_OLD_load[index] =
756     NULL;
757     cpu->cd.mips.host_OLD_store[index] =
758     NULL;
759 dpavlin 14 }
760     }
761     }
762     }
763     }
764    
765    
766     /*
767     * mips_invalidate_translation_caches_paddr():
768     *
769     * Invalidate based on physical address.
770     */
771     void mips_invalidate_translation_caches_paddr(struct cpu *cpu,
772     uint64_t paddr, int flags)
773     {
774     paddr &= ~0xfff;
775    
776     if (cpu->machine->bintrans_enable) {
777     #if 1
778     int i;
779     uint64_t tlb_paddr0, tlb_paddr1;
780     uint64_t tlb_vaddr;
781     uint64_t p, p2;
782    
783     switch (cpu->cd.mips.cpu_type.mmu_model) {
784     case MMU3K:
785     for (i=0; i<64; i++) {
786     tlb_paddr0 = cpu->cd.mips.coproc[0]->
787     tlbs[i].lo0 & R2K3K_ENTRYLO_PFN_MASK;
788     tlb_vaddr = cpu->cd.mips.coproc[0]->
789     tlbs[i].hi & R2K3K_ENTRYHI_VPN_MASK;
790     tlb_vaddr = (int64_t)(int32_t)tlb_vaddr;
791     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo0 &
792     R2K3K_ENTRYLO_V) && tlb_paddr0 == paddr)
793     invalidate_table_entry(cpu, tlb_vaddr);
794     }
795     break;
796     default:
797     for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
798     int psize = 12;
799     int or_pmask = 0x1fff;
800     int phys_shift = 12;
801 dpavlin 20 int tmp_pmask = cpu->cd.mips.coproc[0]->
802     tlbs[i].mask | or_pmask;
803 dpavlin 14
804     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
805     or_pmask = 0x7ff;
806     phys_shift = 10;
807     }
808 dpavlin 20 switch (tmp_pmask) {
809 dpavlin 14 case 0x000007ff: psize = 10; break;
810     case 0x00001fff: psize = 12; break;
811     case 0x00007fff: psize = 14; break;
812     case 0x0001ffff: psize = 16; break;
813     case 0x0007ffff: psize = 18; break;
814     case 0x001fffff: psize = 20; break;
815     case 0x007fffff: psize = 22; break;
816     case 0x01ffffff: psize = 24; break;
817     case 0x07ffffff: psize = 26; break;
818     default:
819     printf("invalidate_translation_caches"
820 dpavlin 20 "_paddr(): bad pagemask: 0x%x\n",
821     (int)tmp_pmask);
822 dpavlin 14 }
823     tlb_paddr0 = (cpu->cd.mips.coproc[0]->tlbs[i].
824     lo0 & ENTRYLO_PFN_MASK)>>ENTRYLO_PFN_SHIFT;
825     tlb_paddr1 = (cpu->cd.mips.coproc[0]->tlbs[i].
826     lo1 & ENTRYLO_PFN_MASK)>>ENTRYLO_PFN_SHIFT;
827     tlb_paddr0 <<= phys_shift;
828     tlb_paddr1 <<= phys_shift;
829     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
830     tlb_vaddr = cpu->cd.mips.coproc[0]->
831     tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
832     if (tlb_vaddr & ((int64_t)1 << 43))
833     tlb_vaddr |=
834     0xfffff00000000000ULL;
835     } else {
836     tlb_vaddr = cpu->cd.mips.coproc[0]->
837     tlbs[i].hi & ENTRYHI_VPN2_MASK;
838     if (tlb_vaddr & ((int64_t)1 << 39))
839     tlb_vaddr |=
840     0xffffff0000000000ULL;
841     }
842     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo0 &
843     ENTRYLO_V) && paddr >= tlb_paddr0 &&
844     paddr < tlb_paddr0 + (1<<psize)) {
845     p2 = 1 << psize;
846     for (p=0; p<p2; p+=4096)
847     invalidate_table_entry(cpu,
848     tlb_vaddr + p);
849     }
850     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo1 &
851     ENTRYLO_V) && paddr >= tlb_paddr1 &&
852     paddr < tlb_paddr1 + (1<<psize)) {
853     p2 = 1 << psize;
854     for (p=0; p<p2; p+=4096)
855     invalidate_table_entry(cpu,
856     tlb_vaddr + p +
857     (1 << psize));
858     }
859     }
860     }
861     #endif
862    
863     if (paddr < 0x20000000) {
864     invalidate_table_entry(cpu, 0xffffffff80000000ULL
865     + paddr);
866     invalidate_table_entry(cpu, 0xffffffffa0000000ULL
867     + paddr);
868     }
869     }
870    
871     #if 0
872     {
873     int i;
874    
875     /* TODO: Don't invalidate everything. */
876     for (i=0; i<N_BINTRANS_VADDR_TO_HOST; i++)
877     cpu->bintrans_data_hostpage[i] = NULL;
878     }
879     #endif
880     }
881    
882    
883     /*
884     * invalidate_translation_caches():
885     *
886     * This is necessary for every change to the TLB, and when the ASID is changed,
887     * so that for example user-space addresses are not cached when they should
888     * not be.
889     */
890     static void invalidate_translation_caches(struct cpu *cpu,
891     int all, uint64_t vaddr, int kernelspace, int old_asid_to_invalidate)
892     {
893     int i;
894    
895     /* printf("inval(all=%i, kernel=%i, addr=%016llx)\n",
896     all, kernelspace, (long long)vaddr); */
897    
898     if (!cpu->machine->bintrans_enable)
899     goto nobintrans;
900    
901     if (all) {
902     int i;
903     uint64_t tlb_vaddr;
904     switch (cpu->cd.mips.cpu_type.mmu_model) {
905     case MMU3K:
906     for (i=0; i<64; i++) {
907     tlb_vaddr = cpu->cd.mips.coproc[0]->tlbs[i].hi
908     & R2K3K_ENTRYHI_VPN_MASK;
909     tlb_vaddr = (int64_t)(int32_t)tlb_vaddr;
910     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo0 &
911     R2K3K_ENTRYLO_V) && (tlb_vaddr &
912     0xc0000000ULL) != 0x80000000ULL) {
913     int asid = (cpu->cd.mips.coproc[0]->
914     tlbs[i].hi & R2K3K_ENTRYHI_ASID_MASK
915     ) >> R2K3K_ENTRYHI_ASID_SHIFT;
916     if (old_asid_to_invalidate < 0 ||
917     old_asid_to_invalidate == asid)
918     invalidate_table_entry(cpu,
919     tlb_vaddr);
920     }
921     }
922     break;
923     default:
924     for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
925     int psize = 10, or_pmask = 0x1fff;
926     int phys_shift = 12;
927    
928     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
929     or_pmask = 0x7ff;
930     phys_shift = 10;
931     }
932    
933     switch (cpu->cd.mips.coproc[0]->tlbs[i].mask
934     | or_pmask) {
935     case 0x000007ff: psize = 10; break;
936     case 0x00001fff: psize = 12; break;
937     case 0x00007fff: psize = 14; break;
938     case 0x0001ffff: psize = 16; break;
939     case 0x0007ffff: psize = 18; break;
940     case 0x001fffff: psize = 20; break;
941     case 0x007fffff: psize = 22; break;
942     case 0x01ffffff: psize = 24; break;
943     case 0x07ffffff: psize = 26; break;
944     default:
945     printf("invalidate_translation_caches"
946     "(): bad pagemask?\n");
947     }
948    
949     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
950     tlb_vaddr = cpu->cd.mips.coproc[0]->
951     tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
952     if (tlb_vaddr & ((int64_t)1 << 43))
953     tlb_vaddr |=
954     0xfffff00000000000ULL;
955     } else {
956     tlb_vaddr = cpu->cd.mips.coproc[0]->
957     tlbs[i].hi & ENTRYHI_VPN2_MASK;
958     if (tlb_vaddr & ((int64_t)1 << 39))
959     tlb_vaddr |=
960     0xffffff0000000000ULL;
961     }
962    
963     /* TODO: Check the ASID etc. */
964    
965     invalidate_table_entry(cpu, tlb_vaddr);
966     invalidate_table_entry(cpu, tlb_vaddr |
967     (1 << psize));
968     }
969     }
970     } else
971     invalidate_table_entry(cpu, vaddr);
972    
973     nobintrans:
974    
975     /* TODO: Don't invalidate everything. */
976     for (i=0; i<N_BINTRANS_VADDR_TO_HOST; i++)
977     cpu->cd.mips.bintrans_data_hostpage[i] = NULL;
978    
979     if (kernelspace)
980     all = 1;
981    
982     #ifdef USE_TINY_CACHE
983     {
984     vaddr >>= 12;
985    
986     /* Invalidate the tiny translation cache... */
987     if (!cpu->machine->bintrans_enable)
988     for (i=0; i<N_TRANSLATION_CACHE_INSTR; i++)
989     if (all || vaddr == (cpu->cd.mips.
990     translation_cache_instr[i].vaddr_pfn))
991     cpu->cd.mips.translation_cache_instr[i].wf = 0;
992    
993     if (!cpu->machine->bintrans_enable)
994     for (i=0; i<N_TRANSLATION_CACHE_DATA; i++)
995     if (all || vaddr == (cpu->cd.mips.
996     translation_cache_data[i].vaddr_pfn))
997     cpu->cd.mips.translation_cache_data[i].wf = 0;
998     }
999     #endif
1000     }
1001    
1002    
1003     /*
1004     * coproc_register_read();
1005     *
1006     * Read a value from a MIPS coprocessor register.
1007     */
1008     void coproc_register_read(struct cpu *cpu,
1009     struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int select)
1010     {
1011     int unimpl = 1;
1012    
1013     if (cp->coproc_nr==0 && reg_nr==COP0_INDEX) unimpl = 0;
1014     if (cp->coproc_nr==0 && reg_nr==COP0_RANDOM) unimpl = 0;
1015     if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO0) unimpl = 0;
1016     if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO1) unimpl = 0;
1017     if (cp->coproc_nr==0 && reg_nr==COP0_CONTEXT) unimpl = 0;
1018     if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK) unimpl = 0;
1019     if (cp->coproc_nr==0 && reg_nr==COP0_WIRED) unimpl = 0;
1020     if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR) unimpl = 0;
1021     if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) {
1022 dpavlin 20 #if 0
1023 dpavlin 14 /*
1024     * This speeds up delay-loops that just read the count
1025     * register until it has reached a certain value. (Only for
1026     * R4000 etc.)
1027     *
1028     * TODO: Maybe this should be optional?
1029     */
1030     if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1031     int increase = 500;
1032     int32_t x = cp->reg[COP0_COUNT];
1033     int32_t y = cp->reg[COP0_COMPARE];
1034     int32_t diff = x - y;
1035     if (diff < 0 && diff + increase >= 0
1036     && cpu->cd.mips.compare_register_set) {
1037     mips_cpu_interrupt(cpu, 7);
1038     cpu->cd.mips.compare_register_set = 0;
1039     }
1040     cp->reg[COP0_COUNT] = (int64_t)
1041     (int32_t)(cp->reg[COP0_COUNT] + increase);
1042     }
1043 dpavlin 20 #endif
1044 dpavlin 14 unimpl = 0;
1045     }
1046     if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI) unimpl = 0;
1047     if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE) unimpl = 0;
1048     if (cp->coproc_nr==0 && reg_nr==COP0_STATUS) unimpl = 0;
1049     if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE) unimpl = 0;
1050     if (cp->coproc_nr==0 && reg_nr==COP0_EPC) unimpl = 0;
1051     if (cp->coproc_nr==0 && reg_nr==COP0_PRID) unimpl = 0;
1052     if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG) {
1053     if (select > 0) {
1054     switch (select) {
1055     case 1: *ptr = cpu->cd.mips.cop0_config_select1;
1056     break;
1057     default:fatal("coproc_register_read(): unimplemented"
1058     " config register select %i\n", select);
1059     exit(1);
1060     }
1061     return;
1062     }
1063     unimpl = 0;
1064     }
1065     if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR) unimpl = 0;
1066     if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO) unimpl = 0;
1067     if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI) unimpl = 0;
1068     if (cp->coproc_nr==0 && reg_nr==COP0_XCONTEXT) unimpl = 0;
1069     if (cp->coproc_nr==0 && reg_nr==COP0_ERRCTL) unimpl = 0;
1070     if (cp->coproc_nr==0 && reg_nr==COP0_CACHEERR) unimpl = 0;
1071     if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_LO) unimpl = 0;
1072     if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_HI) unimpl = 0;
1073     if (cp->coproc_nr==0 && reg_nr==COP0_ERROREPC) unimpl = 0;
1074     if (cp->coproc_nr==0 && reg_nr==COP0_RESERV22) {
1075     /* Used by Linux on Linksys WRT54G */
1076     unimpl = 0;
1077     }
1078     if (cp->coproc_nr==0 && reg_nr==COP0_DEBUG) unimpl = 0;
1079     if (cp->coproc_nr==0 && reg_nr==COP0_PERFCNT) unimpl = 0;
1080     if (cp->coproc_nr==0 && reg_nr==COP0_DESAVE) unimpl = 0;
1081    
1082     if (cp->coproc_nr==1) unimpl = 0;
1083    
1084     if (unimpl) {
1085     fatal("cpu%i: warning: read from unimplemented coproc%i"
1086     " register %i (%s)\n", cpu->cpu_id, cp->coproc_nr, reg_nr,
1087     cp->coproc_nr==0? cop0_names[reg_nr] : "?");
1088    
1089     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
1090     cp->coproc_nr, 0, 0, 0);
1091     return;
1092     }
1093    
1094     *ptr = cp->reg[reg_nr];
1095     }
1096    
1097    
1098     /*
1099     * coproc_register_write();
1100     *
1101     * Write a value to a MIPS coprocessor register.
1102     */
1103     void coproc_register_write(struct cpu *cpu,
1104     struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64,
1105     int select)
1106     {
1107     int unimpl = 1;
1108     int readonly = 0;
1109     uint64_t tmp = *ptr;
1110     uint64_t tmp2 = 0, old;
1111     int inval = 0, old_asid, oldmode;
1112    
1113     switch (cp->coproc_nr) {
1114     case 0:
1115     /* COPROC 0: */
1116     switch (reg_nr) {
1117     case COP0_INDEX:
1118     case COP0_RANDOM:
1119     unimpl = 0;
1120     break;
1121     case COP0_ENTRYLO0:
1122     unimpl = 0;
1123     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
1124     (tmp & 0xff)!=0) {
1125     /* char *symbol;
1126     uint64_t offset;
1127     symbol = get_symbol_name(
1128     cpu->cd.mips.pc_last, &offset);
1129     fatal("YO! pc = 0x%08llx <%s> "
1130     "lo=%016llx\n", (long long)
1131     cpu->cd.mips.pc_last, symbol? symbol :
1132     "no symbol", (long long)tmp); */
1133     tmp &= (R2K3K_ENTRYLO_PFN_MASK |
1134     R2K3K_ENTRYLO_N | R2K3K_ENTRYLO_D |
1135     R2K3K_ENTRYLO_V | R2K3K_ENTRYLO_G);
1136     } else if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
1137     tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
1138     ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
1139     }
1140     break;
1141     case COP0_BADVADDR:
1142     /* Hm. Irix writes to this register. (Why?) */
1143     unimpl = 0;
1144     break;
1145     case COP0_ENTRYLO1:
1146     unimpl = 0;
1147     if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
1148     tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
1149     ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
1150     }
1151     break;
1152     case COP0_CONTEXT:
1153     old = cp->reg[COP0_CONTEXT];
1154     cp->reg[COP0_CONTEXT] = tmp;
1155     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1156     cp->reg[COP0_CONTEXT] &=
1157     ~R2K3K_CONTEXT_BADVPN_MASK;
1158     cp->reg[COP0_CONTEXT] |=
1159     (old & R2K3K_CONTEXT_BADVPN_MASK);
1160     } else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1161     cp->reg[COP0_CONTEXT] &=
1162     ~CONTEXT_BADVPN2_MASK_R4100;
1163     cp->reg[COP0_CONTEXT] |=
1164     (old & CONTEXT_BADVPN2_MASK_R4100);
1165     } else {
1166     cp->reg[COP0_CONTEXT] &=
1167     ~CONTEXT_BADVPN2_MASK;
1168     cp->reg[COP0_CONTEXT] |=
1169     (old & CONTEXT_BADVPN2_MASK);
1170     }
1171     return;
1172     case COP0_PAGEMASK:
1173     tmp2 = tmp >> PAGEMASK_SHIFT;
1174     if (tmp2 != 0x000 &&
1175     tmp2 != 0x003 &&
1176     tmp2 != 0x00f &&
1177     tmp2 != 0x03f &&
1178     tmp2 != 0x0ff &&
1179     tmp2 != 0x3ff &&
1180     tmp2 != 0xfff)
1181     fatal("cpu%i: trying to write an invalid"
1182     " pagemask 0x%08lx to COP0_PAGEMASK\n",
1183     cpu->cpu_id, (long)tmp);
1184     unimpl = 0;
1185     break;
1186     case COP0_WIRED:
1187     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1188     fatal("cpu%i: r2k/r3k wired register must "
1189     "always be 8\n", cpu->cpu_id);
1190     tmp = 8;
1191     }
1192     cp->reg[COP0_RANDOM] = cp->nr_of_tlbs-1;
1193     tmp &= INDEX_MASK;
1194     unimpl = 0;
1195     break;
1196     case COP0_COUNT:
1197 dpavlin 22 if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
1198 dpavlin 14 fatal("WARNING: trying to write a 64-bit value"
1199     " to the COUNT register!\n");
1200     tmp = (int64_t)(int32_t)tmp;
1201     unimpl = 0;
1202     break;
1203     case COP0_COMPARE:
1204     /* Clear the timer interrupt bit (bit 7): */
1205     cpu->cd.mips.compare_register_set = 1;
1206     mips_cpu_interrupt_ack(cpu, 7);
1207 dpavlin 22 if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
1208 dpavlin 14 fatal("WARNING: trying to write a 64-bit value"
1209     " to the COMPARE register!\n");
1210     tmp = (int64_t)(int32_t)tmp;
1211     unimpl = 0;
1212     break;
1213     case COP0_ENTRYHI:
1214     /*
1215     * Translation caches must be invalidated, because the
1216     * address space might change (if the ASID changes).
1217     */
1218     switch (cpu->cd.mips.cpu_type.mmu_model) {
1219     case MMU3K:
1220     old_asid = (cp->reg[COP0_ENTRYHI] &
1221     R2K3K_ENTRYHI_ASID_MASK) >>
1222     R2K3K_ENTRYHI_ASID_SHIFT;
1223     if ((cp->reg[COP0_ENTRYHI] &
1224     R2K3K_ENTRYHI_ASID_MASK) !=
1225     (tmp & R2K3K_ENTRYHI_ASID_MASK))
1226     inval = 1;
1227     break;
1228     default:
1229     old_asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
1230     if ((cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID) !=
1231     (tmp & ENTRYHI_ASID))
1232     inval = 1;
1233     break;
1234     }
1235     if (inval)
1236     invalidate_translation_caches(cpu, 1, 0, 0,
1237     old_asid);
1238     unimpl = 0;
1239     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
1240     (tmp & 0x3f)!=0) {
1241     /* char *symbol;
1242     uint64_t offset;
1243     symbol = get_symbol_name(cpu->
1244     cd.mips.pc_last, &offset);
1245     fatal("YO! pc = 0x%08llx <%s> "
1246     "hi=%016llx\n", (long long)cpu->
1247     cd.mips.pc_last, symbol? symbol :
1248     "no symbol", (long long)tmp); */
1249     tmp &= ~0x3f;
1250     }
1251     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1252     tmp &= (R2K3K_ENTRYHI_VPN_MASK |
1253     R2K3K_ENTRYHI_ASID_MASK);
1254     else if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1255     tmp &= (ENTRYHI_R_MASK |
1256     ENTRYHI_VPN2_MASK_R10K | ENTRYHI_ASID);
1257     else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
1258     tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
1259     0x1800 | ENTRYHI_ASID);
1260     else
1261     tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
1262     ENTRYHI_ASID);
1263     break;
1264     case COP0_EPC:
1265     unimpl = 0;
1266     break;
1267     case COP0_PRID:
1268     readonly = 1;
1269     break;
1270     case COP0_CONFIG:
1271     if (select > 0) {
1272     switch (select) {
1273     case 1: cpu->cd.mips.cop0_config_select1 = tmp;
1274     break;
1275     default:fatal("coproc_register_write(): unimpl"
1276     "emented config register select "
1277     "%i\n", select);
1278     exit(1);
1279     }
1280     return;
1281     }
1282    
1283     /* fatal("COP0_CONFIG: modifying K0 bits: "
1284     "0x%08x => ", cp->reg[reg_nr]); */
1285     tmp = *ptr;
1286     tmp &= 0x3; /* only bits 2..0 can be written */
1287     cp->reg[reg_nr] &= ~(0x3); cp->reg[reg_nr] |= tmp;
1288     /* fatal("0x%08x\n", cp->reg[reg_nr]); */
1289     return;
1290     case COP0_STATUS:
1291     oldmode = cp->reg[COP0_STATUS];
1292     tmp &= ~(1 << 21); /* bit 21 is read-only */
1293     #if 0
1294     /* Why was this here? It should not be necessary. */
1295    
1296     /* Changing from kernel to user mode? Then
1297     invalidate some translation caches: */
1298     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1299     if (!(oldmode & MIPS1_SR_KU_CUR)
1300     && (tmp & MIPS1_SR_KU_CUR))
1301     invalidate_translation_caches(cpu,
1302     0, 0, 1, 0);
1303     } else {
1304     /* TODO: don't hardcode */
1305     if ((oldmode & 0xff) != (tmp & 0xff))
1306     invalidate_translation_caches(
1307     cpu, 0, 0, 1, 0);
1308     }
1309     #endif
1310    
1311     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
1312 dpavlin 22 ((uint32_t)oldmode & MIPS1_ISOL_CACHES) !=
1313 dpavlin 14 (tmp & MIPS1_ISOL_CACHES)) {
1314     /* R3000-style caches when isolated are
1315     treated in bintrans mode by changing
1316     the vaddr_to_hostaddr_table0 pointer: */
1317     if (tmp & MIPS1_ISOL_CACHES) {
1318     /* 2-level table: */
1319     cpu->cd.mips.vaddr_to_hostaddr_table0 =
1320     tmp & MIPS1_SWAP_CACHES?
1321     cpu->cd.mips.
1322     vaddr_to_hostaddr_table0_cacheisol_i
1323     : cpu->cd.mips.
1324     vaddr_to_hostaddr_table0_cacheisol_d;
1325    
1326     /* 1M-entry table: */
1327 dpavlin 22 cpu->cd.mips.host_OLD_load =
1328     cpu->cd.mips.host_OLD_store =
1329 dpavlin 14 cpu->cd.mips.huge_r2k3k_cache_table;
1330     } else {
1331     /* 2-level table: */
1332     cpu->cd.mips.vaddr_to_hostaddr_table0 =
1333     cpu->cd.mips.
1334     vaddr_to_hostaddr_table0_kernel;
1335    
1336     /* TODO: cpu->cd.mips.
1337     vaddr_to_hostaddr_table0_user; */
1338    
1339     /* 1M-entry table: */
1340 dpavlin 22 cpu->cd.mips.host_OLD_load =
1341 dpavlin 14 cpu->cd.mips.host_load_orig;
1342 dpavlin 22 cpu->cd.mips.host_OLD_store =
1343 dpavlin 14 cpu->cd.mips.host_store_orig;
1344     }
1345     }
1346     unimpl = 0;
1347     break;
1348     case COP0_CAUSE:
1349     /* A write to the cause register only
1350     affects IM bits 0 and 1: */
1351     cp->reg[reg_nr] &= ~(0x3 << STATUS_IM_SHIFT);
1352     cp->reg[reg_nr] |= (tmp & (0x3 << STATUS_IM_SHIFT));
1353     if (!(cp->reg[COP0_CAUSE] & STATUS_IM_MASK))
1354     cpu->cd.mips.cached_interrupt_is_possible = 0;
1355     else
1356     cpu->cd.mips.cached_interrupt_is_possible = 1;
1357     return;
1358     case COP0_FRAMEMASK:
1359     /* TODO: R10000 */
1360     unimpl = 0;
1361     break;
1362     case COP0_TAGDATA_LO:
1363     case COP0_TAGDATA_HI:
1364     /* TODO: R4300 and others? */
1365     unimpl = 0;
1366     break;
1367     case COP0_LLADDR:
1368     unimpl = 0;
1369     break;
1370     case COP0_WATCHLO:
1371     case COP0_WATCHHI:
1372     unimpl = 0;
1373     break;
1374     case COP0_XCONTEXT:
1375     /*
1376     * TODO: According to the R10000 manual, the R4400
1377     * shares the PTEbase portion of the context registers
1378     * (that is, xcontext and context). On R10000, they
1379     * are separate registers.
1380     */
1381     /* debug("[ xcontext 0x%016llx ]\n", tmp); */
1382     unimpl = 0;
1383     break;
1384    
1385     /* Most of these are actually TODOs: */
1386     case COP0_ERROREPC:
1387     case COP0_DEPC:
1388     case COP0_RESERV22: /* Used by Linux on Linksys WRT54G */
1389     case COP0_DESAVE:
1390     case COP0_PERFCNT:
1391     case COP0_ERRCTL: /* R10000 */
1392     unimpl = 0;
1393     break;
1394     }
1395     break;
1396    
1397     case 1:
1398     /* COPROC 1: */
1399     unimpl = 0;
1400     break;
1401     }
1402    
1403     if (unimpl) {
1404     fatal("cpu%i: warning: write to unimplemented coproc%i "
1405     "register %i (%s), data = 0x%016llx\n", cpu->cpu_id,
1406     cp->coproc_nr, reg_nr, cp->coproc_nr==0?
1407     cop0_names[reg_nr] : "?", (long long)tmp);
1408    
1409     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
1410     cp->coproc_nr, 0, 0, 0);
1411     return;
1412     }
1413    
1414     if (readonly) {
1415     fatal("cpu%i: warning: write to READONLY coproc%i register "
1416     "%i ignored\n", cpu->cpu_id, cp->coproc_nr, reg_nr);
1417     return;
1418     }
1419    
1420     cp->reg[reg_nr] = tmp;
1421    
1422     if (!flag64)
1423     cp->reg[reg_nr] = (int64_t)(int32_t)cp->reg[reg_nr];
1424     }
1425    
1426    
1427     /*
1428     * MIPS floating-point stuff:
1429     *
1430     * TODO: Move this to some other file?
1431     */
1432 dpavlin 20 static int mips_fmt_to_ieee_fmt[32] = {
1433     0, 0, 0, 0, 0, 0, 0, 0,
1434     0, 0, 0, 0, 0, 0, 0, 0,
1435     IEEE_FMT_S, IEEE_FMT_D, 0, 0,
1436     IEEE_FMT_W, IEEE_FMT_L, /* PS (Paired Single) */ 0, 0,
1437     0, 0, 0, 0, 0, 0, 0, 0 };
1438    
1439     /* MIPS floating point types: */
1440 dpavlin 14 #define FMT_S 16
1441     #define FMT_D 17
1442     #define FMT_W 20
1443     #define FMT_L 21
1444     #define FMT_PS 22
1445    
1446     #define FPU_OP_ADD 1
1447     #define FPU_OP_SUB 2
1448     #define FPU_OP_MUL 3
1449     #define FPU_OP_DIV 4
1450     #define FPU_OP_SQRT 5
1451     #define FPU_OP_MOV 6
1452     #define FPU_OP_CVT 7
1453     #define FPU_OP_C 8
1454     #define FPU_OP_ABS 9
1455     #define FPU_OP_NEG 10
1456 dpavlin 20 /* TODO: CEIL.L, CEIL.W, FLOOR.L, FLOOR.W, RECIP, ROUND.L, ROUND.W, RSQRT */
1457 dpavlin 14
1458    
1459     /*
1460     * fpu_store_float_value():
1461     *
1462     * Stores a float value (actually a double) in fmt format.
1463     */
1464     static void fpu_store_float_value(struct mips_coproc *cp, int fd,
1465     double nf, int fmt, int nan)
1466     {
1467 dpavlin 20 int ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1468     uint64_t r = ieee_store_float_value(nf, ieee_fmt, nan);
1469 dpavlin 14
1470     /*
1471 dpavlin 20 * TODO: This is for 32-bit mode. It has to be updated later
1472     * for 64-bit coprocessor functionality!
1473 dpavlin 14 */
1474     if (fmt == FMT_D || fmt == FMT_L) {
1475     cp->reg[fd] = r & 0xffffffffULL;
1476     cp->reg[(fd+1) & 31] = (r >> 32) & 0xffffffffULL;
1477    
1478     if (cp->reg[fd] & 0x80000000ULL)
1479     cp->reg[fd] |= 0xffffffff00000000ULL;
1480     if (cp->reg[fd+1] & 0x80000000ULL)
1481     cp->reg[fd+1] |= 0xffffffff00000000ULL;
1482     } else {
1483     cp->reg[fd] = r & 0xffffffffULL;
1484    
1485     if (cp->reg[fd] & 0x80000000ULL)
1486     cp->reg[fd] |= 0xffffffff00000000ULL;
1487     }
1488     }
1489    
1490    
1491     /*
1492     * fpu_op():
1493     *
1494 dpavlin 20 * Perform a floating-point operation. For those of fs and ft that are >= 0,
1495     * those numbers are interpreted into local variables.
1496 dpavlin 14 *
1497 dpavlin 20 * Only FPU_OP_C (compare) returns anything of interest, 1 for true, 0 for
1498     * false.
1499 dpavlin 14 */
1500     static int fpu_op(struct cpu *cpu, struct mips_coproc *cp, int op, int fmt,
1501     int ft, int fs, int fd, int cond, int output_fmt)
1502     {
1503     /* Potentially two input registers, fs and ft */
1504 dpavlin 20 struct ieee_float_value float_value[2];
1505     int unordered, nan, ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1506 dpavlin 14 uint64_t fs_v = 0;
1507     double nf;
1508    
1509     if (fs >= 0) {
1510     fs_v = cp->reg[fs];
1511     /* TODO: register-pair mode and plain
1512     register mode? "FR" bit? */
1513     if (fmt == FMT_D || fmt == FMT_L)
1514     fs_v = (fs_v & 0xffffffffULL) +
1515     (cp->reg[(fs + 1) & 31] << 32);
1516 dpavlin 20 ieee_interpret_float_value(fs_v, &float_value[0], ieee_fmt);
1517 dpavlin 14 }
1518     if (ft >= 0) {
1519     uint64_t v = cp->reg[ft];
1520     /* TODO: register-pair mode and
1521     plain register mode? "FR" bit? */
1522     if (fmt == FMT_D || fmt == FMT_L)
1523     v = (v & 0xffffffffULL) +
1524     (cp->reg[(ft + 1) & 31] << 32);
1525 dpavlin 20 ieee_interpret_float_value(v, &float_value[1], ieee_fmt);
1526 dpavlin 14 }
1527    
1528     switch (op) {
1529     case FPU_OP_ADD:
1530     nf = float_value[0].f + float_value[1].f;
1531     /* debug(" add: %f + %f = %f\n",
1532     float_value[0].f, float_value[1].f, nf); */
1533     fpu_store_float_value(cp, fd, nf, output_fmt,
1534     float_value[0].nan || float_value[1].nan);
1535     break;
1536     case FPU_OP_SUB:
1537     nf = float_value[0].f - float_value[1].f;
1538     /* debug(" sub: %f - %f = %f\n",
1539     float_value[0].f, float_value[1].f, nf); */
1540     fpu_store_float_value(cp, fd, nf, output_fmt,
1541     float_value[0].nan || float_value[1].nan);
1542     break;
1543     case FPU_OP_MUL:
1544     nf = float_value[0].f * float_value[1].f;
1545     /* debug(" mul: %f * %f = %f\n",
1546     float_value[0].f, float_value[1].f, nf); */
1547     fpu_store_float_value(cp, fd, nf, output_fmt,
1548     float_value[0].nan || float_value[1].nan);
1549     break;
1550     case FPU_OP_DIV:
1551     nan = float_value[0].nan || float_value[1].nan;
1552     if (fabs(float_value[1].f) > 0.00000000001)
1553     nf = float_value[0].f / float_value[1].f;
1554     else {
1555     fatal("DIV by zero !!!!\n");
1556     nf = 0.0; /* TODO */
1557     nan = 1;
1558     }
1559     /* debug(" div: %f / %f = %f\n",
1560     float_value[0].f, float_value[1].f, nf); */
1561     fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1562     break;
1563     case FPU_OP_SQRT:
1564     nan = float_value[0].nan;
1565     if (float_value[0].f >= 0.0)
1566     nf = sqrt(float_value[0].f);
1567     else {
1568     fatal("SQRT by less than zero, %f !!!!\n",
1569     float_value[0].f);
1570     nf = 0.0; /* TODO */
1571     nan = 1;
1572     }
1573     /* debug(" sqrt: %f => %f\n", float_value[0].f, nf); */
1574     fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1575     break;
1576     case FPU_OP_ABS:
1577     nf = fabs(float_value[0].f);
1578     /* debug(" abs: %f => %f\n", float_value[0].f, nf); */
1579     fpu_store_float_value(cp, fd, nf, output_fmt,
1580     float_value[0].nan);
1581     break;
1582     case FPU_OP_NEG:
1583     nf = - float_value[0].f;
1584     /* debug(" neg: %f => %f\n", float_value[0].f, nf); */
1585     fpu_store_float_value(cp, fd, nf, output_fmt,
1586     float_value[0].nan);
1587     break;
1588     case FPU_OP_CVT:
1589     nf = float_value[0].f;
1590     /* debug(" mov: %f => %f\n", float_value[0].f, nf); */
1591     fpu_store_float_value(cp, fd, nf, output_fmt,
1592     float_value[0].nan);
1593     break;
1594     case FPU_OP_MOV:
1595     /* Non-arithmetic move: */
1596     /*
1597     * TODO: this is for 32-bit mode. It has to be updated later
1598     * for 64-bit coprocessor stuff.
1599     */
1600     if (output_fmt == FMT_D || output_fmt == FMT_L) {
1601     cp->reg[fd] = fs_v & 0xffffffffULL;
1602     cp->reg[(fd+1) & 31] = (fs_v >> 32) & 0xffffffffULL;
1603     if (cp->reg[fd] & 0x80000000ULL)
1604     cp->reg[fd] |= 0xffffffff00000000ULL;
1605     if (cp->reg[fd+1] & 0x80000000ULL)
1606     cp->reg[fd+1] |= 0xffffffff00000000ULL;
1607     } else {
1608     cp->reg[fd] = fs_v & 0xffffffffULL;
1609     if (cp->reg[fd] & 0x80000000ULL)
1610     cp->reg[fd] |= 0xffffffff00000000ULL;
1611     }
1612     break;
1613     case FPU_OP_C:
1614     /* debug(" c: cond=%i\n", cond); */
1615    
1616     unordered = 0;
1617     if (float_value[0].nan || float_value[1].nan)
1618     unordered = 1;
1619    
1620     switch (cond) {
1621     case 2: /* Equal */
1622     return (float_value[0].f == float_value[1].f);
1623     case 4: /* Ordered or Less than */
1624     return (float_value[0].f < float_value[1].f)
1625     || !unordered;
1626     case 5: /* Unordered or Less than */
1627     return (float_value[0].f < float_value[1].f)
1628     || unordered;
1629     case 6: /* Ordered or Less than or Equal */
1630     return (float_value[0].f <= float_value[1].f)
1631     || !unordered;
1632     case 7: /* Unordered or Less than or Equal */
1633     return (float_value[0].f <= float_value[1].f)
1634     || unordered;
1635     case 12:/* Less than */
1636     return (float_value[0].f < float_value[1].f);
1637     case 14:/* Less than or equal */
1638     return (float_value[0].f <= float_value[1].f);
1639    
1640     /* The following are not commonly used, so I'll move these out
1641     of the if-0 on a case-by-case basis. */
1642     #if 0
1643     case 0: return 0; /* False */
1644     case 1: return 0; /* Unordered */
1645     case 3: return (float_value[0].f == float_value[1].f);
1646     /* Unordered or Equal */
1647     case 8: return 0; /* Signaling false */
1648     case 9: return 0; /* Not Greater than or Less than or Equal */
1649     case 10:return (float_value[0].f == float_value[1].f); /* Signaling Equal */
1650     case 11:return (float_value[0].f == float_value[1].f); /* Not Greater
1651     than or Less than */
1652     case 13:return !(float_value[0].f >= float_value[1].f); /* Not greater
1653     than or equal */
1654     case 15:return !(float_value[0].f > float_value[1].f); /* Not greater than */
1655     #endif
1656    
1657     default:
1658     fatal("fpu_op(): unimplemented condition "
1659     "code %i. see cpu_mips_coproc.c\n", cond);
1660     }
1661     break;
1662     default:
1663     fatal("fpu_op(): unimplemented op %i\n", op);
1664     }
1665    
1666     return 0;
1667     }
1668    
1669    
1670     /*
1671     * fpu_function():
1672     *
1673     * Returns 1 if function was implemented, 0 otherwise.
1674     * Debug trace should be printed for known instructions.
1675     */
1676     static int fpu_function(struct cpu *cpu, struct mips_coproc *cp,
1677     uint32_t function, int unassemble_only)
1678     {
1679     int fd, fs, ft, fmt, cond, cc;
1680    
1681     fmt = (function >> 21) & 31;
1682     ft = (function >> 16) & 31;
1683     fs = (function >> 11) & 31;
1684     cc = (function >> 8) & 7;
1685     fd = (function >> 6) & 31;
1686     cond = (function >> 0) & 15;
1687    
1688    
1689     /* bc1f, bc1t, bc1fl, bc1tl: */
1690     if ((function & 0x03e00000) == 0x01000000) {
1691     int nd, tf, imm, cond_true;
1692     char *instr_mnem;
1693    
1694     /* cc are bits 20..18: */
1695     cc = (function >> 18) & 7;
1696     nd = (function >> 17) & 1;
1697     tf = (function >> 16) & 1;
1698     imm = function & 65535;
1699     if (imm >= 32768)
1700     imm -= 65536;
1701    
1702     instr_mnem = NULL;
1703     if (nd == 0 && tf == 0) instr_mnem = "bc1f";
1704     if (nd == 0 && tf == 1) instr_mnem = "bc1t";
1705     if (nd == 1 && tf == 0) instr_mnem = "bc1fl";
1706     if (nd == 1 && tf == 1) instr_mnem = "bc1tl";
1707    
1708     if (cpu->machine->instruction_trace || unassemble_only)
1709     debug("%s\t%i,0x%016llx\n", instr_mnem, cc,
1710     (long long) (cpu->pc + (imm << 2)));
1711     if (unassemble_only)
1712     return 1;
1713    
1714     if (cpu->cd.mips.delay_slot) {
1715     fatal("%s: jump inside a jump's delay slot, "
1716     "or similar. TODO\n", instr_mnem);
1717     cpu->running = 0;
1718     return 1;
1719     }
1720    
1721     /* Both the FCCR and FCSR contain condition code bits... */
1722     if (cc == 0)
1723     cond_true = (cp->fcr[FPU_FCSR] >> FCSR_FCC0_SHIFT) & 1;
1724     else
1725     cond_true = (cp->fcr[FPU_FCSR] >>
1726     (FCSR_FCC1_SHIFT + cc-1)) & 1;
1727    
1728     if (!tf)
1729     cond_true = !cond_true;
1730    
1731     if (cond_true) {
1732     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
1733     cpu->cd.mips.delay_jmpaddr = cpu->pc + (imm << 2);
1734     } else {
1735     /* "likely": */
1736     if (nd) {
1737     /* nullify the delay slot */
1738     cpu->cd.mips.nullify_next = 1;
1739     }
1740     }
1741    
1742     return 1;
1743     }
1744    
1745     /* add.fmt: Floating-point add */
1746     if ((function & 0x0000003f) == 0x00000000) {
1747     if (cpu->machine->instruction_trace || unassemble_only)
1748     debug("add.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1749     if (unassemble_only)
1750     return 1;
1751    
1752     fpu_op(cpu, cp, FPU_OP_ADD, fmt, ft, fs, fd, -1, fmt);
1753     return 1;
1754     }
1755    
1756     /* sub.fmt: Floating-point subtract */
1757     if ((function & 0x0000003f) == 0x00000001) {
1758     if (cpu->machine->instruction_trace || unassemble_only)
1759     debug("sub.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1760     if (unassemble_only)
1761     return 1;
1762    
1763     fpu_op(cpu, cp, FPU_OP_SUB, fmt, ft, fs, fd, -1, fmt);
1764     return 1;
1765     }
1766    
1767     /* mul.fmt: Floating-point multiply */
1768     if ((function & 0x0000003f) == 0x00000002) {
1769     if (cpu->machine->instruction_trace || unassemble_only)
1770     debug("mul.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1771     if (unassemble_only)
1772     return 1;
1773    
1774     fpu_op(cpu, cp, FPU_OP_MUL, fmt, ft, fs, fd, -1, fmt);
1775     return 1;
1776     }
1777    
1778     /* div.fmt: Floating-point divide */
1779     if ((function & 0x0000003f) == 0x00000003) {
1780     if (cpu->machine->instruction_trace || unassemble_only)
1781     debug("div.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1782     if (unassemble_only)
1783     return 1;
1784    
1785     fpu_op(cpu, cp, FPU_OP_DIV, fmt, ft, fs, fd, -1, fmt);
1786     return 1;
1787     }
1788    
1789     /* sqrt.fmt: Floating-point square-root */
1790     if ((function & 0x001f003f) == 0x00000004) {
1791     if (cpu->machine->instruction_trace || unassemble_only)
1792     debug("sqrt.%i\tr%i,r%i\n", fmt, fd, fs);
1793     if (unassemble_only)
1794     return 1;
1795    
1796     fpu_op(cpu, cp, FPU_OP_SQRT, fmt, -1, fs, fd, -1, fmt);
1797     return 1;
1798     }
1799    
1800     /* abs.fmt: Floating-point absolute value */
1801     if ((function & 0x001f003f) == 0x00000005) {
1802     if (cpu->machine->instruction_trace || unassemble_only)
1803     debug("abs.%i\tr%i,r%i\n", fmt, fd, fs);
1804     if (unassemble_only)
1805     return 1;
1806    
1807     fpu_op(cpu, cp, FPU_OP_ABS, fmt, -1, fs, fd, -1, fmt);
1808     return 1;
1809     }
1810    
1811     /* mov.fmt: Floating-point (non-arithmetic) move */
1812     if ((function & 0x0000003f) == 0x00000006) {
1813     if (cpu->machine->instruction_trace || unassemble_only)
1814     debug("mov.%i\tr%i,r%i\n", fmt, fd, fs);
1815     if (unassemble_only)
1816     return 1;
1817    
1818     fpu_op(cpu, cp, FPU_OP_MOV, fmt, -1, fs, fd, -1, fmt);
1819     return 1;
1820     }
1821    
1822     /* neg.fmt: Floating-point negate */
1823     if ((function & 0x001f003f) == 0x00000007) {
1824     if (cpu->machine->instruction_trace || unassemble_only)
1825     debug("neg.%i\tr%i,r%i\n", fmt, fd, fs);
1826     if (unassemble_only)
1827     return 1;
1828    
1829     fpu_op(cpu, cp, FPU_OP_NEG, fmt, -1, fs, fd, -1, fmt);
1830     return 1;
1831     }
1832    
1833     /* trunc.l.fmt: Truncate */
1834     if ((function & 0x001f003f) == 0x00000009) {
1835     if (cpu->machine->instruction_trace || unassemble_only)
1836     debug("trunc.l.%i\tr%i,r%i\n", fmt, fd, fs);
1837     if (unassemble_only)
1838     return 1;
1839    
1840     /* TODO: not CVT? */
1841    
1842     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_L);
1843     return 1;
1844     }
1845    
1846     /* trunc.w.fmt: Truncate */
1847     if ((function & 0x001f003f) == 0x0000000d) {
1848     if (cpu->machine->instruction_trace || unassemble_only)
1849     debug("trunc.w.%i\tr%i,r%i\n", fmt, fd, fs);
1850     if (unassemble_only)
1851     return 1;
1852    
1853     /* TODO: not CVT? */
1854    
1855     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_W);
1856     return 1;
1857     }
1858    
1859     /* c.cond.fmt: Floating-point compare */
1860     if ((function & 0x000000f0) == 0x00000030) {
1861     int cond_true;
1862     int bit;
1863    
1864     if (cpu->machine->instruction_trace || unassemble_only)
1865     debug("c.%i.%i\tr%i,r%i,r%i\n", cond, fmt, cc, fs, ft);
1866     if (unassemble_only)
1867     return 1;
1868    
1869     cond_true = fpu_op(cpu, cp, FPU_OP_C, fmt,
1870     ft, fs, -1, cond, fmt);
1871    
1872     /*
1873     * Both the FCCR and FCSR contain condition code bits:
1874     * FCCR: bits 7..0
1875     * FCSR: bits 31..25 and 23
1876     */
1877     cp->fcr[FPU_FCCR] &= ~(1 << cc);
1878     if (cond_true)
1879     cp->fcr[FPU_FCCR] |= (1 << cc);
1880    
1881     if (cc == 0) {
1882     bit = 1 << FCSR_FCC0_SHIFT;
1883     cp->fcr[FPU_FCSR] &= ~bit;
1884     if (cond_true)
1885     cp->fcr[FPU_FCSR] |= bit;
1886     } else {
1887     bit = 1 << (FCSR_FCC1_SHIFT + cc-1);
1888     cp->fcr[FPU_FCSR] &= ~bit;
1889     if (cond_true)
1890     cp->fcr[FPU_FCSR] |= bit;
1891     }
1892    
1893     return 1;
1894     }
1895    
1896     /* cvt.s.fmt: Convert to single floating-point */
1897     if ((function & 0x001f003f) == 0x00000020) {
1898     if (cpu->machine->instruction_trace || unassemble_only)
1899     debug("cvt.s.%i\tr%i,r%i\n", fmt, fd, fs);
1900     if (unassemble_only)
1901     return 1;
1902    
1903     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_S);
1904     return 1;
1905     }
1906    
1907     /* cvt.d.fmt: Convert to double floating-point */
1908     if ((function & 0x001f003f) == 0x00000021) {
1909     if (cpu->machine->instruction_trace || unassemble_only)
1910     debug("cvt.d.%i\tr%i,r%i\n", fmt, fd, fs);
1911     if (unassemble_only)
1912     return 1;
1913    
1914     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_D);
1915     return 1;
1916     }
1917    
1918     /* cvt.w.fmt: Convert to word fixed-point */
1919     if ((function & 0x001f003f) == 0x00000024) {
1920     if (cpu->machine->instruction_trace || unassemble_only)
1921     debug("cvt.w.%i\tr%i,r%i\n", fmt, fd, fs);
1922     if (unassemble_only)
1923     return 1;
1924    
1925     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_W);
1926     return 1;
1927     }
1928    
1929     return 0;
1930     }
1931    
1932    
1933     /*
1934     * coproc_tlbpr():
1935     *
1936     * 'tlbp' and 'tlbr'.
1937     */
1938     void coproc_tlbpr(struct cpu *cpu, int readflag)
1939     {
1940     struct mips_coproc *cp = cpu->cd.mips.coproc[0];
1941     int i, found, g_bit;
1942     uint64_t vpn2, xmask;
1943    
1944     /* Read: */
1945     if (readflag) {
1946     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1947     i = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK) >>
1948     R2K3K_INDEX_SHIFT;
1949     if (i >= cp->nr_of_tlbs) {
1950     /* TODO: exception? */
1951     fatal("warning: tlbr from index %i (too "
1952     "high)\n", i);
1953     return;
1954     }
1955    
1956     /*
1957     * TODO: Hm. Earlier I had an & ~0x3f on the high
1958     * assignment and an & ~0xff on the lo0 assignment.
1959     * I wonder why.
1960     */
1961    
1962     cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi; /* & ~0x3f; */
1963     cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;/* & ~0xff; */
1964     } else {
1965     /* R4000: */
1966     i = cp->reg[COP0_INDEX] & INDEX_MASK;
1967     if (i >= cp->nr_of_tlbs) /* TODO: exception */
1968     return;
1969    
1970     cp->reg[COP0_PAGEMASK] = cp->tlbs[i].mask;
1971     cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi;
1972     cp->reg[COP0_ENTRYLO1] = cp->tlbs[i].lo1;
1973     cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;
1974    
1975     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1976     /* R4100 don't have the G bit in entryhi */
1977     } else {
1978     /* R4000 etc: */
1979     cp->reg[COP0_ENTRYHI] &= ~TLB_G;
1980     g_bit = cp->tlbs[i].hi & TLB_G;
1981    
1982     cp->reg[COP0_ENTRYLO0] &= ~ENTRYLO_G;
1983     cp->reg[COP0_ENTRYLO1] &= ~ENTRYLO_G;
1984     if (g_bit) {
1985     cp->reg[COP0_ENTRYLO0] |= ENTRYLO_G;
1986     cp->reg[COP0_ENTRYLO1] |= ENTRYLO_G;
1987     }
1988     }
1989     }
1990    
1991     return;
1992     }
1993    
1994     /* Probe: */
1995     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1996     vpn2 = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
1997     found = -1;
1998     for (i=0; i<cp->nr_of_tlbs; i++)
1999     if ( ((cp->tlbs[i].hi & R2K3K_ENTRYHI_ASID_MASK) ==
2000     (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK))
2001     || cp->tlbs[i].lo0 & R2K3K_ENTRYLO_G)
2002     if ((cp->tlbs[i].hi & R2K3K_ENTRYHI_VPN_MASK)
2003     == vpn2) {
2004     found = i;
2005     break;
2006     }
2007     } else {
2008     /* R4000 and R10000: */
2009     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
2010     xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K;
2011     else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
2012     xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800;
2013     else
2014     xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK;
2015     vpn2 = cp->reg[COP0_ENTRYHI] & xmask;
2016     found = -1;
2017     for (i=0; i<cp->nr_of_tlbs; i++) {
2018     int gbit = cp->tlbs[i].hi & TLB_G;
2019     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
2020     gbit = (cp->tlbs[i].lo0 & ENTRYLO_G) &&
2021     (cp->tlbs[i].lo1 & ENTRYLO_G);
2022    
2023     if ( ((cp->tlbs[i].hi & ENTRYHI_ASID) ==
2024     (cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID)) || gbit) {
2025     uint64_t a = vpn2 & ~cp->tlbs[i].mask;
2026     uint64_t b = (cp->tlbs[i].hi & xmask) &
2027     ~cp->tlbs[i].mask;
2028     if (a == b) {
2029     found = i;
2030     break;
2031     }
2032     }
2033     }
2034     }
2035     if (found == -1)
2036     cp->reg[COP0_INDEX] = INDEX_P;
2037     else {
2038     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
2039     cp->reg[COP0_INDEX] = found << R2K3K_INDEX_SHIFT;
2040     else
2041     cp->reg[COP0_INDEX] = found;
2042     }
2043    
2044     /* Sign extend the index register: */
2045     if ((cp->reg[COP0_INDEX] >> 32) == 0 &&
2046     cp->reg[COP0_INDEX] & 0x80000000)
2047     cp->reg[COP0_INDEX] |=
2048     0xffffffff00000000ULL;
2049     }
2050    
2051    
2052     /*
2053     * coproc_tlbwri():
2054     *
2055     * 'tlbwr' and 'tlbwi'
2056     */
2057     void coproc_tlbwri(struct cpu *cpu, int randomflag)
2058     {
2059     struct mips_coproc *cp = cpu->cd.mips.coproc[0];
2060     int index, g_bit;
2061     uint64_t oldvaddr;
2062     int old_asid = -1;
2063    
2064     /*
2065     * ... and the last instruction page:
2066     *
2067     * Some thoughts about this: Code running in
2068     * the kernel's physical address space has the
2069     * same vaddr->paddr translation, so the last
2070     * virtual page invalidation only needs to
2071     * happen if we are for some extremely weird
2072     * reason NOT running in the kernel's physical
2073     * address space.
2074     *
2075     * (An even insaner (but probably useless)
2076     * optimization would be to only invalidate
2077     * the last virtual page stuff if the TLB
2078     * update actually affects the vaddr in
2079     * question.)
2080     */
2081    
2082     if (cpu->pc < (uint64_t)0xffffffff80000000ULL ||
2083     cpu->pc >= (uint64_t)0xffffffffc0000000ULL)
2084     cpu->cd.mips.pc_last_virtual_page =
2085     PC_LAST_PAGE_IMPOSSIBLE_VALUE;
2086    
2087     if (randomflag) {
2088     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
2089     index = (cp->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
2090     >> R2K3K_RANDOM_SHIFT;
2091     else
2092     index = cp->reg[COP0_RANDOM] & RANDOM_MASK;
2093     } else {
2094     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
2095     index = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
2096     >> R2K3K_INDEX_SHIFT;
2097     else
2098     index = cp->reg[COP0_INDEX] & INDEX_MASK;
2099     }
2100    
2101     if (index >= cp->nr_of_tlbs) {
2102     fatal("warning: tlb index %i too high (max is %i)\n",
2103     index, cp->nr_of_tlbs - 1);
2104     /* TODO: cause an exception? */
2105     return;
2106     }
2107    
2108     #if 0
2109     /* Debug dump of the previous entry at that index: */
2110     debug(" old entry at index = %04x", index);
2111     debug(" mask = %016llx", (long long) cp->tlbs[index].mask);
2112     debug(" hi = %016llx", (long long) cp->tlbs[index].hi);
2113     debug(" lo0 = %016llx", (long long) cp->tlbs[index].lo0);
2114     debug(" lo1 = %016llx\n", (long long) cp->tlbs[index].lo1);
2115     #endif
2116    
2117     /* Translation caches must be invalidated: */
2118     switch (cpu->cd.mips.cpu_type.mmu_model) {
2119     case MMU3K:
2120     oldvaddr = cp->tlbs[index].hi & R2K3K_ENTRYHI_VPN_MASK;
2121     oldvaddr &= 0xffffffffULL;
2122     if (oldvaddr & 0x80000000ULL)
2123     oldvaddr |= 0xffffffff00000000ULL;
2124     old_asid = (cp->tlbs[index].hi & R2K3K_ENTRYHI_ASID_MASK)
2125     >> R2K3K_ENTRYHI_ASID_SHIFT;
2126    
2127     /* TODO: Bug? Why does this if need to be commented out? */
2128    
2129     /* if (cp->tlbs[index].lo0 & ENTRYLO_V) */
2130     invalidate_translation_caches(cpu, 0, oldvaddr, 0, 0);
2131     break;
2132     default:
2133     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
2134     oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;
2135     /* 44 addressable bits: */
2136     if (oldvaddr & 0x80000000000ULL)
2137     oldvaddr |= 0xfffff00000000000ULL;
2138     } else {
2139     /* Assume MMU4K */
2140     oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
2141     /* 40 addressable bits: */
2142     if (oldvaddr & 0x8000000000ULL)
2143     oldvaddr |= 0xffffff0000000000ULL;
2144     }
2145    
2146     /*
2147     * Both pages:
2148     *
2149     * TODO: non-4KB page sizes!
2150     */
2151     invalidate_translation_caches(
2152     cpu, 0, oldvaddr & ~0x1fff, 0, 0);
2153     invalidate_translation_caches(
2154     cpu, 0, (oldvaddr & ~0x1fff) | 0x1000, 0, 0);
2155     }
2156    
2157    
2158     /*
2159     * Check for duplicate entries. (There should not be two mappings
2160     * from one virtual address to physical addresses.)
2161     *
2162     * TODO: Do this for MMU3K and R4100 too.
2163     *
2164     * TODO: Make this detection more robust.
2165     */
2166     if (cpu->cd.mips.cpu_type.mmu_model != MMU3K &&
2167     cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
2168     uint64_t vaddr1, vaddr2;
2169 dpavlin 22 int i;
2170     unsigned int asid;
2171 dpavlin 14
2172     vaddr1 = cp->reg[COP0_ENTRYHI] & ENTRYHI_VPN2_MASK_R10K;
2173     asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
2174     /* Since this is just a warning, it's probably not necessary
2175     to use R4000 masks etc. */
2176    
2177     for (i=0; i<cp->nr_of_tlbs; i++) {
2178     if (i == index && !randomflag)
2179     continue;
2180    
2181     if (!(cp->tlbs[i].hi & TLB_G) &&
2182     (cp->tlbs[i].hi & ENTRYHI_ASID) != asid)
2183     continue;
2184    
2185     vaddr2 = cp->tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
2186     if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 &
2187     ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V)))
2188     fatal("\n[ WARNING! tlbw%s to index 0x%02x "
2189     "vaddr=0x%llx (asid 0x%02x) is already in"
2190     " the TLB (entry 0x%02x) ! ]\n\n",
2191     randomflag? "r" : "i", index,
2192     (long long)vaddr1, asid, i);
2193     }
2194     }
2195    
2196    
2197     /* Write the new entry: */
2198    
2199     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
2200     uint64_t vaddr, paddr;
2201     int wf = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_D? 1 : 0;
2202     unsigned char *memblock = NULL;
2203    
2204     cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
2205     cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
2206    
2207     vaddr = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
2208     paddr = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_PFN_MASK;
2209    
2210     /* TODO: This is ugly. */
2211     if (paddr < 0x10000000)
2212     memblock = memory_paddr_to_hostaddr(
2213     cpu->mem, paddr, 1);
2214    
2215     if (memblock != NULL &&
2216     cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_V) {
2217     memblock += (paddr & ((1 << BITS_PER_PAGETABLE) - 1));
2218    
2219     /*
2220     * TODO: Hahaha, this is even uglier than the thing
2221     * above. Some OSes seem to map code pages read/write,
2222     * which causes the bintrans cache to be invalidated
2223     * even when it doesn't have to be.
2224     */
2225     /* if (vaddr < 0x10000000) */
2226     wf = 0;
2227    
2228     cpu->update_translation_table(cpu, vaddr, memblock,
2229     wf, paddr);
2230     }
2231     } else {
2232     /* R4000: */
2233     g_bit = (cp->reg[COP0_ENTRYLO0] &
2234     cp->reg[COP0_ENTRYLO1]) & ENTRYLO_G;
2235     cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];
2236     cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
2237     cp->tlbs[index].lo1 = cp->reg[COP0_ENTRYLO1];
2238     cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
2239    
2240     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
2241     /* NOTE: The VR4131 (and possibly others) don't have
2242     a Global bit in entryhi */
2243     cp->tlbs[index].hi &= ~cp->reg[COP0_PAGEMASK];
2244     } else {
2245     cp->tlbs[index].lo0 &= ~ENTRYLO_G;
2246     cp->tlbs[index].lo1 &= ~ENTRYLO_G;
2247    
2248     cp->tlbs[index].hi &= ~TLB_G;
2249     if (g_bit)
2250     cp->tlbs[index].hi |= TLB_G;
2251     }
2252     }
2253    
2254     if (randomflag) {
2255     if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
2256     cp->reg[COP0_RANDOM] =
2257     ((random() % (cp->nr_of_tlbs - 8)) + 8)
2258     << R2K3K_RANDOM_SHIFT;
2259     } else {
2260     cp->reg[COP0_RANDOM] = cp->reg[COP0_WIRED] + (random()
2261     % (cp->nr_of_tlbs - cp->reg[COP0_WIRED]));
2262     }
2263     }
2264     }
2265    
2266    
2267     /*
2268     * coproc_rfe():
2269     *
2270     * Return from exception. (R3000 etc.)
2271     */
2272     void coproc_rfe(struct cpu *cpu)
2273     {
2274     int oldmode;
2275    
2276     oldmode = cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS1_SR_KU_CUR;
2277    
2278     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2279     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
2280     ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
2281    
2282     /* Changing from kernel to user mode? Then this is necessary: */
2283     if (!oldmode &&
2284     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &
2285     MIPS1_SR_KU_CUR))
2286     invalidate_translation_caches(cpu, 0, 0, 1, 0);
2287     }
2288    
2289    
2290     /*
2291     * coproc_eret():
2292     *
2293     * Return from exception. (R4000 etc.)
2294     */
2295     void coproc_eret(struct cpu *cpu)
2296     {
2297     int oldmode, newmode;
2298    
2299     /* Kernel mode flag: */
2300     oldmode = 0;
2301     if ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS3_SR_KSU_MASK)
2302     != MIPS3_SR_KSU_USER
2303     || (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & (STATUS_EXL |
2304     STATUS_ERL)) ||
2305     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 1) == 0)
2306     oldmode = 1;
2307    
2308     if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2309     cpu->pc = cpu->cd.mips.pc_last =
2310     cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2311     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
2312     } else {
2313     cpu->pc = cpu->cd.mips.pc_last =
2314     cpu->cd.mips.coproc[0]->reg[COP0_EPC];
2315     cpu->cd.mips.delay_slot = 0;
2316     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2317     }
2318    
2319     cpu->cd.mips.rmw = 0; /* the "LL bit" */
2320    
2321     /* New kernel mode flag: */
2322     newmode = 0;
2323     if ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS3_SR_KSU_MASK)
2324     != MIPS3_SR_KSU_USER
2325     || (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & (STATUS_EXL |
2326     STATUS_ERL)) ||
2327     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 1) == 0)
2328     newmode = 1;
2329    
2330     #if 0
2331     /* Changing from kernel to user mode?
2332     Then this is necessary: TODO */
2333     if (oldmode && !newmode)
2334     invalidate_translation_caches(cpu, 0, 0, 1, 0);
2335     #endif
2336     }
2337    
2338    
2339     /*
2340     * coproc_function():
2341     *
2342     * Execute a coprocessor specific instruction. cp must be != NULL.
2343     * Debug trace should be printed for known instructions, if
2344     * unassemble_only is non-zero. (This will NOT execute the instruction.)
2345     *
2346     * TODO: This is a mess and should be restructured (again).
2347     */
2348     void coproc_function(struct cpu *cpu, struct mips_coproc *cp, int cpnr,
2349     uint32_t function, int unassemble_only, int running)
2350     {
2351     int co_bit, op, rt, rd, fs, copz;
2352     uint64_t tmpvalue;
2353    
2354     if (cp == NULL) {
2355     if (unassemble_only) {
2356     debug("cop%i\t0x%08x (coprocessor not available)\n",
2357     cpnr, (int)function);
2358     return;
2359     }
2360     fatal("[ pc=0x%016llx cop%i\t0x%08x (coprocessor not "
2361     "available)\n", (long long)cpu->pc, cpnr, (int)function);
2362     return;
2363     }
2364    
2365     #if 0
2366     /* No FPU? */
2367     if (cpnr == 1 && (cpu->cd.mips.cpu_type.flags & NOFPU)) {
2368     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2369     return;
2370     }
2371     #endif
2372    
2373     /* For quick reference: */
2374     copz = (function >> 21) & 31;
2375     rt = (function >> 16) & 31;
2376     rd = (function >> 11) & 31;
2377    
2378     if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21))
2379     || ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) {
2380     if (unassemble_only) {
2381     debug("%s%i\t%s,", copz==COPz_DMFCz? "dmfc" : "mfc",
2382     cpnr, regnames[rt]);
2383     if (cpnr == 0)
2384     debug("%s", cop0_names[rd]);
2385     else
2386     debug("cpreg%i", rd);
2387     if (function & 7)
2388     debug(",%i", (int)(function & 7));
2389     debug("\n");
2390     return;
2391     }
2392     coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr],
2393     rd, &tmpvalue, function & 7);
2394     cpu->cd.mips.gpr[rt] = tmpvalue;
2395     if (copz == COPz_MFCz) {
2396     /* Sign-extend: */
2397     cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
2398     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
2399     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
2400     }
2401     return;
2402     }
2403    
2404     if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21))
2405     || ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) {
2406     if (unassemble_only) {
2407     debug("%s%i\t%s,", copz==COPz_DMTCz? "dmtc" : "mtc",
2408     cpnr, regnames[rt]);
2409     if (cpnr == 0)
2410     debug("%s", cop0_names[rd]);
2411     else
2412     debug("cpreg%i", rd);
2413     if (function & 7)
2414     debug(",%i", (int)(function & 7));
2415     debug("\n");
2416     return;
2417     }
2418     tmpvalue = cpu->cd.mips.gpr[rt];
2419     if (copz == COPz_MTCz) {
2420     /* Sign-extend: */
2421     tmpvalue &= 0xffffffffULL;
2422     if (tmpvalue & 0x80000000ULL)
2423     tmpvalue |= 0xffffffff00000000ULL;
2424     }
2425     coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd,
2426     &tmpvalue, copz == COPz_DMTCz, function & 7);
2427     return;
2428     }
2429    
2430     if (cpnr <= 1 && (((function & 0x03e007ff) == (COPz_CFCz << 21))
2431     || ((function & 0x03e007ff) == (COPz_CTCz << 21)))) {
2432     switch (copz) {
2433     case COPz_CFCz: /* Copy from FPU control register */
2434     rt = (function >> 16) & 31;
2435     fs = (function >> 11) & 31;
2436     if (unassemble_only) {
2437     debug("cfc%i\t%s,r%i\n", cpnr,
2438     regnames[rt], fs);
2439     return;
2440     }
2441     cpu->cd.mips.gpr[rt] = cp->fcr[fs] & 0xffffffffULL;
2442     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
2443     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
2444     /* TODO: implement delay for gpr[rt]
2445     (for MIPS I,II,III only) */
2446     return;
2447     case COPz_CTCz: /* Copy to FPU control register */
2448     rt = (function >> 16) & 31;
2449     fs = (function >> 11) & 31;
2450     if (unassemble_only) {
2451     debug("ctc%i\t%s,r%i\n", cpnr,
2452     regnames[rt], fs);
2453     return;
2454     }
2455    
2456     switch (cpnr) {
2457     case 0: /* System coprocessor */
2458     fatal("[ warning: unimplemented ctc%i, "
2459     "0x%08x -> ctl reg %i ]\n", cpnr,
2460     (int)cpu->cd.mips.gpr[rt], fs);
2461     break;
2462     case 1: /* FPU */
2463     if (fs == 0)
2464     fatal("[ Attempt to write to FPU "
2465     "control register 0 (?) ]\n");
2466     else {
2467     uint64_t tmp = cpu->cd.mips.gpr[rt];
2468     cp->fcr[fs] = tmp;
2469    
2470     /* TODO: writing to control register 31
2471     should cause exceptions, depending
2472     on status bits! */
2473    
2474     switch (fs) {
2475     case FPU_FCCR:
2476     cp->fcr[FPU_FCSR] =
2477     (cp->fcr[FPU_FCSR] &
2478     0x017fffffULL) | ((tmp & 1)
2479     << FCSR_FCC0_SHIFT)
2480     | (((tmp & 0xfe) >> 1) <<
2481     FCSR_FCC1_SHIFT);
2482     break;
2483     case FPU_FCSR:
2484     cp->fcr[FPU_FCCR] =
2485     (cp->fcr[FPU_FCCR] &
2486     0xffffff00ULL) | ((tmp >>
2487     FCSR_FCC0_SHIFT) & 1) |
2488     (((tmp >> FCSR_FCC1_SHIFT)
2489     & 0x7f) << 1);
2490     break;
2491     default:
2492     ;
2493     }
2494     }
2495     break;
2496     }
2497    
2498     /* TODO: implement delay for gpr[rt]
2499     (for MIPS I,II,III only) */
2500     return;
2501     default:
2502     ;
2503     }
2504     }
2505    
2506     /* Math (Floating point) coprocessor calls: */
2507     if (cpnr==1) {
2508     if (fpu_function(cpu, cp, function, unassemble_only))
2509     return;
2510     }
2511    
2512     /* For AU1500 and probably others: deret */
2513     if (function == 0x0200001f) {
2514     if (unassemble_only) {
2515     debug("deret\n");
2516     return;
2517     }
2518    
2519     /*
2520     * According to the MIPS64 manual, deret loads PC from the
2521     * DEPC cop0 register, and jumps there immediately. No
2522     * delay slot.
2523     *
2524     * TODO: This instruction is only available if the processor
2525     * is in debug mode. (What does that mean?)
2526     * TODO: This instruction is undefined in a delay slot.
2527     */
2528    
2529     cpu->pc = cpu->cd.mips.pc_last = cp->reg[COP0_DEPC];
2530     cpu->cd.mips.delay_slot = 0;
2531     cp->reg[COP0_STATUS] &= ~STATUS_EXL;
2532    
2533     return;
2534     }
2535    
2536    
2537     /* Ugly R5900 hacks: */
2538     if ((function & 0xfffff) == 0x38) { /* ei */
2539     if (unassemble_only) {
2540     debug("ei\n");
2541     return;
2542     }
2543     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2544     return;
2545     }
2546    
2547     if ((function & 0xfffff) == 0x39) { /* di */
2548     if (unassemble_only) {
2549     debug("di\n");
2550     return;
2551     }
2552     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2553     return;
2554     }
2555    
2556     co_bit = (function >> 25) & 1;
2557    
2558     /* TLB operations and other things: */
2559     if (cp->coproc_nr == 0) {
2560     op = (function) & 0xff;
2561     switch (co_bit) {
2562     case 1:
2563     switch (op) {
2564     case COP0_TLBR: /* Read indexed TLB entry */
2565     if (unassemble_only) {
2566     debug("tlbr\n");
2567     return;
2568     }
2569     coproc_tlbpr(cpu, 1);
2570     return;
2571     case COP0_TLBWI: /* Write indexed */
2572     case COP0_TLBWR: /* Write random */
2573     if (unassemble_only) {
2574     if (op == COP0_TLBWI)
2575     debug("tlbwi");
2576     else
2577     debug("tlbwr");
2578     if (!running) {
2579     debug("\n");
2580     return;
2581     }
2582     debug("\tindex=%08llx",
2583     (long long)cp->reg[COP0_INDEX]);
2584     debug(", random=%08llx",
2585     (long long)cp->reg[COP0_RANDOM]);
2586     debug(", mask=%016llx",
2587     (long long)cp->reg[COP0_PAGEMASK]);
2588     debug(", hi=%016llx",
2589     (long long)cp->reg[COP0_ENTRYHI]);
2590     debug(", lo0=%016llx",
2591     (long long)cp->reg[COP0_ENTRYLO0]);
2592     debug(", lo1=%016llx\n",
2593     (long long)cp->reg[COP0_ENTRYLO1]);
2594     }
2595     coproc_tlbwri(cpu, op == COP0_TLBWR);
2596     return;
2597     case COP0_TLBP: /* Probe TLB for
2598     matching entry */
2599     if (unassemble_only) {
2600     debug("tlbp\n");
2601     return;
2602     }
2603     coproc_tlbpr(cpu, 0);
2604     return;
2605     case COP0_RFE: /* R2000/R3000 only:
2606     Return from Exception */
2607     if (unassemble_only) {
2608     debug("rfe\n");
2609     return;
2610     }
2611     coproc_rfe(cpu);
2612     return;
2613     case COP0_ERET: /* R4000: Return from exception */
2614     if (unassemble_only) {
2615     debug("eret\n");
2616     return;
2617     }
2618     coproc_eret(cpu);
2619     return;
2620     case COP0_STANDBY:
2621     if (unassemble_only) {
2622     debug("standby\n");
2623     return;
2624     }
2625     /* TODO: Hm. Do something here? */
2626     return;
2627     case COP0_SUSPEND:
2628     if (unassemble_only) {
2629     debug("suspend\n");
2630     return;
2631     }
2632     /* TODO: Hm. Do something here? */
2633     return;
2634     case COP0_HIBERNATE:
2635     if (unassemble_only) {
2636     debug("hibernate\n");
2637     return;
2638     }
2639     /* TODO: Hm. Do something here? */
2640     return;
2641     default:
2642     ;
2643     }
2644     default:
2645     ;
2646     }
2647     }
2648    
2649     /* TODO: coprocessor R2020 on DECstation? */
2650     if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x0100ffff) {
2651     if (unassemble_only) {
2652     debug("decstation_r2020_writeback\n");
2653     return;
2654     }
2655     /* TODO */
2656     return;
2657     }
2658    
2659     /* TODO: RM5200 idle (?) */
2660     if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x02000020) {
2661     if (unassemble_only) {
2662     debug("idle(?)\n"); /* TODO */
2663     return;
2664     }
2665    
2666     /* Idle? TODO */
2667     return;
2668     }
2669    
2670     if (unassemble_only) {
2671     debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);
2672     return;
2673     }
2674    
2675     fatal("cpu%i: UNIMPLEMENTED coproc%i function %08lx "
2676     "(pc = %016llx)\n", cpu->cpu_id, cp->coproc_nr, function,
2677     (long long)cpu->cd.mips.pc_last);
2678     #if 1
2679     single_step = 1;
2680     #else
2681     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0);
2682     #endif
2683     }
2684    
2685     #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26