cpu_mips_coproc.cc Source File

Back to the index.

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

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18