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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26