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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (hide annotations)
Mon Oct 8 16:17:52 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 74915 byte(s)
0.3.1
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     * $Id: cpu_mips_coproc.c,v 1.11 2005/03/15 06:52:14 debug Exp $
29     *
30     * Emulation of MIPS coprocessors.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <math.h>
37    
38     #include "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     for (b=0; b<0x400; b++)
688     tbl1->bintrans_chunks[b] = NULL;
689     }
690     }
691     }
692     #endif
693    
694    
695     /*
696     * mips_invalidate_translation_caches_paddr():
697     *
698     * Invalidate based on physical address.
699     */
700     void mips_invalidate_translation_caches_paddr(struct cpu *cpu, uint64_t paddr)
701     {
702     #ifdef BINTRANS
703     paddr &= ~0xfff;
704    
705     if (cpu->machine->bintrans_enable) {
706     #if 1
707     int i;
708     uint64_t tlb_paddr0, tlb_paddr1;
709     uint64_t tlb_vaddr;
710     uint64_t p, p2;
711    
712     switch (cpu->cd.mips.cpu_type.mmu_model) {
713     case MMU3K:
714     for (i=0; i<64; i++) {
715     tlb_paddr0 = cpu->cd.mips.coproc[0]->
716     tlbs[i].lo0 & R2K3K_ENTRYLO_PFN_MASK;
717     tlb_vaddr = cpu->cd.mips.coproc[0]->
718     tlbs[i].hi & R2K3K_ENTRYHI_VPN_MASK;
719     tlb_vaddr = (int64_t)(int32_t)tlb_vaddr;
720     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo0 &
721     R2K3K_ENTRYLO_V) && tlb_paddr0 == paddr)
722     invalidate_table_entry(cpu, tlb_vaddr);
723     }
724     break;
725     default:
726     for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
727     int psize = 12;
728     int or_pmask = 0x1fff;
729     int phys_shift = 12;
730    
731     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
732     or_pmask = 0x7ff;
733     phys_shift = 10;
734     }
735     switch (cpu->cd.mips.coproc[0]->
736     tlbs[i].mask | or_pmask) {
737     case 0x000007ff: psize = 10; break;
738     case 0x00001fff: psize = 12; break;
739     case 0x00007fff: psize = 14; break;
740     case 0x0001ffff: psize = 16; break;
741     case 0x0007ffff: psize = 18; break;
742     case 0x001fffff: psize = 20; break;
743     case 0x007fffff: psize = 22; break;
744     case 0x01ffffff: psize = 24; break;
745     case 0x07ffffff: psize = 26; break;
746     default:
747     printf("invalidate_translation_caches"
748     "_paddr(): bad pagemask?\n");
749     }
750     tlb_paddr0 = (cpu->cd.mips.coproc[0]->tlbs[i].
751     lo0 & ENTRYLO_PFN_MASK)>>ENTRYLO_PFN_SHIFT;
752     tlb_paddr1 = (cpu->cd.mips.coproc[0]->tlbs[i].
753     lo1 & ENTRYLO_PFN_MASK)>>ENTRYLO_PFN_SHIFT;
754     tlb_paddr0 <<= phys_shift;
755     tlb_paddr1 <<= phys_shift;
756     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
757     tlb_vaddr = cpu->cd.mips.coproc[0]->
758     tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
759     if (tlb_vaddr & ((int64_t)1 << 43))
760     tlb_vaddr |=
761     0xfffff00000000000ULL;
762     } else {
763     tlb_vaddr = cpu->cd.mips.coproc[0]->
764     tlbs[i].hi & ENTRYHI_VPN2_MASK;
765     if (tlb_vaddr & ((int64_t)1 << 39))
766     tlb_vaddr |=
767     0xffffff0000000000ULL;
768     }
769     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo0 &
770     ENTRYLO_V) && paddr >= tlb_paddr0 &&
771     paddr < tlb_paddr0 + (1<<psize)) {
772     p2 = 1 << psize;
773     for (p=0; p<p2; p+=4096)
774     invalidate_table_entry(cpu,
775     tlb_vaddr + p);
776     }
777     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo1 &
778     ENTRYLO_V) && paddr >= tlb_paddr1 &&
779     paddr < tlb_paddr1 + (1<<psize)) {
780     p2 = 1 << psize;
781     for (p=0; p<p2; p+=4096)
782     invalidate_table_entry(cpu,
783     tlb_vaddr + p +
784     (1 << psize));
785     }
786     }
787     }
788     #endif
789    
790     if (paddr < 0x20000000) {
791     invalidate_table_entry(cpu, 0xffffffff80000000ULL
792     + paddr);
793     invalidate_table_entry(cpu, 0xffffffffa0000000ULL
794     + paddr);
795     }
796     }
797    
798     #if 0
799     {
800     int i;
801    
802     /* TODO: Don't invalidate everything. */
803     for (i=0; i<N_BINTRANS_VADDR_TO_HOST; i++)
804     cpu->bintrans_data_hostpage[i] = NULL;
805     }
806     #endif
807    
808     #endif
809     }
810    
811    
812     /*
813     * invalidate_translation_caches():
814     *
815     * This is necessary for every change to the TLB, and when the ASID is changed,
816     * so that for example user-space addresses are not cached when they should
817     * not be.
818     */
819     static void invalidate_translation_caches(struct cpu *cpu,
820     int all, uint64_t vaddr, int kernelspace, int old_asid_to_invalidate)
821     {
822     int i;
823    
824     /* printf("inval(all=%i, kernel=%i, addr=%016llx)\n",
825     all, kernelspace, (long long)vaddr); */
826    
827     #ifdef BINTRANS
828     if (!cpu->machine->bintrans_enable)
829     goto nobintrans;
830    
831     if (all) {
832     int i;
833     uint64_t tlb_vaddr;
834     switch (cpu->cd.mips.cpu_type.mmu_model) {
835     case MMU3K:
836     for (i=0; i<64; i++) {
837     tlb_vaddr = cpu->cd.mips.coproc[0]->tlbs[i].hi
838     & R2K3K_ENTRYHI_VPN_MASK;
839     tlb_vaddr = (int64_t)(int32_t)tlb_vaddr;
840     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo0 &
841     R2K3K_ENTRYLO_V) && (tlb_vaddr &
842     0xc0000000ULL) != 0x80000000ULL) {
843     int asid = (cpu->cd.mips.coproc[0]->
844     tlbs[i].hi & R2K3K_ENTRYHI_ASID_MASK
845     ) >> R2K3K_ENTRYHI_ASID_SHIFT;
846     if (old_asid_to_invalidate < 0 ||
847     old_asid_to_invalidate == asid)
848     invalidate_table_entry(cpu,
849     tlb_vaddr);
850     }
851     }
852     break;
853     default:
854     for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
855     int psize = 10, or_pmask = 0x1fff;
856     int phys_shift = 12;
857    
858     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
859     or_pmask = 0x7ff;
860     phys_shift = 10;
861     }
862    
863     switch (cpu->cd.mips.coproc[0]->tlbs[i].mask
864     | or_pmask) {
865     case 0x000007ff: psize = 10; break;
866     case 0x00001fff: psize = 12; break;
867     case 0x00007fff: psize = 14; break;
868     case 0x0001ffff: psize = 16; break;
869     case 0x0007ffff: psize = 18; break;
870     case 0x001fffff: psize = 20; break;
871     case 0x007fffff: psize = 22; break;
872     case 0x01ffffff: psize = 24; break;
873     case 0x07ffffff: psize = 26; break;
874     default:
875     printf("invalidate_translation_caches"
876     "(): bad pagemask?\n");
877     }
878    
879     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
880     tlb_vaddr = cpu->cd.mips.coproc[0]->
881     tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
882     if (tlb_vaddr & ((int64_t)1 << 43))
883     tlb_vaddr |=
884     0xfffff00000000000ULL;
885     } else {
886     tlb_vaddr = cpu->cd.mips.coproc[0]->
887     tlbs[i].hi & ENTRYHI_VPN2_MASK;
888     if (tlb_vaddr & ((int64_t)1 << 39))
889     tlb_vaddr |=
890     0xffffff0000000000ULL;
891     }
892    
893     /* TODO: Check the ASID etc. */
894    
895     invalidate_table_entry(cpu, tlb_vaddr);
896     invalidate_table_entry(cpu, tlb_vaddr |
897     (1 << psize));
898     }
899     }
900     } else
901     invalidate_table_entry(cpu, vaddr);
902    
903     nobintrans:
904    
905     /* TODO: Don't invalidate everything. */
906     for (i=0; i<N_BINTRANS_VADDR_TO_HOST; i++)
907     cpu->cd.mips.bintrans_data_hostpage[i] = NULL;
908     #endif
909    
910     if (kernelspace)
911     all = 1;
912    
913     #ifdef USE_TINY_CACHE
914     {
915     vaddr >>= 12;
916    
917     /* Invalidate the tiny translation cache... */
918     if (!cpu->machine->bintrans_enable)
919     for (i=0; i<N_TRANSLATION_CACHE_INSTR; i++)
920     if (all || vaddr == (cpu->cd.mips.
921     translation_cache_instr[i].vaddr_pfn))
922     cpu->cd.mips.translation_cache_instr[i].wf = 0;
923    
924     if (!cpu->machine->bintrans_enable)
925     for (i=0; i<N_TRANSLATION_CACHE_DATA; i++)
926     if (all || vaddr == (cpu->cd.mips.
927     translation_cache_data[i].vaddr_pfn))
928     cpu->cd.mips.translation_cache_data[i].wf = 0;
929     }
930     #endif
931     }
932    
933    
934     /*
935     * coproc_register_read();
936     *
937     * Read a value from a MIPS coprocessor register.
938     */
939     void coproc_register_read(struct cpu *cpu,
940     struct mips_coproc *cp, int reg_nr, uint64_t *ptr)
941     {
942     int unimpl = 1;
943    
944     if (cp->coproc_nr==0 && reg_nr==COP0_INDEX) unimpl = 0;
945     if (cp->coproc_nr==0 && reg_nr==COP0_RANDOM) unimpl = 0;
946     if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO0) unimpl = 0;
947     if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO1) unimpl = 0;
948     if (cp->coproc_nr==0 && reg_nr==COP0_CONTEXT) unimpl = 0;
949     if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK) unimpl = 0;
950     if (cp->coproc_nr==0 && reg_nr==COP0_WIRED) unimpl = 0;
951     if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR) unimpl = 0;
952     if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) unimpl = 0;
953     if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI) unimpl = 0;
954     if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE) unimpl = 0;
955     if (cp->coproc_nr==0 && reg_nr==COP0_STATUS) unimpl = 0;
956     if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE) unimpl = 0;
957     if (cp->coproc_nr==0 && reg_nr==COP0_EPC) unimpl = 0;
958     if (cp->coproc_nr==0 && reg_nr==COP0_PRID) unimpl = 0;
959     if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG) unimpl = 0;
960     if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR) unimpl = 0;
961     if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO) unimpl = 0;
962     if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI) unimpl = 0;
963     if (cp->coproc_nr==0 && reg_nr==COP0_XCONTEXT) unimpl = 0;
964     if (cp->coproc_nr==0 && reg_nr==COP0_ERRCTL) unimpl = 0;
965     if (cp->coproc_nr==0 && reg_nr==COP0_CACHEERR) unimpl = 0;
966     if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_LO) unimpl = 0;
967     if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_HI) unimpl = 0;
968     if (cp->coproc_nr==0 && reg_nr==COP0_ERROREPC) unimpl = 0;
969     if (cp->coproc_nr==0 && reg_nr==COP0_RESERV22) {
970     /* Used by Linux on Linksys WRT54G */
971     unimpl = 0;
972     }
973     if (cp->coproc_nr==0 && reg_nr==COP0_DEBUG) unimpl = 0;
974     if (cp->coproc_nr==0 && reg_nr==COP0_PERFCNT) unimpl = 0;
975     if (cp->coproc_nr==0 && reg_nr==COP0_DESAVE) unimpl = 0;
976    
977     if (cp->coproc_nr==1) unimpl = 0;
978    
979     if (unimpl) {
980     fatal("cpu%i: warning: read from unimplemented coproc%i"
981     " register %i (%s)\n", cpu->cpu_id, cp->coproc_nr, reg_nr,
982     cp->coproc_nr==0? cop0_names[reg_nr] : "?");
983    
984     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
985     cp->coproc_nr, 0, 0, 0);
986     return;
987     }
988    
989     *ptr = cp->reg[reg_nr];
990     }
991    
992    
993     /*
994     * coproc_register_write();
995     *
996     * Write a value to a MIPS coprocessor register.
997     */
998     void coproc_register_write(struct cpu *cpu,
999     struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64)
1000     {
1001     int unimpl = 1;
1002     int readonly = 0;
1003     uint64_t tmp = *ptr;
1004     uint64_t tmp2 = 0, old;
1005     int inval = 0, old_asid, oldmode;
1006    
1007     switch (cp->coproc_nr) {
1008     case 0:
1009     /* COPROC 0: */
1010     switch (reg_nr) {
1011     case COP0_INDEX:
1012     case COP0_RANDOM:
1013     unimpl = 0;
1014     break;
1015     case COP0_ENTRYLO0:
1016     unimpl = 0;
1017     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
1018     (tmp & 0xff)!=0) {
1019     /* char *symbol;
1020     uint64_t offset;
1021     symbol = get_symbol_name(
1022     cpu->cd.mips.pc_last, &offset);
1023     fatal("YO! pc = 0x%08llx <%s> "
1024     "lo=%016llx\n", (long long)
1025     cpu->cd.mips.pc_last, symbol? symbol :
1026     "no symbol", (long long)tmp); */
1027     tmp &= (R2K3K_ENTRYLO_PFN_MASK |
1028     R2K3K_ENTRYLO_N | R2K3K_ENTRYLO_D |
1029     R2K3K_ENTRYLO_V | R2K3K_ENTRYLO_G);
1030     } else if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
1031     tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
1032     ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
1033     }
1034     break;
1035     case COP0_BADVADDR:
1036     /* Hm. Irix writes to this register. (Why?) */
1037     unimpl = 0;
1038     break;
1039     case COP0_ENTRYLO1:
1040     unimpl = 0;
1041     if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
1042     tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
1043     ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
1044     }
1045     break;
1046     case COP0_CONTEXT:
1047     old = cp->reg[COP0_CONTEXT];
1048     cp->reg[COP0_CONTEXT] = tmp;
1049     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1050     cp->reg[COP0_CONTEXT] &=
1051     ~R2K3K_CONTEXT_BADVPN_MASK;
1052     cp->reg[COP0_CONTEXT] |=
1053     (old & R2K3K_CONTEXT_BADVPN_MASK);
1054     } else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1055     cp->reg[COP0_CONTEXT] &=
1056     ~CONTEXT_BADVPN2_MASK_R4100;
1057     cp->reg[COP0_CONTEXT] |=
1058     (old & CONTEXT_BADVPN2_MASK_R4100);
1059     } else {
1060     cp->reg[COP0_CONTEXT] &=
1061     ~CONTEXT_BADVPN2_MASK;
1062     cp->reg[COP0_CONTEXT] |=
1063     (old & CONTEXT_BADVPN2_MASK);
1064     }
1065     return;
1066     case COP0_PAGEMASK:
1067     tmp2 = tmp >> PAGEMASK_SHIFT;
1068     if (tmp2 != 0x000 &&
1069     tmp2 != 0x003 &&
1070     tmp2 != 0x00f &&
1071     tmp2 != 0x03f &&
1072     tmp2 != 0x0ff &&
1073     tmp2 != 0x3ff &&
1074     tmp2 != 0xfff)
1075     fatal("cpu%i: trying to write an invalid"
1076     " pagemask 0x%08lx to COP0_PAGEMASK\n",
1077     cpu->cpu_id, (long)tmp);
1078     unimpl = 0;
1079     break;
1080     case COP0_WIRED:
1081     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1082     fatal("cpu%i: r2k/r3k wired register must "
1083     "always be 8\n", cpu->cpu_id);
1084     tmp = 8;
1085     }
1086     cp->reg[COP0_RANDOM] = cp->nr_of_tlbs-1;
1087     tmp &= INDEX_MASK;
1088     unimpl = 0;
1089     break;
1090     case COP0_COUNT:
1091     if (tmp != (int64_t)(int32_t)tmp)
1092     fatal("WARNING: trying to write a 64-bit value"
1093     " to the COUNT register!\n");
1094     tmp = (int64_t)(int32_t)tmp;
1095     unimpl = 0;
1096     break;
1097     case COP0_COMPARE:
1098     /* Clear the timer interrupt bit (bit 7): */
1099     cpu->cd.mips.compare_register_set = 1;
1100     mips_cpu_interrupt_ack(cpu, 7);
1101     if (tmp != (int64_t)(int32_t)tmp)
1102     fatal("WARNING: trying to write a 64-bit value"
1103     " to the COMPARE register!\n");
1104     tmp = (int64_t)(int32_t)tmp;
1105     unimpl = 0;
1106     break;
1107     case COP0_ENTRYHI:
1108     /*
1109     * Translation caches must be invalidated, because the
1110     * address space might change (if the ASID changes).
1111     */
1112     switch (cpu->cd.mips.cpu_type.mmu_model) {
1113     case MMU3K:
1114     old_asid = (cp->reg[COP0_ENTRYHI] &
1115     R2K3K_ENTRYHI_ASID_MASK) >>
1116     R2K3K_ENTRYHI_ASID_SHIFT;
1117     if ((cp->reg[COP0_ENTRYHI] &
1118     R2K3K_ENTRYHI_ASID_MASK) !=
1119     (tmp & R2K3K_ENTRYHI_ASID_MASK))
1120     inval = 1;
1121     break;
1122     default:
1123     old_asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
1124     if ((cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID) !=
1125     (tmp & ENTRYHI_ASID))
1126     inval = 1;
1127     break;
1128     }
1129     if (inval)
1130     invalidate_translation_caches(cpu, 1, 0, 0,
1131     old_asid);
1132     unimpl = 0;
1133     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
1134     (tmp & 0x3f)!=0) {
1135     /* char *symbol;
1136     uint64_t offset;
1137     symbol = get_symbol_name(cpu->
1138     cd.mips.pc_last, &offset);
1139     fatal("YO! pc = 0x%08llx <%s> "
1140     "hi=%016llx\n", (long long)cpu->
1141     cd.mips.pc_last, symbol? symbol :
1142     "no symbol", (long long)tmp); */
1143     tmp &= ~0x3f;
1144     }
1145     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1146     tmp &= (R2K3K_ENTRYHI_VPN_MASK |
1147     R2K3K_ENTRYHI_ASID_MASK);
1148     else if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1149     tmp &= (ENTRYHI_R_MASK |
1150     ENTRYHI_VPN2_MASK_R10K | ENTRYHI_ASID);
1151     else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
1152     tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
1153     0x1800 | ENTRYHI_ASID);
1154     else
1155     tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
1156     ENTRYHI_ASID);
1157     break;
1158     case COP0_EPC:
1159     unimpl = 0;
1160     break;
1161     case COP0_PRID:
1162     readonly = 1;
1163     break;
1164     case COP0_CONFIG:
1165     /* fatal("COP0_CONFIG: modifying K0 bits: "
1166     "0x%08x => ", cp->reg[reg_nr]); */
1167     tmp = *ptr;
1168     tmp &= 0x3; /* only bits 2..0 can be written */
1169     cp->reg[reg_nr] &= ~(0x3); cp->reg[reg_nr] |= tmp;
1170     /* fatal("0x%08x\n", cp->reg[reg_nr]); */
1171     return;
1172     case COP0_STATUS:
1173     oldmode = cp->reg[COP0_STATUS];
1174     tmp &= ~(1 << 21); /* bit 21 is read-only */
1175     /* Changing from kernel to user mode? Then
1176     invalidate some translation caches: */
1177     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1178     if (!(oldmode & MIPS1_SR_KU_CUR)
1179     && (tmp & MIPS1_SR_KU_CUR))
1180     invalidate_translation_caches(cpu,
1181     0, 0, 1, 0);
1182     } else {
1183     /* TODO: don't hardcode */
1184     if ((oldmode & 0xff) != (tmp & 0xff))
1185     invalidate_translation_caches(
1186     cpu, 0, 0, 1, 0);
1187     }
1188     unimpl = 0;
1189     break;
1190     case COP0_CAUSE:
1191     /* A write to the cause register only
1192     affects IM bits 0 and 1: */
1193     cp->reg[reg_nr] &= ~(0x3 << STATUS_IM_SHIFT);
1194     cp->reg[reg_nr] |= (tmp & (0x3 << STATUS_IM_SHIFT));
1195     if (!(cp->reg[COP0_CAUSE] & STATUS_IM_MASK))
1196     cpu->cd.mips.cached_interrupt_is_possible = 0;
1197     else
1198     cpu->cd.mips.cached_interrupt_is_possible = 1;
1199     return;
1200     case COP0_FRAMEMASK:
1201     /* TODO: R10000 */
1202     unimpl = 0;
1203     break;
1204     case COP0_TAGDATA_LO:
1205     case COP0_TAGDATA_HI:
1206     /* TODO: R4300 and others? */
1207     unimpl = 0;
1208     break;
1209     case COP0_LLADDR:
1210     unimpl = 0;
1211     break;
1212     case COP0_WATCHLO:
1213     case COP0_WATCHHI:
1214     unimpl = 0;
1215     break;
1216     case COP0_XCONTEXT:
1217     /*
1218     * TODO: According to the R10000 manual, the R4400
1219     * shares the PTEbase portion of the context registers
1220     * (that is, xcontext and context). On R10000, they
1221     * are separate registers.
1222     */
1223     /* debug("[ xcontext 0x%016llx ]\n", tmp); */
1224     unimpl = 0;
1225     break;
1226    
1227     /* Most of these are actually TODOs: */
1228     case COP0_ERROREPC:
1229     case COP0_DEPC:
1230     case COP0_RESERV22: /* Used by Linux on Linksys WRT54G */
1231     case COP0_DESAVE:
1232     case COP0_PERFCNT:
1233     case COP0_ERRCTL: /* R10000 */
1234     unimpl = 0;
1235     break;
1236     }
1237     break;
1238    
1239     case 1:
1240     /* COPROC 1: */
1241     unimpl = 0;
1242     break;
1243     }
1244    
1245     if (unimpl) {
1246     fatal("cpu%i: warning: write to unimplemented coproc%i "
1247     "register %i (%s), data = 0x%016llx\n", cpu->cpu_id,
1248     cp->coproc_nr, reg_nr, cp->coproc_nr==0?
1249     cop0_names[reg_nr] : "?", (long long)tmp);
1250    
1251     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
1252     cp->coproc_nr, 0, 0, 0);
1253     return;
1254     }
1255    
1256     if (readonly) {
1257     fatal("cpu%i: warning: write to READONLY coproc%i register "
1258     "%i ignored\n", cpu->cpu_id, cp->coproc_nr, reg_nr);
1259     return;
1260     }
1261    
1262     cp->reg[reg_nr] = tmp;
1263    
1264     if (!flag64)
1265     cp->reg[reg_nr] = (int64_t)(int32_t)cp->reg[reg_nr];
1266     }
1267    
1268    
1269     /*
1270     * MIPS floating-point stuff:
1271     *
1272     * TODO: Move this to some other file?
1273     */
1274     #define FMT_S 16
1275     #define FMT_D 17
1276     #define FMT_W 20
1277     #define FMT_L 21
1278     #define FMT_PS 22
1279    
1280     #define FPU_OP_ADD 1
1281     #define FPU_OP_SUB 2
1282     #define FPU_OP_MUL 3
1283     #define FPU_OP_DIV 4
1284     #define FPU_OP_SQRT 5
1285     #define FPU_OP_MOV 6
1286     #define FPU_OP_CVT 7
1287     #define FPU_OP_C 8
1288     #define FPU_OP_ABS 9
1289     #define FPU_OP_NEG 10
1290     /* TODO: CEIL.L, CEIL.W, FLOOR.L, FLOOR.W, RECIP, ROUND.L, ROUND.W,
1291     RSQRT */
1292    
1293    
1294     struct internal_float_value {
1295     double f;
1296     int nan;
1297     };
1298    
1299    
1300     /*
1301     * fpu_interpret_float_value():
1302     *
1303     * Interprets a float value from binary IEEE format into an
1304     * internal_float_value struct.
1305     */
1306     static void fpu_interpret_float_value(uint64_t reg,
1307     struct internal_float_value *fvp, int fmt)
1308     {
1309     int n_frac = 0, n_exp = 0;
1310     int i, nan, sign = 0, exponent;
1311     double fraction;
1312    
1313     memset(fvp, 0, sizeof(struct internal_float_value));
1314    
1315     /* n_frac and n_exp: */
1316     switch (fmt) {
1317     case FMT_S: n_frac = 23; n_exp = 8; break;
1318     case FMT_W: n_frac = 31; n_exp = 0; break;
1319     case FMT_D: n_frac = 52; n_exp = 11; break;
1320     case FMT_L: n_frac = 63; n_exp = 0; break;
1321     default:
1322     fatal("fpu_interpret_float_value(): "
1323     "unimplemented format %i\n", fmt);
1324     }
1325    
1326     /* exponent: */
1327     exponent = 0;
1328     switch (fmt) {
1329     case FMT_W:
1330     reg &= 0xffffffffULL;
1331     case FMT_L:
1332     break;
1333     case FMT_S:
1334     reg &= 0xffffffffULL;
1335     case FMT_D:
1336     exponent = (reg >> n_frac) & ((1 << n_exp) - 1);
1337     exponent -= (1 << (n_exp-1)) - 1;
1338     break;
1339     default:
1340     fatal("fpu_interpret_float_value(): unimplemented "
1341     "format %i\n", fmt);
1342     }
1343    
1344     /* nan: */
1345     nan = 0;
1346     switch (fmt) {
1347     case FMT_S:
1348     if (reg == 0x7fffffffULL || reg == 0x7fbfffffULL)
1349     nan = 1;
1350     break;
1351     case FMT_D:
1352     if (reg == 0x7fffffffffffffffULL ||
1353     reg == 0x7ff7ffffffffffffULL)
1354     nan = 1;
1355     break;
1356     }
1357    
1358     if (nan) {
1359     fvp->f = 1.0;
1360     goto no_reasonable_result;
1361     }
1362    
1363     /* fraction: */
1364     fraction = 0.0;
1365     switch (fmt) {
1366     case FMT_W:
1367     {
1368     int32_t r_int = reg;
1369     fraction = r_int;
1370     }
1371     break;
1372     case FMT_L:
1373     {
1374     int64_t r_int = reg;
1375     fraction = r_int;
1376     }
1377     break;
1378     case FMT_S:
1379     case FMT_D:
1380     /* sign: */
1381     sign = (reg >> 31) & 1;
1382     if (fmt == FMT_D)
1383     sign = (reg >> 63) & 1;
1384    
1385     fraction = 0.0;
1386     for (i=0; i<n_frac; i++) {
1387     int bit = (reg >> i) & 1;
1388     fraction /= 2.0;
1389     if (bit)
1390     fraction += 1.0;
1391     }
1392     /* Add implicit bit 0: */
1393     fraction = (fraction / 2.0) + 1.0;
1394     break;
1395     default:
1396     fatal("fpu_interpret_float_value(): "
1397     "unimplemented format %i\n", fmt);
1398     }
1399    
1400     /* form the value: */
1401     fvp->f = fraction;
1402    
1403     /* fatal("load reg=%016llx sign=%i exponent=%i fraction=%f ",
1404     (long long)reg, sign, exponent, fraction); */
1405    
1406     /* TODO: this is awful for exponents of large magnitude. */
1407     if (exponent > 0) {
1408     /*
1409     * NOTE / TODO:
1410     *
1411     * This is an ulgy workaround on Alpha, where it seems that
1412     * multiplying by 2, 1024 times causes a floating point
1413     * exception. (Triggered by running for example NetBSD/pmax
1414     * 2.0 on an Alpha.)
1415     */
1416     if (exponent == 1024)
1417     exponent = 1023;
1418    
1419     while (exponent-- > 0)
1420     fvp->f *= 2.0;
1421     } else if (exponent < 0) {
1422     while (exponent++ < 0)
1423     fvp->f /= 2.0;
1424     }
1425    
1426     if (sign)
1427     fvp->f = -fvp->f;
1428    
1429     no_reasonable_result:
1430     fvp->nan = nan;
1431    
1432     /* fatal("f = %f\n", fvp->f); */
1433     }
1434    
1435    
1436     /*
1437     * fpu_store_float_value():
1438     *
1439     * Stores a float value (actually a double) in fmt format.
1440     */
1441     static void fpu_store_float_value(struct mips_coproc *cp, int fd,
1442     double nf, int fmt, int nan)
1443     {
1444     int n_frac = 0, n_exp = 0, signofs=0;
1445     int i, exponent;
1446     uint64_t r = 0, r2;
1447     int64_t r3;
1448    
1449     /* n_frac and n_exp: */
1450     switch (fmt) {
1451     case FMT_S: n_frac = 23; n_exp = 8; signofs = 31; break;
1452     case FMT_W: n_frac = 31; n_exp = 0; signofs = 31; break;
1453     case FMT_D: n_frac = 52; n_exp = 11; signofs = 63; break;
1454     case FMT_L: n_frac = 63; n_exp = 0; signofs = 63; break;
1455     default:
1456     fatal("fpu_store_float_value(): unimplemented format"
1457     " %i\n", fmt);
1458     }
1459    
1460     if ((fmt == FMT_S || fmt == FMT_D) && nan)
1461     goto store_nan;
1462    
1463     /* fraction: */
1464     switch (fmt) {
1465     case FMT_W:
1466     case FMT_L:
1467     /*
1468     * This causes an implicit conversion of double to integer.
1469     * If nf < 0.0, then r2 will begin with a sequence of binary
1470     * 1's, which is ok.
1471     */
1472     r3 = nf;
1473     r2 = r3;
1474     r |= r2;
1475    
1476     if (fmt == FMT_W)
1477     r &= 0xffffffffULL;
1478     break;
1479     case FMT_S:
1480     case FMT_D:
1481     /* fatal("store f=%f ", nf); */
1482    
1483     /* sign bit: */
1484     if (nf < 0.0) {
1485     r |= ((uint64_t)1 << signofs);
1486     nf = -nf;
1487     }
1488    
1489     /*
1490     * How to convert back from double to exponent + fraction:
1491     * We want fraction to be 1.xxx, that is
1492     * 1.0 <= fraction < 2.0
1493     *
1494     * This method is very slow but should work:
1495     */
1496     exponent = 0;
1497     while (nf < 1.0 && exponent > -1023) {
1498     nf *= 2.0;
1499     exponent --;
1500     }
1501     while (nf >= 2.0 && exponent < 1023) {
1502     nf /= 2.0;
1503     exponent ++;
1504     }
1505    
1506     /* Here: 1.0 <= nf < 2.0 */
1507     /* fatal(" nf=%f", nf); */
1508     nf -= 1.0; /* remove implicit first bit */
1509     for (i=n_frac-1; i>=0; i--) {
1510     nf *= 2.0;
1511     if (nf >= 1.0) {
1512     r |= ((uint64_t)1 << i);
1513     nf -= 1.0;
1514     }
1515     /* printf("\n i=%2i r=%016llx\n", i, (long long)r); */
1516     }
1517    
1518     /* Insert the exponent into the resulting word: */
1519     /* (First bias, then make sure it's within range) */
1520     exponent += (((uint64_t)1 << (n_exp-1)) - 1);
1521     if (exponent < 0)
1522     exponent = 0;
1523     if (exponent >= ((int64_t)1 << n_exp))
1524     exponent = ((int64_t)1 << n_exp) - 1;
1525     r |= (uint64_t)exponent << n_frac;
1526    
1527     /* Special case for 0.0: */
1528     if (exponent == 0)
1529     r = 0;
1530    
1531     /* fatal(" exp=%i, r = %016llx\n", exponent, (long long)r); */
1532    
1533     break;
1534     default:
1535     /* TODO */
1536     fatal("fpu_store_float_value(): unimplemented format "
1537     "%i\n", fmt);
1538     }
1539    
1540     store_nan:
1541     if (nan) {
1542     if (fmt == FMT_S)
1543     r = 0x7fffffffULL;
1544     else if (fmt == FMT_D)
1545     r = 0x7fffffffffffffffULL;
1546     else
1547     r = 0x7fffffffULL;
1548     }
1549    
1550     /*
1551     * TODO: this is for 32-bit mode. It has to be updated later
1552     * for 64-bit coprocessor stuff.
1553     */
1554     if (fmt == FMT_D || fmt == FMT_L) {
1555     cp->reg[fd] = r & 0xffffffffULL;
1556     cp->reg[(fd+1) & 31] = (r >> 32) & 0xffffffffULL;
1557    
1558     if (cp->reg[fd] & 0x80000000ULL)
1559     cp->reg[fd] |= 0xffffffff00000000ULL;
1560     if (cp->reg[fd+1] & 0x80000000ULL)
1561     cp->reg[fd+1] |= 0xffffffff00000000ULL;
1562     } else {
1563     cp->reg[fd] = r & 0xffffffffULL;
1564    
1565     if (cp->reg[fd] & 0x80000000ULL)
1566     cp->reg[fd] |= 0xffffffff00000000ULL;
1567     }
1568     }
1569    
1570    
1571     /*
1572     * fpu_op():
1573     *
1574     * Perform a floating-point operation. For those of fs and ft
1575     * that are >= 0, those numbers are interpreted into local
1576     * variables.
1577     *
1578     * Only FPU_OP_C (compare) returns anything of interest, 1 for
1579     * true, 0 for false.
1580     */
1581     static int fpu_op(struct cpu *cpu, struct mips_coproc *cp, int op, int fmt,
1582     int ft, int fs, int fd, int cond, int output_fmt)
1583     {
1584     /* Potentially two input registers, fs and ft */
1585     struct internal_float_value float_value[2];
1586     int unordered, nan;
1587     uint64_t fs_v = 0;
1588     double nf;
1589    
1590     if (fs >= 0) {
1591     fs_v = cp->reg[fs];
1592     /* TODO: register-pair mode and plain
1593     register mode? "FR" bit? */
1594     if (fmt == FMT_D || fmt == FMT_L)
1595     fs_v = (fs_v & 0xffffffffULL) +
1596     (cp->reg[(fs + 1) & 31] << 32);
1597     fpu_interpret_float_value(fs_v, &float_value[0], fmt);
1598     }
1599     if (ft >= 0) {
1600     uint64_t v = cp->reg[ft];
1601     /* TODO: register-pair mode and
1602     plain register mode? "FR" bit? */
1603     if (fmt == FMT_D || fmt == FMT_L)
1604     v = (v & 0xffffffffULL) +
1605     (cp->reg[(ft + 1) & 31] << 32);
1606     fpu_interpret_float_value(v, &float_value[1], fmt);
1607     }
1608    
1609     switch (op) {
1610     case FPU_OP_ADD:
1611     nf = float_value[0].f + float_value[1].f;
1612     /* debug(" add: %f + %f = %f\n",
1613     float_value[0].f, float_value[1].f, nf); */
1614     fpu_store_float_value(cp, fd, nf, output_fmt,
1615     float_value[0].nan || float_value[1].nan);
1616     break;
1617     case FPU_OP_SUB:
1618     nf = float_value[0].f - float_value[1].f;
1619     /* debug(" sub: %f - %f = %f\n",
1620     float_value[0].f, float_value[1].f, nf); */
1621     fpu_store_float_value(cp, fd, nf, output_fmt,
1622     float_value[0].nan || float_value[1].nan);
1623     break;
1624     case FPU_OP_MUL:
1625     nf = float_value[0].f * float_value[1].f;
1626     /* debug(" mul: %f * %f = %f\n",
1627     float_value[0].f, float_value[1].f, nf); */
1628     fpu_store_float_value(cp, fd, nf, output_fmt,
1629     float_value[0].nan || float_value[1].nan);
1630     break;
1631     case FPU_OP_DIV:
1632     nan = float_value[0].nan || float_value[1].nan;
1633     if (fabs(float_value[1].f) > 0.00000000001)
1634     nf = float_value[0].f / float_value[1].f;
1635     else {
1636     fatal("DIV by zero !!!!\n");
1637     nf = 0.0; /* TODO */
1638     nan = 1;
1639     }
1640     /* debug(" div: %f / %f = %f\n",
1641     float_value[0].f, float_value[1].f, nf); */
1642     fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1643     break;
1644     case FPU_OP_SQRT:
1645     nan = float_value[0].nan;
1646     if (float_value[0].f >= 0.0)
1647     nf = sqrt(float_value[0].f);
1648     else {
1649     fatal("SQRT by less than zero, %f !!!!\n",
1650     float_value[0].f);
1651     nf = 0.0; /* TODO */
1652     nan = 1;
1653     }
1654     /* debug(" sqrt: %f => %f\n", float_value[0].f, nf); */
1655     fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1656     break;
1657     case FPU_OP_ABS:
1658     nf = fabs(float_value[0].f);
1659     /* debug(" abs: %f => %f\n", float_value[0].f, nf); */
1660     fpu_store_float_value(cp, fd, nf, output_fmt,
1661     float_value[0].nan);
1662     break;
1663     case FPU_OP_NEG:
1664     nf = - float_value[0].f;
1665     /* debug(" neg: %f => %f\n", float_value[0].f, nf); */
1666     fpu_store_float_value(cp, fd, nf, output_fmt,
1667     float_value[0].nan);
1668     break;
1669     case FPU_OP_CVT:
1670     nf = float_value[0].f;
1671     /* debug(" mov: %f => %f\n", float_value[0].f, nf); */
1672     fpu_store_float_value(cp, fd, nf, output_fmt,
1673     float_value[0].nan);
1674     break;
1675     case FPU_OP_MOV:
1676     /* Non-arithmetic move: */
1677     /*
1678     * TODO: this is for 32-bit mode. It has to be updated later
1679     * for 64-bit coprocessor stuff.
1680     */
1681     if (output_fmt == FMT_D || output_fmt == FMT_L) {
1682     cp->reg[fd] = fs_v & 0xffffffffULL;
1683     cp->reg[(fd+1) & 31] = (fs_v >> 32) & 0xffffffffULL;
1684     if (cp->reg[fd] & 0x80000000ULL)
1685     cp->reg[fd] |= 0xffffffff00000000ULL;
1686     if (cp->reg[fd+1] & 0x80000000ULL)
1687     cp->reg[fd+1] |= 0xffffffff00000000ULL;
1688     } else {
1689     cp->reg[fd] = fs_v & 0xffffffffULL;
1690     if (cp->reg[fd] & 0x80000000ULL)
1691     cp->reg[fd] |= 0xffffffff00000000ULL;
1692     }
1693     break;
1694     case FPU_OP_C:
1695     /* debug(" c: cond=%i\n", cond); */
1696    
1697     unordered = 0;
1698     if (float_value[0].nan || float_value[1].nan)
1699     unordered = 1;
1700    
1701     switch (cond) {
1702     case 2: /* Equal */
1703     return (float_value[0].f == float_value[1].f);
1704     case 4: /* Ordered or Less than */
1705     return (float_value[0].f < float_value[1].f)
1706     || !unordered;
1707     case 5: /* Unordered or Less than */
1708     return (float_value[0].f < float_value[1].f)
1709     || unordered;
1710     case 6: /* Ordered or Less than or Equal */
1711     return (float_value[0].f <= float_value[1].f)
1712     || !unordered;
1713     case 7: /* Unordered or Less than or Equal */
1714     return (float_value[0].f <= float_value[1].f)
1715     || unordered;
1716     case 12:/* Less than */
1717     return (float_value[0].f < float_value[1].f);
1718     case 14:/* Less than or equal */
1719     return (float_value[0].f <= float_value[1].f);
1720    
1721     /* The following are not commonly used, so I'll move these out
1722     of the if-0 on a case-by-case basis. */
1723     #if 0
1724     case 0: return 0; /* False */
1725     case 1: return 0; /* Unordered */
1726     case 3: return (float_value[0].f == float_value[1].f);
1727     /* Unordered or Equal */
1728     case 8: return 0; /* Signaling false */
1729     case 9: return 0; /* Not Greater than or Less than or Equal */
1730     case 10:return (float_value[0].f == float_value[1].f); /* Signaling Equal */
1731     case 11:return (float_value[0].f == float_value[1].f); /* Not Greater
1732     than or Less than */
1733     case 13:return !(float_value[0].f >= float_value[1].f); /* Not greater
1734     than or equal */
1735     case 15:return !(float_value[0].f > float_value[1].f); /* Not greater than */
1736     #endif
1737    
1738     default:
1739     fatal("fpu_op(): unimplemented condition "
1740     "code %i. see cpu_mips_coproc.c\n", cond);
1741     }
1742     break;
1743     default:
1744     fatal("fpu_op(): unimplemented op %i\n", op);
1745     }
1746    
1747     return 0;
1748     }
1749    
1750    
1751     /*
1752     * fpu_function():
1753     *
1754     * Returns 1 if function was implemented, 0 otherwise.
1755     * Debug trace should be printed for known instructions.
1756     */
1757     static int fpu_function(struct cpu *cpu, struct mips_coproc *cp,
1758     uint32_t function, int unassemble_only)
1759     {
1760     int fd, fs, ft, fmt, cond, cc;
1761    
1762     fmt = (function >> 21) & 31;
1763     ft = (function >> 16) & 31;
1764     fs = (function >> 11) & 31;
1765     cc = (function >> 8) & 7;
1766     fd = (function >> 6) & 31;
1767     cond = (function >> 0) & 15;
1768    
1769    
1770     /* bc1f, bc1t, bc1fl, bc1tl: */
1771     if ((function & 0x03e00000) == 0x01000000) {
1772     int nd, tf, imm, cond_true;
1773     char *instr_mnem;
1774    
1775     /* cc are bits 20..18: */
1776     cc = (function >> 18) & 7;
1777     nd = (function >> 17) & 1;
1778     tf = (function >> 16) & 1;
1779     imm = function & 65535;
1780     if (imm >= 32768)
1781     imm -= 65536;
1782    
1783     instr_mnem = NULL;
1784     if (nd == 0 && tf == 0) instr_mnem = "bc1f";
1785     if (nd == 0 && tf == 1) instr_mnem = "bc1t";
1786     if (nd == 1 && tf == 0) instr_mnem = "bc1fl";
1787     if (nd == 1 && tf == 1) instr_mnem = "bc1tl";
1788    
1789     if (cpu->machine->instruction_trace || unassemble_only)
1790     debug("%s\t%i,0x%016llx\n", instr_mnem, cc,
1791     (long long) (cpu->pc + (imm << 2)));
1792     if (unassemble_only)
1793     return 1;
1794    
1795     if (cpu->cd.mips.delay_slot) {
1796     fatal("%s: jump inside a jump's delay slot, "
1797     "or similar. TODO\n", instr_mnem);
1798     cpu->running = 0;
1799     return 1;
1800     }
1801    
1802     /* Both the FCCR and FCSR contain condition code bits... */
1803     if (cc == 0)
1804     cond_true = (cp->fcr[FPU_FCSR] >> FCSR_FCC0_SHIFT) & 1;
1805     else
1806     cond_true = (cp->fcr[FPU_FCSR] >>
1807     (FCSR_FCC1_SHIFT + cc-1)) & 1;
1808    
1809     if (!tf)
1810     cond_true = !cond_true;
1811    
1812     if (cond_true) {
1813     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
1814     cpu->cd.mips.delay_jmpaddr = cpu->pc + (imm << 2);
1815     } else {
1816     /* "likely": */
1817     if (nd) {
1818     /* nullify the delay slot */
1819     cpu->cd.mips.nullify_next = 1;
1820     }
1821     }
1822    
1823     return 1;
1824     }
1825    
1826     /* add.fmt: Floating-point add */
1827     if ((function & 0x0000003f) == 0x00000000) {
1828     if (cpu->machine->instruction_trace || unassemble_only)
1829     debug("add.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1830     if (unassemble_only)
1831     return 1;
1832    
1833     fpu_op(cpu, cp, FPU_OP_ADD, fmt, ft, fs, fd, -1, fmt);
1834     return 1;
1835     }
1836    
1837     /* sub.fmt: Floating-point subtract */
1838     if ((function & 0x0000003f) == 0x00000001) {
1839     if (cpu->machine->instruction_trace || unassemble_only)
1840     debug("sub.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1841     if (unassemble_only)
1842     return 1;
1843    
1844     fpu_op(cpu, cp, FPU_OP_SUB, fmt, ft, fs, fd, -1, fmt);
1845     return 1;
1846     }
1847    
1848     /* mul.fmt: Floating-point multiply */
1849     if ((function & 0x0000003f) == 0x00000002) {
1850     if (cpu->machine->instruction_trace || unassemble_only)
1851     debug("mul.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1852     if (unassemble_only)
1853     return 1;
1854    
1855     fpu_op(cpu, cp, FPU_OP_MUL, fmt, ft, fs, fd, -1, fmt);
1856     return 1;
1857     }
1858    
1859     /* div.fmt: Floating-point divide */
1860     if ((function & 0x0000003f) == 0x00000003) {
1861     if (cpu->machine->instruction_trace || unassemble_only)
1862     debug("div.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1863     if (unassemble_only)
1864     return 1;
1865    
1866     fpu_op(cpu, cp, FPU_OP_DIV, fmt, ft, fs, fd, -1, fmt);
1867     return 1;
1868     }
1869    
1870     /* sqrt.fmt: Floating-point square-root */
1871     if ((function & 0x001f003f) == 0x00000004) {
1872     if (cpu->machine->instruction_trace || unassemble_only)
1873     debug("sqrt.%i\tr%i,r%i\n", fmt, fd, fs);
1874     if (unassemble_only)
1875     return 1;
1876    
1877     fpu_op(cpu, cp, FPU_OP_SQRT, fmt, -1, fs, fd, -1, fmt);
1878     return 1;
1879     }
1880    
1881     /* abs.fmt: Floating-point absolute value */
1882     if ((function & 0x001f003f) == 0x00000005) {
1883     if (cpu->machine->instruction_trace || unassemble_only)
1884     debug("abs.%i\tr%i,r%i\n", fmt, fd, fs);
1885     if (unassemble_only)
1886     return 1;
1887    
1888     fpu_op(cpu, cp, FPU_OP_ABS, fmt, -1, fs, fd, -1, fmt);
1889     return 1;
1890     }
1891    
1892     /* mov.fmt: Floating-point (non-arithmetic) move */
1893     if ((function & 0x0000003f) == 0x00000006) {
1894     if (cpu->machine->instruction_trace || unassemble_only)
1895     debug("mov.%i\tr%i,r%i\n", fmt, fd, fs);
1896     if (unassemble_only)
1897     return 1;
1898    
1899     fpu_op(cpu, cp, FPU_OP_MOV, fmt, -1, fs, fd, -1, fmt);
1900     return 1;
1901     }
1902    
1903     /* neg.fmt: Floating-point negate */
1904     if ((function & 0x001f003f) == 0x00000007) {
1905     if (cpu->machine->instruction_trace || unassemble_only)
1906     debug("neg.%i\tr%i,r%i\n", fmt, fd, fs);
1907     if (unassemble_only)
1908     return 1;
1909    
1910     fpu_op(cpu, cp, FPU_OP_NEG, fmt, -1, fs, fd, -1, fmt);
1911     return 1;
1912     }
1913    
1914     /* trunc.l.fmt: Truncate */
1915     if ((function & 0x001f003f) == 0x00000009) {
1916     if (cpu->machine->instruction_trace || unassemble_only)
1917     debug("trunc.l.%i\tr%i,r%i\n", fmt, fd, fs);
1918     if (unassemble_only)
1919     return 1;
1920    
1921     /* TODO: not CVT? */
1922    
1923     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_L);
1924     return 1;
1925     }
1926    
1927     /* trunc.w.fmt: Truncate */
1928     if ((function & 0x001f003f) == 0x0000000d) {
1929     if (cpu->machine->instruction_trace || unassemble_only)
1930     debug("trunc.w.%i\tr%i,r%i\n", fmt, fd, fs);
1931     if (unassemble_only)
1932     return 1;
1933    
1934     /* TODO: not CVT? */
1935    
1936     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_W);
1937     return 1;
1938     }
1939    
1940     /* c.cond.fmt: Floating-point compare */
1941     if ((function & 0x000000f0) == 0x00000030) {
1942     int cond_true;
1943     int bit;
1944    
1945     if (cpu->machine->instruction_trace || unassemble_only)
1946     debug("c.%i.%i\tr%i,r%i,r%i\n", cond, fmt, cc, fs, ft);
1947     if (unassemble_only)
1948     return 1;
1949    
1950     cond_true = fpu_op(cpu, cp, FPU_OP_C, fmt,
1951     ft, fs, -1, cond, fmt);
1952    
1953     /*
1954     * Both the FCCR and FCSR contain condition code bits:
1955     * FCCR: bits 7..0
1956     * FCSR: bits 31..25 and 23
1957     */
1958     cp->fcr[FPU_FCCR] &= ~(1 << cc);
1959     if (cond_true)
1960     cp->fcr[FPU_FCCR] |= (1 << cc);
1961    
1962     if (cc == 0) {
1963     bit = 1 << FCSR_FCC0_SHIFT;
1964     cp->fcr[FPU_FCSR] &= ~bit;
1965     if (cond_true)
1966     cp->fcr[FPU_FCSR] |= bit;
1967     } else {
1968     bit = 1 << (FCSR_FCC1_SHIFT + cc-1);
1969     cp->fcr[FPU_FCSR] &= ~bit;
1970     if (cond_true)
1971     cp->fcr[FPU_FCSR] |= bit;
1972     }
1973    
1974     return 1;
1975     }
1976    
1977     /* cvt.s.fmt: Convert to single floating-point */
1978     if ((function & 0x001f003f) == 0x00000020) {
1979     if (cpu->machine->instruction_trace || unassemble_only)
1980     debug("cvt.s.%i\tr%i,r%i\n", fmt, fd, fs);
1981     if (unassemble_only)
1982     return 1;
1983    
1984     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_S);
1985     return 1;
1986     }
1987    
1988     /* cvt.d.fmt: Convert to double floating-point */
1989     if ((function & 0x001f003f) == 0x00000021) {
1990     if (cpu->machine->instruction_trace || unassemble_only)
1991     debug("cvt.d.%i\tr%i,r%i\n", fmt, fd, fs);
1992     if (unassemble_only)
1993     return 1;
1994    
1995     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_D);
1996     return 1;
1997     }
1998    
1999     /* cvt.w.fmt: Convert to word fixed-point */
2000     if ((function & 0x001f003f) == 0x00000024) {
2001     if (cpu->machine->instruction_trace || unassemble_only)
2002     debug("cvt.w.%i\tr%i,r%i\n", fmt, fd, fs);
2003     if (unassemble_only)
2004     return 1;
2005    
2006     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_W);
2007     return 1;
2008     }
2009    
2010     return 0;
2011     }
2012    
2013    
2014     /*
2015     * coproc_tlbpr():
2016     *
2017     * 'tlbp' and 'tlbr'.
2018     */
2019     void coproc_tlbpr(struct cpu *cpu, int readflag)
2020     {
2021     struct mips_coproc *cp = cpu->cd.mips.coproc[0];
2022     int i, found, g_bit;
2023     uint64_t vpn2, xmask;
2024    
2025     /* Read: */
2026     if (readflag) {
2027     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
2028     i = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK) >>
2029     R2K3K_INDEX_SHIFT;
2030     if (i >= cp->nr_of_tlbs) {
2031     /* TODO: exception? */
2032     fatal("warning: tlbr from index %i (too "
2033     "high)\n", i);
2034     return;
2035     }
2036    
2037     /*
2038     * TODO: Hm. Earlier I had an & ~0x3f on the high
2039     * assignment and an & ~0xff on the lo0 assignment.
2040     * I wonder why.
2041     */
2042    
2043     cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi; /* & ~0x3f; */
2044     cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;/* & ~0xff; */
2045     } else {
2046     /* R4000: */
2047     i = cp->reg[COP0_INDEX] & INDEX_MASK;
2048     if (i >= cp->nr_of_tlbs) /* TODO: exception */
2049     return;
2050    
2051     cp->reg[COP0_PAGEMASK] = cp->tlbs[i].mask;
2052     cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi;
2053     cp->reg[COP0_ENTRYLO1] = cp->tlbs[i].lo1;
2054     cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;
2055    
2056     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
2057     /* R4100 don't have the G bit in entryhi */
2058     } else {
2059     /* R4000 etc: */
2060     cp->reg[COP0_ENTRYHI] &= ~TLB_G;
2061     g_bit = cp->tlbs[i].hi & TLB_G;
2062    
2063     cp->reg[COP0_ENTRYLO0] &= ~ENTRYLO_G;
2064     cp->reg[COP0_ENTRYLO1] &= ~ENTRYLO_G;
2065     if (g_bit) {
2066     cp->reg[COP0_ENTRYLO0] |= ENTRYLO_G;
2067     cp->reg[COP0_ENTRYLO1] |= ENTRYLO_G;
2068     }
2069     }
2070     }
2071    
2072     return;
2073     }
2074    
2075     /* Probe: */
2076     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
2077     vpn2 = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
2078     found = -1;
2079     for (i=0; i<cp->nr_of_tlbs; i++)
2080     if ( ((cp->tlbs[i].hi & R2K3K_ENTRYHI_ASID_MASK) ==
2081     (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK))
2082     || cp->tlbs[i].lo0 & R2K3K_ENTRYLO_G)
2083     if ((cp->tlbs[i].hi & R2K3K_ENTRYHI_VPN_MASK)
2084     == vpn2) {
2085     found = i;
2086     break;
2087     }
2088     } else {
2089     /* R4000 and R10000: */
2090     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
2091     xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K;
2092     else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
2093     xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800;
2094     else
2095     xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK;
2096     vpn2 = cp->reg[COP0_ENTRYHI] & xmask;
2097     found = -1;
2098     for (i=0; i<cp->nr_of_tlbs; i++) {
2099     int gbit = cp->tlbs[i].hi & TLB_G;
2100     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
2101     gbit = (cp->tlbs[i].lo0 & ENTRYLO_G) &&
2102     (cp->tlbs[i].lo1 & ENTRYLO_G);
2103    
2104     if ( ((cp->tlbs[i].hi & ENTRYHI_ASID) ==
2105     (cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID)) || gbit) {
2106     uint64_t a = vpn2 & ~cp->tlbs[i].mask;
2107     uint64_t b = (cp->tlbs[i].hi & xmask) &
2108     ~cp->tlbs[i].mask;
2109     if (a == b) {
2110     found = i;
2111     break;
2112     }
2113     }
2114     }
2115     }
2116     if (found == -1)
2117     cp->reg[COP0_INDEX] = INDEX_P;
2118     else {
2119     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
2120     cp->reg[COP0_INDEX] = found << R2K3K_INDEX_SHIFT;
2121     else
2122     cp->reg[COP0_INDEX] = found;
2123     }
2124    
2125     /* Sign extend the index register: */
2126     if ((cp->reg[COP0_INDEX] >> 32) == 0 &&
2127     cp->reg[COP0_INDEX] & 0x80000000)
2128     cp->reg[COP0_INDEX] |=
2129     0xffffffff00000000ULL;
2130     }
2131    
2132    
2133     /*
2134     * coproc_tlbwri():
2135     *
2136     * 'tlbwr' and 'tlbwi'
2137     */
2138     void coproc_tlbwri(struct cpu *cpu, int randomflag)
2139     {
2140     struct mips_coproc *cp = cpu->cd.mips.coproc[0];
2141     int index, g_bit;
2142     uint64_t oldvaddr;
2143     int old_asid = -1;
2144    
2145     /*
2146     * ... and the last instruction page:
2147     *
2148     * Some thoughts about this: Code running in
2149     * the kernel's physical address space has the
2150     * same vaddr->paddr translation, so the last
2151     * virtual page invalidation only needs to
2152     * happen if we are for some extremely weird
2153     * reason NOT running in the kernel's physical
2154     * address space.
2155     *
2156     * (An even insaner (but probably useless)
2157     * optimization would be to only invalidate
2158     * the last virtual page stuff if the TLB
2159     * update actually affects the vaddr in
2160     * question.)
2161     */
2162    
2163     if (cpu->pc < (uint64_t)0xffffffff80000000ULL ||
2164     cpu->pc >= (uint64_t)0xffffffffc0000000ULL)
2165     cpu->cd.mips.pc_last_virtual_page =
2166     PC_LAST_PAGE_IMPOSSIBLE_VALUE;
2167    
2168     if (randomflag) {
2169     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
2170     index = (cp->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
2171     >> R2K3K_RANDOM_SHIFT;
2172     else
2173     index = cp->reg[COP0_RANDOM] & RANDOM_MASK;
2174     } else {
2175     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
2176     index = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
2177     >> R2K3K_INDEX_SHIFT;
2178     else
2179     index = cp->reg[COP0_INDEX] & INDEX_MASK;
2180     }
2181    
2182     if (index >= cp->nr_of_tlbs) {
2183     fatal("warning: tlb index %i too high (max is %i)\n",
2184     index, cp->nr_of_tlbs - 1);
2185     /* TODO: cause an exception? */
2186     return;
2187     }
2188    
2189     #if 0
2190     /* Debug dump of the previous entry at that index: */
2191     debug(" old entry at index = %04x", index);
2192     debug(" mask = %016llx", (long long) cp->tlbs[index].mask);
2193     debug(" hi = %016llx", (long long) cp->tlbs[index].hi);
2194     debug(" lo0 = %016llx", (long long) cp->tlbs[index].lo0);
2195     debug(" lo1 = %016llx\n", (long long) cp->tlbs[index].lo1);
2196     #endif
2197    
2198     /* Translation caches must be invalidated: */
2199     switch (cpu->cd.mips.cpu_type.mmu_model) {
2200     case MMU3K:
2201     oldvaddr = cp->tlbs[index].hi & R2K3K_ENTRYHI_VPN_MASK;
2202     oldvaddr &= 0xffffffffULL;
2203     if (oldvaddr & 0x80000000ULL)
2204     oldvaddr |= 0xffffffff00000000ULL;
2205     old_asid = (cp->tlbs[index].hi & R2K3K_ENTRYHI_ASID_MASK)
2206     >> R2K3K_ENTRYHI_ASID_SHIFT;
2207    
2208     /* TODO: Bug? Why does this if need to be commented out? */
2209    
2210     /* if (cp->tlbs[index].lo0 & ENTRYLO_V) */
2211     invalidate_translation_caches(cpu, 0, oldvaddr, 0, 0);
2212     break;
2213     default:
2214     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
2215     oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;
2216     /* 44 addressable bits: */
2217     if (oldvaddr & 0x80000000000ULL)
2218     oldvaddr |= 0xfffff00000000000ULL;
2219     } else {
2220     /* Assume MMU4K */
2221     oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
2222     /* 40 addressable bits: */
2223     if (oldvaddr & 0x8000000000ULL)
2224     oldvaddr |= 0xffffff0000000000ULL;
2225     }
2226    
2227     /*
2228     * Both pages:
2229     *
2230     * TODO: non-4KB page sizes!
2231     */
2232     invalidate_translation_caches(
2233     cpu, 0, oldvaddr & ~0x1fff, 0, 0);
2234     invalidate_translation_caches(
2235     cpu, 0, (oldvaddr & ~0x1fff) | 0x1000, 0, 0);
2236     }
2237    
2238    
2239     /* Write the new entry: */
2240    
2241     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
2242     uint64_t vaddr, paddr;
2243     int wf = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_D? 1 : 0;
2244     unsigned char *memblock = NULL;
2245    
2246     cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
2247     cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
2248    
2249     vaddr = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
2250     paddr = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_PFN_MASK;
2251    
2252     /* TODO: This is ugly. */
2253     if (paddr < 0x10000000)
2254     memblock = memory_paddr_to_hostaddr(
2255     cpu->mem, paddr, 1);
2256    
2257     if (memblock != NULL &&
2258     cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_V) {
2259     memblock += (paddr & ((1 << BITS_PER_PAGETABLE) - 1));
2260    
2261     /*
2262     * TODO: Hahaha, this is even uglier than the thing
2263     * above. Some OSes seem to map code pages read/write,
2264     * which causes the bintrans cache to be invalidated
2265     * even when it doesn't have to be.
2266     */
2267     /* if (vaddr < 0x10000000) */
2268     wf = 0;
2269    
2270     update_translation_table(cpu, vaddr, memblock,
2271     wf, paddr);
2272     }
2273     } else {
2274     /* R4000: */
2275     g_bit = (cp->reg[COP0_ENTRYLO0] &
2276     cp->reg[COP0_ENTRYLO1]) & ENTRYLO_G;
2277     cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];
2278     cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
2279     cp->tlbs[index].lo1 = cp->reg[COP0_ENTRYLO1];
2280     cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
2281    
2282     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
2283     /* NOTE: The VR4131 (and possibly others) don't have
2284     a Global bit in entryhi */
2285     cp->tlbs[index].hi &= ~cp->reg[COP0_PAGEMASK];
2286     } else {
2287     cp->tlbs[index].lo0 &= ~ENTRYLO_G;
2288     cp->tlbs[index].lo1 &= ~ENTRYLO_G;
2289    
2290     cp->tlbs[index].hi &= ~TLB_G;
2291     if (g_bit)
2292     cp->tlbs[index].hi |= TLB_G;
2293     }
2294     }
2295    
2296     if (randomflag) {
2297     if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
2298     cp->reg[COP0_RANDOM] =
2299     ((random() % (cp->nr_of_tlbs - 8)) + 8)
2300     << R2K3K_RANDOM_SHIFT;
2301     } else {
2302     cp->reg[COP0_RANDOM] = cp->reg[COP0_WIRED] + (random()
2303     % (cp->nr_of_tlbs - cp->reg[COP0_WIRED]));
2304     }
2305     }
2306     }
2307    
2308    
2309     /*
2310     * coproc_rfe():
2311     *
2312     * Return from exception. (R3000 etc.)
2313     */
2314     void coproc_rfe(struct cpu *cpu)
2315     {
2316     int oldmode;
2317    
2318     oldmode = cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS1_SR_KU_CUR;
2319    
2320     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2321     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
2322     ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
2323    
2324     /* Changing from kernel to user mode? Then this is necessary: */
2325     if (!oldmode &&
2326     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &
2327     MIPS1_SR_KU_CUR))
2328     invalidate_translation_caches(cpu, 0, 0, 1, 0);
2329     }
2330    
2331    
2332     /*
2333     * coproc_eret():
2334     *
2335     * Return from exception. (R4000 etc.)
2336     */
2337     void coproc_eret(struct cpu *cpu)
2338     {
2339     int oldmode, newmode;
2340    
2341     /* Kernel mode flag: */
2342     oldmode = 0;
2343     if ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS3_SR_KSU_MASK)
2344     != MIPS3_SR_KSU_USER
2345     || (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & (STATUS_EXL |
2346     STATUS_ERL)) ||
2347     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 1) == 0)
2348     oldmode = 1;
2349    
2350     if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2351     cpu->pc = cpu->cd.mips.pc_last =
2352     cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2353     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
2354     } else {
2355     cpu->pc = cpu->cd.mips.pc_last =
2356     cpu->cd.mips.coproc[0]->reg[COP0_EPC];
2357     cpu->cd.mips.delay_slot = 0;
2358     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2359     }
2360    
2361     cpu->cd.mips.rmw = 0; /* the "LL bit" */
2362    
2363     /* New kernel mode flag: */
2364     newmode = 0;
2365     if ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS3_SR_KSU_MASK)
2366     != MIPS3_SR_KSU_USER
2367     || (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & (STATUS_EXL |
2368     STATUS_ERL)) ||
2369     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 1) == 0)
2370     newmode = 1;
2371    
2372     /* Changing from kernel to user mode?
2373     Then this is necessary: TODO */
2374     if (oldmode && !newmode)
2375     invalidate_translation_caches(cpu, 0, 0, 1, 0);
2376     }
2377    
2378    
2379     /*
2380     * coproc_function():
2381     *
2382     * Execute a coprocessor specific instruction. cp must be != NULL.
2383     * Debug trace should be printed for known instructions, if
2384     * unassemble_only is non-zero. (This will NOT execute the instruction.)
2385     *
2386     * TODO: This is a mess and should be restructured (again).
2387     */
2388     void coproc_function(struct cpu *cpu, struct mips_coproc *cp, int cpnr,
2389     uint32_t function, int unassemble_only, int running)
2390     {
2391     int co_bit, op, rt, rd, fs, copz;
2392     uint64_t tmpvalue;
2393    
2394     if (cp == NULL) {
2395     if (unassemble_only) {
2396     debug("cop%i\t0x%08x (coprocessor not available)\n",
2397     cpnr, (int)function);
2398     return;
2399     }
2400     fatal("[ pc=0x%016llx cop%i\t0x%08x (coprocessor not "
2401     "available)\n", (long long)cpu->pc, cpnr, (int)function);
2402     return;
2403     }
2404    
2405     #if 0
2406     /* No FPU? */
2407     if (cpnr == 1 && (cpu->cd.mips.cpu_type.flags & NOFPU)) {
2408     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2409     return;
2410     }
2411     #endif
2412    
2413     /* For quick reference: */
2414     copz = (function >> 21) & 31;
2415     rt = (function >> 16) & 31;
2416     rd = (function >> 11) & 31;
2417    
2418     if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21))
2419     || ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) {
2420     if (unassemble_only) {
2421     debug("%s%i\t%s,%s\n",
2422     copz==COPz_DMFCz? "dmfc" : "mfc", cpnr,
2423     regnames[rt], cop0_names[rd]);
2424     return;
2425     }
2426     coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr],
2427     rd, &tmpvalue);
2428     cpu->cd.mips.gpr[rt] = tmpvalue;
2429     if (copz == COPz_MFCz) {
2430     /* Sign-extend: */
2431     cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
2432     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
2433     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
2434     }
2435     return;
2436     }
2437    
2438     if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21))
2439     || ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) {
2440     if (unassemble_only) {
2441     debug("%s%i\t%s,%s\n",
2442     copz==COPz_DMTCz? "dmtc" : "mtc", cpnr,
2443     regnames[rt], cop0_names[rd]);
2444     return;
2445     }
2446     tmpvalue = cpu->cd.mips.gpr[rt];
2447     if (copz == COPz_MTCz) {
2448     /* Sign-extend: */
2449     tmpvalue &= 0xffffffffULL;
2450     if (tmpvalue & 0x80000000ULL)
2451     tmpvalue |= 0xffffffff00000000ULL;
2452     }
2453     coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd,
2454     &tmpvalue, copz == COPz_DMTCz);
2455     return;
2456     }
2457    
2458     if (cpnr <= 1 && (((function & 0x03e007ff) == (COPz_CFCz << 21))
2459     || ((function & 0x03e007ff) == (COPz_CTCz << 21)))) {
2460     switch (copz) {
2461     case COPz_CFCz: /* Copy from FPU control register */
2462     rt = (function >> 16) & 31;
2463     fs = (function >> 11) & 31;
2464     if (unassemble_only) {
2465     debug("cfc%i\t%s,r%i\n", cpnr,
2466     regnames[rt], fs);
2467     return;
2468     }
2469     cpu->cd.mips.gpr[rt] = cp->fcr[fs] & 0xffffffffULL;
2470     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
2471     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
2472     /* TODO: implement delay for gpr[rt]
2473     (for MIPS I,II,III only) */
2474     return;
2475     case COPz_CTCz: /* Copy to FPU control register */
2476     rt = (function >> 16) & 31;
2477     fs = (function >> 11) & 31;
2478     if (unassemble_only) {
2479     debug("ctc%i\t%s,r%i\n", cpnr,
2480     regnames[rt], fs);
2481     return;
2482     }
2483    
2484     switch (cpnr) {
2485     case 0: /* System coprocessor */
2486     fatal("[ warning: unimplemented ctc%i, "
2487     "0x%08x -> ctl reg %i ]\n", cpnr,
2488     (int)cpu->cd.mips.gpr[rt], fs);
2489     break;
2490     case 1: /* FPU */
2491     if (fs == 0)
2492     fatal("[ Attempt to write to FPU "
2493     "control register 0 (?) ]\n");
2494     else {
2495     uint64_t tmp = cpu->cd.mips.gpr[rt];
2496     cp->fcr[fs] = tmp;
2497    
2498     /* TODO: writing to control register 31
2499     should cause exceptions, depending
2500     on status bits! */
2501    
2502     switch (fs) {
2503     case FPU_FCCR:
2504     cp->fcr[FPU_FCSR] =
2505     (cp->fcr[FPU_FCSR] &
2506     0x017fffffULL) | ((tmp & 1)
2507     << FCSR_FCC0_SHIFT)
2508     | (((tmp & 0xfe) >> 1) <<
2509     FCSR_FCC1_SHIFT);
2510     break;
2511     case FPU_FCSR:
2512     cp->fcr[FPU_FCCR] =
2513     (cp->fcr[FPU_FCCR] &
2514     0xffffff00ULL) | ((tmp >>
2515     FCSR_FCC0_SHIFT) & 1) |
2516     (((tmp >> FCSR_FCC1_SHIFT)
2517     & 0x7f) << 1);
2518     break;
2519     default:
2520     ;
2521     }
2522     }
2523     break;
2524     }
2525    
2526     /* TODO: implement delay for gpr[rt]
2527     (for MIPS I,II,III only) */
2528     return;
2529     default:
2530     ;
2531     }
2532     }
2533    
2534     /* Math (Floating point) coprocessor calls: */
2535     if (cpnr==1) {
2536     if (fpu_function(cpu, cp, function, unassemble_only))
2537     return;
2538     }
2539    
2540     /* For AU1500 and probably others: deret */
2541     if (function == 0x0200001f) {
2542     if (unassemble_only) {
2543     debug("deret\n");
2544     return;
2545     }
2546    
2547     /*
2548     * According to the MIPS64 manual, deret loads PC from the
2549     * DEPC cop0 register, and jumps there immediately. No
2550     * delay slot.
2551     *
2552     * TODO: This instruction is only available if the processor
2553     * is in debug mode. (What does that mean?)
2554     * TODO: This instruction is undefined in a delay slot.
2555     */
2556    
2557     cpu->pc = cpu->cd.mips.pc_last = cp->reg[COP0_DEPC];
2558     cpu->cd.mips.delay_slot = 0;
2559     cp->reg[COP0_STATUS] &= ~STATUS_EXL;
2560    
2561     return;
2562     }
2563    
2564    
2565     /* Ugly R5900 hacks: */
2566     if ((function & 0xfffff) == 0x38) { /* ei */
2567     if (unassemble_only) {
2568     debug("ei\n");
2569     return;
2570     }
2571     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2572     return;
2573     }
2574    
2575     if ((function & 0xfffff) == 0x39) { /* di */
2576     if (unassemble_only) {
2577     debug("di\n");
2578     return;
2579     }
2580     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2581     return;
2582     }
2583    
2584     co_bit = (function >> 25) & 1;
2585    
2586     /* TLB operations and other things: */
2587     if (cp->coproc_nr == 0) {
2588     op = (function) & 0xff;
2589     switch (co_bit) {
2590     case 1:
2591     switch (op) {
2592     case COP0_TLBR: /* Read indexed TLB entry */
2593     if (unassemble_only) {
2594     debug("tlbr\n");
2595     return;
2596     }
2597     coproc_tlbpr(cpu, 1);
2598     return;
2599     case COP0_TLBWI: /* Write indexed */
2600     case COP0_TLBWR: /* Write random */
2601     if (unassemble_only) {
2602     if (op == COP0_TLBWI)
2603     debug("tlbwi");
2604     else
2605     debug("tlbwr");
2606     if (!running) {
2607     debug("\n");
2608     return;
2609     }
2610     debug("\tindex=%08llx",
2611     (long long)cp->reg[COP0_INDEX]);
2612     debug(", random=%08llx",
2613     (long long)cp->reg[COP0_RANDOM]);
2614     debug(", mask=%016llx",
2615     (long long)cp->reg[COP0_PAGEMASK]);
2616     debug(", hi=%016llx",
2617     (long long)cp->reg[COP0_ENTRYHI]);
2618     debug(", lo0=%016llx",
2619     (long long)cp->reg[COP0_ENTRYLO0]);
2620     debug(", lo1=%016llx\n",
2621     (long long)cp->reg[COP0_ENTRYLO1]);
2622     }
2623     coproc_tlbwri(cpu, op == COP0_TLBWR);
2624     return;
2625     case COP0_TLBP: /* Probe TLB for
2626     matching entry */
2627     if (unassemble_only) {
2628     debug("tlbp\n");
2629     return;
2630     }
2631     coproc_tlbpr(cpu, 0);
2632     return;
2633     case COP0_RFE: /* R2000/R3000 only:
2634     Return from Exception */
2635     if (unassemble_only) {
2636     debug("rfe\n");
2637     return;
2638     }
2639     coproc_rfe(cpu);
2640     return;
2641     case COP0_ERET: /* R4000: Return from exception */
2642     if (unassemble_only) {
2643     debug("eret\n");
2644     return;
2645     }
2646     coproc_eret(cpu);
2647     return;
2648     case COP0_STANDBY:
2649     if (unassemble_only) {
2650     debug("standby\n");
2651     return;
2652     }
2653     /* TODO: Hm. Do something here? */
2654     return;
2655     case COP0_SUSPEND:
2656     if (unassemble_only) {
2657     debug("suspend\n");
2658     return;
2659     }
2660     /* TODO: Hm. Do something here? */
2661     return;
2662     case COP0_HIBERNATE:
2663     if (unassemble_only) {
2664     debug("hibernate\n");
2665     return;
2666     }
2667     /* TODO: Hm. Do something here? */
2668     return;
2669     default:
2670     ;
2671     }
2672     default:
2673     ;
2674     }
2675     }
2676    
2677     /* TODO: coprocessor R2020 on DECstation? */
2678     if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x0100ffff) {
2679     if (unassemble_only) {
2680     debug("decstation_r2020_writeback\n");
2681     return;
2682     }
2683     /* TODO */
2684     return;
2685     }
2686    
2687     /* TODO: RM5200 idle (?) */
2688     if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x02000020) {
2689     if (unassemble_only) {
2690     debug("idle(?)\n"); /* TODO */
2691     return;
2692     }
2693    
2694     /* Idle? TODO */
2695     return;
2696     }
2697    
2698     if (unassemble_only) {
2699     debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);
2700     return;
2701     }
2702    
2703     fatal("cpu%i: UNIMPLEMENTED coproc%i function %08lx "
2704     "(pc = %016llx)\n", cpu->cpu_id, cp->coproc_nr, function,
2705     (long long)cpu->cd.mips.pc_last);
2706     #if 1
2707     single_step = 1;
2708     #else
2709     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0);
2710     #endif
2711     }
2712    
2713     #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26