/[gxemul]/upstream/0.3.3.2/src/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 /upstream/0.3.3.2/src/cpu_mips_coproc.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26