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-2018 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! */
85  IB = cpu->cd.mips.cache_picache_linesize - 1;
86  IB = IB < 0? 0 : (IB > 7? 7 : IB);
87  DB = cpu->cd.mips.cache_pdcache_linesize - 1;
88  DB = DB < 0? 0 : (DB > 7? 7 : DB);
89  IC = cpu->cd.mips.cache_picache -
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);
124  SB = cpu->cd.mips.cache_secondary_linesize - 4;
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  */
356 struct mips_coproc *mips_coproc_new(struct cpu *cpu, int coproc_nr)
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] =
427  cpu->cd.mips.coproc[0]->reg[COP0_COMPARE];
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: */
469  if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
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  /* 44 addressable bits: */
546  if (oldvaddr & 0x80000000000ULL)
547  oldvaddr |= 0x3ffff00000000000ULL;
548  } else if (cpu->is_32bit) {
549  /* MIPS32 etc.: */
550  oldvaddr = cp->tlbs[i].hi & ENTRYHI_VPN2_MASK;
551  oldvaddr = (int32_t)oldvaddr;
552  } else {
553  /* Assume MMU4K */
554  oldvaddr = cp->tlbs[i].hi &
556  /* 40 addressable bits: */
557  if (oldvaddr & 0x8000000000ULL)
558  oldvaddr |= 0x3fffff0000000000ULL;
559  }
560 
561  mask |= 0x1fff;
562  oldvaddr &= ~mask;
563 
564  // printf("pagesize = %016llx mask = %016llx\n", pagesize, mask);
565 
566  if (cp->tlbs[i].lo0 & ENTRYLO_V)
567  for (uint64_t ofs = 0; ofs < pagesize; ofs += 0x1000)
568  cpu->invalidate_translation_caches(cpu, oldvaddr + ofs, INVALIDATE_VADDR);
569 
570  if (cp->tlbs[i].lo1 & ENTRYLO_V)
571  for (uint64_t ofs = 0; ofs < pagesize; ofs += 0x1000)
572  cpu->invalidate_translation_caches(cpu, oldvaddr + ofs + pagesize, INVALIDATE_VADDR);
573  }
574  }
575 }
576 
577 
578 /*
579  * coproc_register_read();
580  *
581  * Read a value from a MIPS coprocessor register.
582  */
583 void coproc_register_read(struct cpu *cpu,
584  struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int select)
585 {
586  int unimpl = 1;
587 
588  if (cp->coproc_nr==0 && reg_nr==COP0_INDEX) unimpl = 0;
589  if (cp->coproc_nr==0 && reg_nr==COP0_RANDOM) unimpl = 0;
590  if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO0) unimpl = 0;
591  if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO1) unimpl = 0;
592  if (cp->coproc_nr==0 && reg_nr==COP0_CONTEXT) unimpl = 0;
593  if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK) unimpl = 0;
594  if (cp->coproc_nr==0 && reg_nr==COP0_WIRED) unimpl = 0;
595  if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR) unimpl = 0;
596  if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) {
597  /* TODO: Increase count in a more meaningful way! */
598  cp->reg[COP0_COUNT] = (int32_t) (cp->reg[COP0_COUNT] + 1);
600  unimpl = 0;
601  }
602  if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI) unimpl = 0;
603  if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE) unimpl = 0;
604  if (cp->coproc_nr==0 && reg_nr==COP0_STATUS) unimpl = 0;
605  if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE) unimpl = 0;
606  if (cp->coproc_nr==0 && reg_nr==COP0_EPC) unimpl = 0;
607  if (cp->coproc_nr==0 && reg_nr==COP0_PRID) unimpl = 0;
608  if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG) {
609  if (select > 0) {
610  switch (select) {
611  case 1: *ptr = cpu->cd.mips.cop0_config_select1;
612  break;
613  default:fatal("coproc_register_read(): unimplemented"
614  " config register select %i\n", select);
615  exit(1);
616  }
617  return;
618  }
619  unimpl = 0;
620  }
621  if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR) unimpl = 0;
622  if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO) unimpl = 0;
623  if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI) unimpl = 0;
624  if (cp->coproc_nr==0 && reg_nr==COP0_XCONTEXT) unimpl = 0;
625  if (cp->coproc_nr==0 && reg_nr==COP0_ERRCTL) unimpl = 0;
626  if (cp->coproc_nr==0 && reg_nr==COP0_CACHEERR) unimpl = 0;
627  if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_LO) unimpl = 0;
628  if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_HI) unimpl = 0;
629  if (cp->coproc_nr==0 && reg_nr==COP0_ERROREPC) unimpl = 0;
630  if (cp->coproc_nr==0 && reg_nr==COP0_RESERV22) {
631  /* Used by Linux on Linksys WRT54G */
632  unimpl = 0;
633  }
634  if (cp->coproc_nr==0 && reg_nr==COP0_DEBUG) unimpl = 0;
635  if (cp->coproc_nr==0 && reg_nr==COP0_PERFCNT) unimpl = 0;
636  if (cp->coproc_nr==0 && reg_nr==COP0_DESAVE) unimpl = 0;
637 
638  if (cp->coproc_nr==1) unimpl = 0;
639 
640  if (unimpl) {
641  fatal("cpu%i: warning: read from unimplemented coproc%i"
642  " register %i (%s)\n", cpu->cpu_id, cp->coproc_nr, reg_nr,
643  cp->coproc_nr==0? cop0_names[reg_nr] : "?");
644 
646  cp->coproc_nr, 0, 0, 0);
647  return;
648  }
649 
650  *ptr = cp->reg[reg_nr];
651 }
652 
653 
654 /*
655  * coproc_register_write();
656  *
657  * Write a value to a MIPS coprocessor register.
658  */
659 void coproc_register_write(struct cpu *cpu,
660  struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64,
661  int select)
662 {
663  int unimpl = 1;
664  int readonly = 0;
665  uint64_t tmp = *ptr;
666  uint64_t tmp2 = 0, old;
667  int inval = 0;
668  unsigned int old_asid;
669  uint64_t oldmode;
670 
671  switch (cp->coproc_nr) {
672  case 0:
673  /* COPROC 0: */
674  switch (reg_nr) {
675  case COP0_INDEX:
676  case COP0_RANDOM:
677  unimpl = 0;
678  break;
679  case COP0_ENTRYLO0:
680  unimpl = 0;
681  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
682  (tmp & 0xff)!=0) {
683  /* char *symbol;
684  uint64_t offset;
685  symbol = get_symbol_name(cpu->pc, &offset);
686  fatal("YO! pc = 0x%08llx <%s> "
687  "lo=%016llx\n", (long long)
688  cpu->pc, symbol? symbol :
689  "no symbol", (long long)tmp); */
690  tmp &= (R2K3K_ENTRYLO_PFN_MASK |
693  } else if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
694  tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
696  }
697  break;
698  case COP0_BADVADDR:
699  /* Hm. Irix writes to this register. (Why?) */
700  unimpl = 0;
701  break;
702  case COP0_ENTRYLO1:
703  unimpl = 0;
704  if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
705  tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
707  }
708  break;
709  case COP0_CONTEXT:
710  old = cp->reg[COP0_CONTEXT];
711  cp->reg[COP0_CONTEXT] = tmp;
712  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
713  cp->reg[COP0_CONTEXT] &=
715  cp->reg[COP0_CONTEXT] |=
717  } else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
718  cp->reg[COP0_CONTEXT] &=
720  cp->reg[COP0_CONTEXT] |=
722  } else {
723  cp->reg[COP0_CONTEXT] &=
725  cp->reg[COP0_CONTEXT] |=
726  (old & CONTEXT_BADVPN2_MASK);
727  }
728  return;
729  case COP0_PAGEMASK:
730  tmp2 = tmp >> PAGEMASK_SHIFT;
731  if (tmp2 != 0x000 &&
732  tmp2 != 0x003 &&
733  tmp2 != 0x00f &&
734  tmp2 != 0x03f &&
735  tmp2 != 0x0ff &&
736  tmp2 != 0x3ff &&
737  tmp2 != 0xfff)
738  fatal("[ cpu%i: trying to write an invalid"
739  " pagemask 0x%08lx to COP0_PAGEMASK ]\n",
740  cpu->cpu_id, (long)tmp);
741  unimpl = 0;
742  break;
743  case COP0_WIRED:
744  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
745  fatal("[ cpu%i: r2k/r3k wired register must "
746  "always be 8 ]\n", cpu->cpu_id);
747  tmp = 8;
748  }
749  cp->reg[COP0_RANDOM] = cp->nr_of_tlbs-1;
750  tmp &= INDEX_MASK;
751  unimpl = 0;
752  break;
753  case COP0_COUNT:
754  if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
755  fatal("[ WARNING: trying to write a 64-bit value"
756  " to the COUNT register! ]\n");
757  tmp = (int64_t)(int32_t)tmp;
758  unimpl = 0;
759  break;
760  case COP0_COMPARE:
761  if (cpu->machine->emulated_hz > 0) {
762  int32_t compare_diff = tmp -
763  cp->reg[COP0_COMPARE];
764  double hz;
765 
766  if (compare_diff < 0)
767  hz = tmp - cp->reg[COP0_COUNT];
768 
769  if (compare_diff == 0)
770  hz = 0;
771  else
772  hz = (double)cpu->machine->emulated_hz
773  / (double)compare_diff;
774 
775  /* Initialize or re-set the periodic timer: */
776  if (hz > 0) {
777  if (cpu->cd.mips.timer == NULL)
778  cpu->cd.mips.timer = timer_add(
779  hz, mips_timer_tick, cpu);
780  else
782  cpu->cd.mips.timer, hz);
783  }
784  }
785 
786  /* Ack the periodic timer, if it was asserted: */
787  if (cp->reg[COP0_CAUSE] & 0x8000 &&
790 
791  /* Clear the timer interrupt assertion (bit 7): */
792  cp->reg[COP0_CAUSE] &= ~0x8000;
793 
794  if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
795  fatal("[ WARNING: trying to write a 64-bit value"
796  " to the COMPARE register! ]\n");
797 
798  tmp = (int64_t)(int32_t)tmp;
799  cpu->cd.mips.compare_register_set = 1;
800  unimpl = 0;
801  break;
802  case COP0_ENTRYHI:
803  /*
804  * Translation caches must be invalidated if the
805  * ASID changes:
806  */
807  switch (cpu->cd.mips.cpu_type.mmu_model) {
808  case MMU3K:
809  old_asid = cp->reg[COP0_ENTRYHI] &
811  if ((cp->reg[COP0_ENTRYHI] &
813  (tmp & R2K3K_ENTRYHI_ASID_MASK))
814  inval = 1;
815  break;
816  default:
817  old_asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
818  if ((cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID) !=
819  (tmp & ENTRYHI_ASID))
820  inval = 1;
821  break;
822  }
823 
824  if (inval)
825  invalidate_asid(cpu, old_asid);
826 
827  unimpl = 0;
828  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
829  (tmp & 0x3f)!=0) {
830  /* char *symbol;
831  uint64_t offset;
832  symbol = get_symbol_name(cpu->pc,
833  &offset);
834  fatal("YO! pc = 0x%08llx <%s> "
835  "hi=%016llx\n", (long long)cpu->pc,
836  symbol? symbol :
837  "no symbol", (long long)tmp); */
838  tmp &= ~0x3f;
839  }
840  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
841  tmp &= (R2K3K_ENTRYHI_VPN_MASK |
843  else if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
844  tmp &= (ENTRYHI_R_MASK |
846  else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
848  0x1800 | ENTRYHI_ASID);
849  else
851  ENTRYHI_ASID);
852  break;
853  case COP0_EPC:
854  unimpl = 0;
855  break;
856  case COP0_PRID:
857  readonly = 1;
858  break;
859  case COP0_CONFIG:
860  if (select > 0) {
861  switch (select) {
862  case 1: cpu->cd.mips.cop0_config_select1 = tmp;
863  break;
864  default:fatal("[ coproc_register_write(): unimpl"
865  "emented config register select "
866  "%i ]\n", select);
867  exit(1);
868  }
869  return;
870  }
871 
872  /* fatal("COP0_CONFIG: modifying K0 bits: "
873  "0x%08x => ", cp->reg[reg_nr]); */
874  tmp = *ptr;
875  tmp &= 0x3; /* only bits 2..0 can be written */
876  cp->reg[reg_nr] &= ~(0x3); cp->reg[reg_nr] |= tmp;
877  /* fatal("0x%08x\n", cp->reg[reg_nr]); */
878  return;
879  case COP0_STATUS:
880  oldmode = cp->reg[COP0_STATUS];
881  tmp &= ~(1 << 21); /* bit 21 is read-only */
882 
883  /*
884  * When isolating caches, invalidate all translations.
885  * During the isolation, a special hack in memory_rw.c
886  * prevents translation tables from being updated, so
887  * the translation caches don't have to be invalidated
888  * when switching back to normal mode.
889  */
890  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
891  (oldmode & MIPS1_ISOL_CACHES) !=
892  (tmp & MIPS1_ISOL_CACHES)) {
893  /* Invalidate everything if we are switching
894  to isolated mode: */
895  if (tmp & MIPS1_ISOL_CACHES) {
897  cpu, 0, INVALIDATE_ALL);
898  }
899  }
900  unimpl = 0;
901  break;
902  case COP0_CAUSE:
903  /* A write to the cause register only
904  affects IM bits 0 and 1: */
905  cp->reg[reg_nr] &= ~(0x3 << STATUS_IM_SHIFT);
906  cp->reg[reg_nr] |= (tmp & (0x3 << STATUS_IM_SHIFT));
907  return;
908  case COP0_FRAMEMASK:
909  /* TODO: R10000 */
910  unimpl = 0;
911  break;
912  case COP0_TAGDATA_LO:
913  case COP0_TAGDATA_HI:
914  /* TODO: R4300 and others? */
915  unimpl = 0;
916  break;
917  case COP0_LLADDR:
918  unimpl = 0;
919  break;
920  case COP0_WATCHLO:
921  case COP0_WATCHHI:
922  unimpl = 0;
923  break;
924  case COP0_XCONTEXT:
925  /*
926  * TODO: According to the R10000 manual, the R4400
927  * shares the PTEbase portion of the context registers
928  * (that is, xcontext and context). On R10000, they
929  * are separate registers.
930  */
931  /* debug("[ xcontext 0x%016llx ]\n", tmp); */
932  unimpl = 0;
933  break;
934 
935  /* Most of these are actually TODOs: */
936  case COP0_ERROREPC:
937  case COP0_DEPC:
938  case COP0_RESERV22: /* Used by Linux on Linksys WRT54G */
939  case COP0_DESAVE:
940  case COP0_PERFCNT:
941  case COP0_ERRCTL: /* R10000 */
942  unimpl = 0;
943  break;
944  }
945  break;
946 
947  case 1:
948  /* COPROC 1: */
949  unimpl = 0;
950  break;
951  }
952 
953  if (unimpl) {
954  fatal("[ cpu%i: warning: write to unimplemented coproc%i "
955  "register %i (%s), data = 0x%016llx ]\n", cpu->cpu_id,
956  cp->coproc_nr, reg_nr, cp->coproc_nr==0?
957  cop0_names[reg_nr] : "?", (long long)tmp);
958 
959  /* mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
960  cp->coproc_nr, 0, 0, 0);
961  return; */
962  }
963 
964  if (readonly) {
965  fatal("[ cpu%i: warning: write to READONLY coproc%i register "
966  "%i ignored ]\n", cpu->cpu_id, cp->coproc_nr, reg_nr);
967  return;
968  }
969 
970  cp->reg[reg_nr] = tmp;
971 
972  if (!flag64)
973  cp->reg[reg_nr] = (int64_t)(int32_t)cp->reg[reg_nr];
974 }
975 
976 
977 /*
978  * MIPS floating-point stuff:
979  *
980  * TODO: Move this to some other file?
981  */
982 static int mips_fmt_to_ieee_fmt[32] = {
983  0, 0, 0, 0, 0, 0, 0, 0,
984  0, 0, 0, 0, 0, 0, 0, 0,
985  IEEE_FMT_S, IEEE_FMT_D, 0, 0,
986  IEEE_FMT_W, IEEE_FMT_L, /* PS (Paired Single) */ 0, 0,
987  0, 0, 0, 0, 0, 0, 0, 0 };
988 
989 static const char *fmtname[32] = {
990  "0", "1", "2", "3", "4", "5", "6", "7",
991  "8", "9", "10", "11", "12", "13", "14", "15",
992  "s", "d", "18", "19", "w", "l", "ps", "23",
993  "24", "25", "26", "27", "28", "29", "30", "31" };
994 
995 static const char *ccname[16] = {
996  "f", "un", "eq", "ueq", "olt", "ult", "ole", "ule",
997  "sf", "ngle", "seq", "ngl", "lt", "nge", "le", "ngt" };
998 
999 #define FPU_OP_ADD 1
1000 #define FPU_OP_SUB 2
1001 #define FPU_OP_MUL 3
1002 #define FPU_OP_DIV 4
1003 #define FPU_OP_SQRT 5
1004 #define FPU_OP_MOV 6
1005 #define FPU_OP_CVT 7
1006 #define FPU_OP_C 8
1007 #define FPU_OP_ABS 9
1008 #define FPU_OP_NEG 10
1009 /* TODO: CEIL.L, CEIL.W, FLOOR.L, FLOOR.W, RECIP, ROUND.L, ROUND.W, RSQRT */
1010 
1011 
1012 /*
1013  * fpu_store_float_value():
1014  *
1015  * Stores a float value (actually a double) in fmt format.
1016  */
1017 static void fpu_store_float_value(struct mips_coproc *cp, int fd,
1018  double nf, int fmt, int nan)
1019 {
1020  int ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1021  uint64_t r = ieee_store_float_value(nf, ieee_fmt, nan);
1022 
1023  /*
1024  * TODO: This is for 32-bit mode. It has to be updated later
1025  * for 64-bit coprocessor functionality!
1026  */
1027  if (fmt == COP1_FMT_D || fmt == COP1_FMT_L) {
1028  cp->reg[fd] = r & 0xffffffffULL;
1029  cp->reg[(fd+1) & 31] = (r >> 32) & 0xffffffffULL;
1030 
1031  if (cp->reg[fd] & 0x80000000ULL)
1032  cp->reg[fd] |= 0xffffffff00000000ULL;
1033  if (cp->reg[fd+1] & 0x80000000ULL)
1034  cp->reg[fd+1] |= 0xffffffff00000000ULL;
1035  } else {
1036  cp->reg[fd] = r & 0xffffffffULL;
1037 
1038  if (cp->reg[fd] & 0x80000000ULL)
1039  cp->reg[fd] |= 0xffffffff00000000ULL;
1040  }
1041 }
1042 
1043 
1044 /*
1045  * fpu_op():
1046  *
1047  * Perform a floating-point operation. For those of fs and ft that are >= 0,
1048  * those numbers are interpreted into local variables.
1049  *
1050  * Only FPU_OP_C (compare) returns anything of interest, 1 for true, 0 for
1051  * false.
1052  */
1053 static int fpu_op(struct cpu *cpu, struct mips_coproc *cp, int op, int fmt,
1054  int ft, int fs, int fd, int cond, int output_fmt)
1055 {
1056  /* Potentially two input registers, fs and ft */
1057  struct ieee_float_value float_value[2];
1058  int unordered, nan, ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1059  uint64_t fs_v = 0;
1060  double nf;
1061 
1062  if (fs >= 0) {
1063  fs_v = cp->reg[fs];
1064  /* TODO: register-pair mode and plain
1065  register mode? "FR" bit? */
1066  if (fmt == COP1_FMT_D || fmt == COP1_FMT_L)
1067  fs_v = (fs_v & 0xffffffffULL) +
1068  (cp->reg[(fs + 1) & 31] << 32);
1069  ieee_interpret_float_value(fs_v, &float_value[0], ieee_fmt);
1070  }
1071  if (ft >= 0) {
1072  uint64_t v = cp->reg[ft];
1073  /* TODO: register-pair mode and
1074  plain register mode? "FR" bit? */
1075  if (fmt == COP1_FMT_D || fmt == COP1_FMT_L)
1076  v = (v & 0xffffffffULL) +
1077  (cp->reg[(ft + 1) & 31] << 32);
1078  ieee_interpret_float_value(v, &float_value[1], ieee_fmt);
1079  }
1080 
1081  switch (op) {
1082  case FPU_OP_ADD:
1083  nf = float_value[0].f + float_value[1].f;
1084  /* debug(" add: %f + %f = %f\n",
1085  float_value[0].f, float_value[1].f, nf); */
1086  fpu_store_float_value(cp, fd, nf, output_fmt,
1087  float_value[0].nan || float_value[1].nan);
1088  break;
1089  case FPU_OP_SUB:
1090  nf = float_value[0].f - float_value[1].f;
1091  /* debug(" sub: %f - %f = %f\n",
1092  float_value[0].f, float_value[1].f, nf); */
1093  fpu_store_float_value(cp, fd, nf, output_fmt,
1094  float_value[0].nan || float_value[1].nan);
1095  break;
1096  case FPU_OP_MUL:
1097  nf = float_value[0].f * float_value[1].f;
1098  /* debug(" mul: %f * %f = %f\n",
1099  float_value[0].f, float_value[1].f, nf); */
1100  fpu_store_float_value(cp, fd, nf, output_fmt,
1101  float_value[0].nan || float_value[1].nan);
1102  break;
1103  case FPU_OP_DIV:
1104  nan = float_value[0].nan || float_value[1].nan;
1105  if (fabs(float_value[1].f) > 0.00000000001)
1106  nf = float_value[0].f / float_value[1].f;
1107  else {
1108  fatal("DIV by zero !!!! TODO\n");
1109  // nf = 0.0; /* TODO */
1110  // nan = 1;
1111  mips_cpu_exception(cpu, EXCEPTION_FPE, 0, 0, 1, 0, 0, 0);
1112  return 0;
1113  }
1114  /* debug(" div: %f / %f = %f\n",
1115  float_value[0].f, float_value[1].f, nf); */
1116  fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1117  break;
1118  case FPU_OP_SQRT:
1119  nan = float_value[0].nan;
1120  if (float_value[0].f >= 0.0)
1121  nf = sqrt(float_value[0].f);
1122  else {
1123  fatal("SQRT by less than zero, %f !!!!\n",
1124  float_value[0].f);
1125  nf = 0.0; /* TODO */
1126  nan = 1;
1127  }
1128  /* debug(" sqrt: %f => %f\n", float_value[0].f, nf); */
1129  fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1130  break;
1131  case FPU_OP_ABS:
1132  nf = fabs(float_value[0].f);
1133  /* debug(" abs: %f => %f\n", float_value[0].f, nf); */
1134  fpu_store_float_value(cp, fd, nf, output_fmt,
1135  float_value[0].nan);
1136  break;
1137  case FPU_OP_NEG:
1138  nf = - float_value[0].f;
1139  /* debug(" neg: %f => %f\n", float_value[0].f, nf); */
1140  fpu_store_float_value(cp, fd, nf, output_fmt,
1141  float_value[0].nan);
1142  break;
1143  case FPU_OP_CVT:
1144  nf = float_value[0].f;
1145  /* debug(" mov: %f => %f\n", float_value[0].f, nf); */
1146  fpu_store_float_value(cp, fd, nf, output_fmt,
1147  float_value[0].nan);
1148  break;
1149  case FPU_OP_MOV:
1150  /* Non-arithmetic move: */
1151  /*
1152  * TODO: this is for 32-bit mode. It has to be updated later
1153  * for 64-bit coprocessor stuff.
1154  */
1155  if (output_fmt == COP1_FMT_D || output_fmt == COP1_FMT_L) {
1156  cp->reg[fd] = fs_v & 0xffffffffULL;
1157  cp->reg[(fd+1) & 31] = (fs_v >> 32) & 0xffffffffULL;
1158  if (cp->reg[fd] & 0x80000000ULL)
1159  cp->reg[fd] |= 0xffffffff00000000ULL;
1160  if (cp->reg[fd+1] & 0x80000000ULL)
1161  cp->reg[fd+1] |= 0xffffffff00000000ULL;
1162  } else {
1163  cp->reg[fd] = fs_v & 0xffffffffULL;
1164  if (cp->reg[fd] & 0x80000000ULL)
1165  cp->reg[fd] |= 0xffffffff00000000ULL;
1166  }
1167  break;
1168  case FPU_OP_C:
1169  /* debug(" c: cond=%i\n", cond); */
1170 
1171  unordered = 0;
1172  if (float_value[0].nan || float_value[1].nan)
1173  unordered = 1;
1174 
1175  switch (cond) {
1176  case 2: /* Equal */
1177  return (float_value[0].f == float_value[1].f);
1178  case 4: /* Ordered or Less than */
1179  return (float_value[0].f < float_value[1].f)
1180  || !unordered;
1181  case 5: /* Unordered or Less than */
1182  return (float_value[0].f < float_value[1].f)
1183  || unordered;
1184  case 6: /* Ordered or Less than or Equal */
1185  return (float_value[0].f <= float_value[1].f)
1186  || !unordered;
1187  case 7: /* Unordered or Less than or Equal */
1188  return (float_value[0].f <= float_value[1].f)
1189  || unordered;
1190  case 12:/* Less than */
1191  return (float_value[0].f < float_value[1].f);
1192  case 14:/* Less than or equal */
1193  return (float_value[0].f <= float_value[1].f);
1194 
1195  /* The following are not commonly used, so I'll move these out
1196  of the if-0 on a case-by-case basis. */
1197 #if 0
1198 case 0: return 0; /* False */
1199 case 1: return 0; /* Unordered */
1200 case 3: return (float_value[0].f == float_value[1].f);
1201  /* Unordered or Equal */
1202 case 8: return 0; /* Signaling false */
1203 case 9: return 0; /* Not Greater than or Less than or Equal */
1204 case 10:return (float_value[0].f == float_value[1].f); /* Signaling Equal */
1205 case 11:return (float_value[0].f == float_value[1].f); /* Not Greater
1206  than or Less than */
1207 case 13:return !(float_value[0].f >= float_value[1].f); /* Not greater
1208  than or equal */
1209 case 15:return !(float_value[0].f > float_value[1].f); /* Not greater than */
1210 #endif
1211 
1212  default:
1213  fatal("fpu_op(): unimplemented condition "
1214  "code %i. see cpu_mips_coproc.c\n", cond);
1215  }
1216  break;
1217  default:
1218  fatal("fpu_op(): unimplemented op %i\n", op);
1219  }
1220 
1221  return 0;
1222 }
1223 
1224 
1225 /*
1226  * fpu_function():
1227  *
1228  * Returns 1 if function was implemented, 0 otherwise.
1229  * Debug trace should be printed for known instructions.
1230  */
1231 static int fpu_function(struct cpu *cpu, struct mips_coproc *cp,
1232  uint32_t function, int unassemble_only)
1233 {
1234  int fd, fs, ft, fmt, cond, cc;
1235 
1236  fmt = (function >> 21) & 31;
1237  ft = (function >> 16) & 31;
1238  fs = (function >> 11) & 31;
1239  cc = (function >> 8) & 7;
1240  fd = (function >> 6) & 31;
1241  cond = (function >> 0) & 15;
1242 
1243 
1244  /* bc1f, bc1t, bc1fl, bc1tl: */
1245  if ((function & 0x03e00000) == 0x01000000) {
1246  int nd, tf, imm;
1247  const char *instr_mnem;
1248 
1249  /* cc are bits 20..18: */
1250  cc = (function >> 18) & 7;
1251  nd = (function >> 17) & 1;
1252  tf = (function >> 16) & 1;
1253  imm = function & 65535;
1254  if (imm >= 32768)
1255  imm -= 65536;
1256 
1257  instr_mnem = NULL;
1258  if (nd == 0 && tf == 0) instr_mnem = "bc1f";
1259  if (nd == 0 && tf == 1) instr_mnem = "bc1t";
1260  if (nd == 1 && tf == 0) instr_mnem = "bc1fl";
1261  if (nd == 1 && tf == 1) instr_mnem = "bc1tl";
1262 
1263  if (cpu->machine->instruction_trace || unassemble_only)
1264  debug("%s\t%i,0x%016llx\n", instr_mnem, cc,
1265  (long long) (cpu->pc + 4 + (imm << 2)));
1266  if (unassemble_only)
1267  return 1;
1268 
1269  fatal("INTERNAL ERROR: MIPS coprocessor branches should not"
1270  " be implemented in cpu_mips_coproc.c, but in"
1271  " cpu_mips_instr.c!\n");
1272  exit(1);
1273  }
1274 
1275  /* add.fmt: Floating-point add */
1276  if ((function & 0x0000003f) == 0x00000000) {
1277  if (cpu->machine->instruction_trace || unassemble_only)
1278  debug("add.%s\tr%i,r%i,r%i\n",
1279  fmtname[fmt], fd, fs, ft);
1280  if (unassemble_only)
1281  return 1;
1282 
1283  fpu_op(cpu, cp, FPU_OP_ADD, fmt, ft, fs, fd, -1, fmt);
1284  return 1;
1285  }
1286 
1287  /* sub.fmt: Floating-point subtract */
1288  if ((function & 0x0000003f) == 0x00000001) {
1289  if (cpu->machine->instruction_trace || unassemble_only)
1290  debug("sub.%s\tr%i,r%i,r%i\n",
1291  fmtname[fmt], fd, fs, ft);
1292  if (unassemble_only)
1293  return 1;
1294 
1295  fpu_op(cpu, cp, FPU_OP_SUB, fmt, ft, fs, fd, -1, fmt);
1296  return 1;
1297  }
1298 
1299  /* mul.fmt: Floating-point multiply */
1300  if ((function & 0x0000003f) == 0x00000002) {
1301  if (cpu->machine->instruction_trace || unassemble_only)
1302  debug("mul.%s\tr%i,r%i,r%i\n",
1303  fmtname[fmt], fd, fs, ft);
1304  if (unassemble_only)
1305  return 1;
1306 
1307  fpu_op(cpu, cp, FPU_OP_MUL, fmt, ft, fs, fd, -1, fmt);
1308  return 1;
1309  }
1310 
1311  /* div.fmt: Floating-point divide */
1312  if ((function & 0x0000003f) == 0x00000003) {
1313  if (cpu->machine->instruction_trace || unassemble_only)
1314  debug("div.%s\tr%i,r%i,r%i\n",
1315  fmtname[fmt], fd, fs, ft);
1316  if (unassemble_only)
1317  return 1;
1318 
1319  fpu_op(cpu, cp, FPU_OP_DIV, fmt, ft, fs, fd, -1, fmt);
1320  return 1;
1321  }
1322 
1323  /* sqrt.fmt: Floating-point square-root */
1324  if ((function & 0x001f003f) == 0x00000004) {
1325  if (cpu->machine->instruction_trace || unassemble_only)
1326  debug("sqrt.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1327  if (unassemble_only)
1328  return 1;
1329 
1330  fpu_op(cpu, cp, FPU_OP_SQRT, fmt, -1, fs, fd, -1, fmt);
1331  return 1;
1332  }
1333 
1334  /* abs.fmt: Floating-point absolute value */
1335  if ((function & 0x001f003f) == 0x00000005) {
1336  if (cpu->machine->instruction_trace || unassemble_only)
1337  debug("abs.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1338  if (unassemble_only)
1339  return 1;
1340 
1341  fpu_op(cpu, cp, FPU_OP_ABS, fmt, -1, fs, fd, -1, fmt);
1342  return 1;
1343  }
1344 
1345  /* mov.fmt: Floating-point (non-arithmetic) move */
1346  if ((function & 0x0000003f) == 0x00000006) {
1347  if (cpu->machine->instruction_trace || unassemble_only)
1348  debug("mov.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1349  if (unassemble_only)
1350  return 1;
1351 
1352  fpu_op(cpu, cp, FPU_OP_MOV, fmt, -1, fs, fd, -1, fmt);
1353  return 1;
1354  }
1355 
1356  /* neg.fmt: Floating-point negate */
1357  if ((function & 0x001f003f) == 0x00000007) {
1358  if (cpu->machine->instruction_trace || unassemble_only)
1359  debug("neg.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1360  if (unassemble_only)
1361  return 1;
1362 
1363  fpu_op(cpu, cp, FPU_OP_NEG, fmt, -1, fs, fd, -1, fmt);
1364  return 1;
1365  }
1366 
1367  /* trunc.l.fmt: Truncate */
1368  if ((function & 0x001f003f) == 0x00000009) {
1369  if (cpu->machine->instruction_trace || unassemble_only)
1370  debug("trunc.l.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1371  if (unassemble_only)
1372  return 1;
1373 
1374  /* TODO: not CVT? */
1375 
1376  fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_L);
1377  return 1;
1378  }
1379 
1380  /* trunc.w.fmt: Truncate */
1381  if ((function & 0x001f003f) == 0x0000000d) {
1382  if (cpu->machine->instruction_trace || unassemble_only)
1383  debug("trunc.w.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1384  if (unassemble_only)
1385  return 1;
1386 
1387  /* TODO: not CVT? */
1388 
1389  fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_W);
1390  return 1;
1391  }
1392 
1393  /* c.cond.fmt: Floating-point compare */
1394  if ((function & 0x000000f0) == 0x00000030) {
1395  int cond_true;
1396  int bit;
1397 
1398  if (cpu->machine->instruction_trace || unassemble_only)
1399  debug("c.%s.%s\tcc%i,r%i,r%i\n", ccname[cond],
1400  fmtname[fmt], cc, fs, ft);
1401  if (unassemble_only)
1402  return 1;
1403 
1404  cond_true = fpu_op(cpu, cp, FPU_OP_C, fmt,
1405  ft, fs, -1, cond, fmt);
1406 
1407  /*
1408  * Both the FCCR and FCSR contain condition code bits:
1409  * FCCR: bits 7..0
1410  * FCSR: bits 31..25 and 23
1411  */
1412  cp->fcr[MIPS_FPU_FCCR] &= ~(1 << cc);
1413  if (cond_true)
1414  cp->fcr[MIPS_FPU_FCCR] |= (1 << cc);
1415 
1416  if (cc == 0) {
1417  bit = 1 << MIPS_FCSR_FCC0_SHIFT;
1418  cp->fcr[MIPS_FPU_FCSR] &= ~bit;
1419  if (cond_true)
1420  cp->fcr[MIPS_FPU_FCSR] |= bit;
1421  } else {
1422  bit = 1 << (MIPS_FCSR_FCC1_SHIFT + cc-1);
1423  cp->fcr[MIPS_FPU_FCSR] &= ~bit;
1424  if (cond_true)
1425  cp->fcr[MIPS_FPU_FCSR] |= bit;
1426  }
1427 
1428  return 1;
1429  }
1430 
1431  /* cvt.s.fmt: Convert to single floating-point */
1432  if ((function & 0x001f003f) == 0x00000020) {
1433  if (cpu->machine->instruction_trace || unassemble_only)
1434  debug("cvt.s.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1435  if (unassemble_only)
1436  return 1;
1437 
1438  fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_S);
1439  return 1;
1440  }
1441 
1442  /* cvt.d.fmt: Convert to double floating-point */
1443  if ((function & 0x001f003f) == 0x00000021) {
1444  if (cpu->machine->instruction_trace || unassemble_only)
1445  debug("cvt.d.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1446  if (unassemble_only)
1447  return 1;
1448 
1449  fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_D);
1450  return 1;
1451  }
1452 
1453  /* cvt.w.fmt: Convert to word fixed-point */
1454  if ((function & 0x001f003f) == 0x00000024) {
1455  if (cpu->machine->instruction_trace || unassemble_only)
1456  debug("cvt.w.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1457  if (unassemble_only)
1458  return 1;
1459 
1460  fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, COP1_FMT_W);
1461  return 1;
1462  }
1463 
1464  return 0;
1465 }
1466 
1467 
1468 /*
1469  * coproc_tlbpr():
1470  *
1471  * 'tlbp' and 'tlbr'.
1472  */
1473 void coproc_tlbpr(struct cpu *cpu, int readflag)
1474 {
1475  struct mips_coproc *cp = cpu->cd.mips.coproc[0];
1476  int i, found, g_bit;
1477  uint64_t vpn2, xmask;
1478 
1479  /* Read: */
1480  if (readflag) {
1481  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1482  i = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK) >>
1484  if (i >= cp->nr_of_tlbs) {
1485  /* TODO: exception? */
1486  fatal("[ warning: tlbr from index %i (too "
1487  "high) ]\n", i);
1488  return;
1489  }
1490 
1491  cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi;
1492  cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;
1493  } else {
1494  /* R4000: */
1495  i = cp->reg[COP0_INDEX] & INDEX_MASK;
1496  if (i >= cp->nr_of_tlbs) {
1497  /* TODO: exception? */
1498  fatal("[ warning: tlbr from index %i (too "
1499  "high) ]\n", i);
1500  return;
1501  }
1502 
1503  cp->reg[COP0_PAGEMASK] = cp->tlbs[i].mask;
1504  cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi;
1505  cp->reg[COP0_ENTRYLO1] = cp->tlbs[i].lo1;
1506  cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;
1507 
1508  if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1509  /* R4100 don't have the G bit in entryhi */
1510  } else {
1511  /* R4000 etc: */
1512  cp->reg[COP0_ENTRYHI] &= ~TLB_G;
1513  g_bit = cp->tlbs[i].hi & TLB_G;
1514 
1515  cp->reg[COP0_ENTRYLO0] &= ~ENTRYLO_G;
1516  cp->reg[COP0_ENTRYLO1] &= ~ENTRYLO_G;
1517  if (g_bit) {
1518  cp->reg[COP0_ENTRYLO0] |= ENTRYLO_G;
1519  cp->reg[COP0_ENTRYLO1] |= ENTRYLO_G;
1520  }
1521  }
1522  }
1523 
1524  return;
1525  }
1526 
1527  /* Probe: */
1528  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1529  vpn2 = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
1530  found = -1;
1531  for (i=0; i<cp->nr_of_tlbs; i++)
1532  if ( ((cp->tlbs[i].hi & R2K3K_ENTRYHI_ASID_MASK) ==
1533  (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK))
1534  || cp->tlbs[i].lo0 & R2K3K_ENTRYLO_G)
1535  if ((cp->tlbs[i].hi & R2K3K_ENTRYHI_VPN_MASK)
1536  == vpn2) {
1537  found = i;
1538  break;
1539  }
1540  } else {
1541  /* R4000 and R10000: */
1542  if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1544  else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
1545  xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800;
1546  else
1548  vpn2 = cp->reg[COP0_ENTRYHI] & xmask;
1549 
1550  found = -1;
1551  for (i=0; i<cp->nr_of_tlbs; i++) {
1552  int gbit = cp->tlbs[i].hi & TLB_G;
1553  if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
1554  gbit = (cp->tlbs[i].lo0 & ENTRYLO_G) &&
1555  (cp->tlbs[i].lo1 & ENTRYLO_G);
1556 
1557  if ( ((cp->tlbs[i].hi & ENTRYHI_ASID) ==
1558  (cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID)) || gbit) {
1559  uint64_t a = vpn2 & ~cp->tlbs[i].mask;
1560  uint64_t b = (cp->tlbs[i].hi & xmask) &
1561  ~cp->tlbs[i].mask;
1562  if (a == b) {
1563  found = i;
1564  break;
1565  }
1566  }
1567  }
1568  }
1569 
1570  if (found == -1)
1571  cp->reg[COP0_INDEX] = INDEX_P;
1572  else {
1573  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1574  cp->reg[COP0_INDEX] = found << R2K3K_INDEX_SHIFT;
1575  else
1576  cp->reg[COP0_INDEX] = found;
1577  }
1578 
1579  /* Sign extend the index register: */
1580  if ((cp->reg[COP0_INDEX] >> 32) == 0 &&
1581  cp->reg[COP0_INDEX] & 0x80000000)
1582  cp->reg[COP0_INDEX] |=
1583  0xffffffff00000000ULL;
1584 }
1585 
1586 
1587 /*
1588  * coproc_tlbwri():
1589  *
1590  * MIPS TLB write random (tlbwr) and write indexed (tlbwi) instructions.
1591  */
1592 void coproc_tlbwri(struct cpu *cpu, int randomflag)
1593 {
1594  struct mips_coproc *cp = cpu->cd.mips.coproc[0];
1595  int index, g_bit;
1596  uint64_t oldvaddr;
1597 
1598  if (randomflag) {
1599  if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1600  index = ((cp->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
1601  >> R2K3K_RANDOM_SHIFT) - 1;
1602  /* R3000 always has 8 wired entries: */
1603  if (index < 8)
1604  index = cp->nr_of_tlbs - 1;
1605  cp->reg[COP0_RANDOM] = index << R2K3K_RANDOM_SHIFT;
1606  } else {
1607  cp->reg[COP0_RANDOM] = cp->reg[COP0_WIRED] + (random()
1608  % (cp->nr_of_tlbs - cp->reg[COP0_WIRED]));
1609  index = cp->reg[COP0_RANDOM] & RANDOM_MASK;
1610  }
1611  } else {
1612  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1613  index = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
1614  >> R2K3K_INDEX_SHIFT;
1615  else
1616  index = cp->reg[COP0_INDEX] & INDEX_MASK;
1617  }
1618 
1619  if (index >= cp->nr_of_tlbs) {
1620  fatal("warning: tlb index %i too high (max is %i)\n",
1621  index, cp->nr_of_tlbs - 1);
1622  /* TODO: cause an exception? */
1623  return;
1624  }
1625 
1626 
1627 #if 0
1628  /* Debug dump of the previous entry at that index: */
1629  fatal("{ old TLB entry at index %02x:", index);
1630  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1631  fatal(" hi=%08" PRIx32, (uint32_t)cp->tlbs[index].hi);
1632  fatal(" lo=%08" PRIx32, (uint32_t)cp->tlbs[index].lo0);
1633  } else {
1634  if (cpu->is_32bit) {
1635  fatal(" mask=%08" PRIx32,(uint32_t)cp->tlbs[index].mask);
1636  fatal(" hi=%08" PRIx32, (uint32_t)cp->tlbs[index].hi);
1637  fatal(" lo0=%08" PRIx32, (uint32_t)cp->tlbs[index].lo0);
1638  fatal(" lo1=%08" PRIx32, (uint32_t)cp->tlbs[index].lo1);
1639  } else {
1640  fatal(" mask=%016" PRIx64, cp->tlbs[index].mask);
1641  fatal(" hi=%016" PRIx64, cp->tlbs[index].hi);
1642  fatal(" lo0=%016" PRIx64, cp->tlbs[index].lo0);
1643  fatal(" lo1=%016" PRIx64, cp->tlbs[index].lo1);
1644  }
1645  }
1646  fatal(" }\n");
1647 #endif
1648 
1649  /*
1650  * Any virtual address translation for the old TLB entry must be
1651  * invalidated first:
1652  *
1653  * (Only Valid entries need to be invalidated, and only those that
1654  * are either Global, or have the same ASID as the new entry will
1655  * have. No other address translations should be active anyway.)
1656  */
1657 
1658  switch (cpu->cd.mips.cpu_type.mmu_model) {
1659 
1660  case MMU3K:
1661  oldvaddr = cp->tlbs[index].hi & R2K3K_ENTRYHI_VPN_MASK;
1662  oldvaddr = (int32_t) oldvaddr;
1663 
1664  if (cp->tlbs[index].lo0 & R2K3K_ENTRYLO_V &&
1665  (cp->tlbs[index].lo0 & R2K3K_ENTRYLO_G ||
1666  (cp->tlbs[index].hi & R2K3K_ENTRYHI_ASID_MASK) ==
1667  (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK) ))
1668  cpu->invalidate_translation_caches(cpu, oldvaddr,
1670 
1671  break;
1672 
1673  default:if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1674  oldvaddr = cp->tlbs[index].hi &
1676  /* 44 addressable bits: */
1677  if (oldvaddr & 0x80000000000ULL)
1678  oldvaddr |= 0x3ffff00000000000ULL;
1679  } else if (cpu->is_32bit) {
1680  /* MIPS32 etc.: */
1681  oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1682  oldvaddr = (int32_t)oldvaddr;
1683  } else {
1684  /* Assume MMU4K */
1685  oldvaddr = cp->tlbs[index].hi &
1687  /* 40 addressable bits: */
1688  if (oldvaddr & 0x8000000000ULL)
1689  oldvaddr |= 0x3fffff0000000000ULL;
1690  }
1691 
1692  {
1693  uint64_t mask = cp->tlbs[index].mask;
1694  uint64_t pagesize = 0x1000;
1695  uint64_t tmp = mask >> 13;
1696  while ((tmp & 1)) {
1697  tmp >>= 1;
1698  pagesize <<= 1;
1699  }
1700 
1701  mask |= 0x1fff;
1702  oldvaddr &= ~mask;
1703 
1704  // printf("pagesize = %016llx mask = %016llx\n", pagesize, mask);
1705 
1706  if (cp->tlbs[index].lo0 & ENTRYLO_V)
1707  for (uint64_t ofs = 0; ofs < pagesize; ofs += 0x1000)
1708  cpu->invalidate_translation_caches(cpu, oldvaddr + ofs, INVALIDATE_VADDR);
1709 
1710  if (cp->tlbs[index].lo1 & ENTRYLO_V)
1711  for (uint64_t ofs = 0; ofs < pagesize; ofs += 0x1000)
1712  cpu->invalidate_translation_caches(cpu, oldvaddr + ofs + pagesize, INVALIDATE_VADDR);
1713  }
1714  }
1715 
1716 #if 0
1717  /*
1718  * Check for duplicate entries. (There should not be two mappings
1719  * from one virtual address to physical addresses.)
1720  *
1721  * TODO: Do this for MMU3K and R4100 too.
1722  *
1723  * TODO: Make this detection more robust.
1724  */
1725  if (cpu->cd.mips.cpu_type.mmu_model != MMU3K &&
1726  cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
1727  uint64_t vaddr1, vaddr2;
1728  int i;
1729  unsigned int asid;
1730 
1731  vaddr1 = cp->reg[COP0_ENTRYHI] &
1733  asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
1734  /* Since this is just a warning, it's probably not necessary
1735  to use R4000 masks etc. */
1736 
1737  for (i=0; i<cp->nr_of_tlbs; i++) {
1738  if (i == index && !randomflag)
1739  continue;
1740 
1741  if (!(cp->tlbs[i].hi & TLB_G) &&
1742  (cp->tlbs[i].hi & ENTRYHI_ASID) != asid)
1743  continue;
1744 
1745  vaddr2 = cp->tlbs[i].hi &
1747  if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 &
1748  ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V)))
1749  fatal("\n[ WARNING! tlbw%s to index 0x%02x "
1750  "vaddr=0x%llx (asid 0x%02x) is already in"
1751  " the TLB (entry 0x%02x) ! ]\n\n",
1752  randomflag? "r" : "i", index,
1753  (long long)vaddr1, asid, i);
1754  }
1755  }
1756 #endif
1757 
1758  /* Write the new entry: */
1759 
1760  if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1761  uint32_t vaddr, paddr;
1762  int wf = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_D? 1 : 0;
1763  unsigned char *memblock = NULL;
1764 
1765  cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
1766  cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
1767 
1768  vaddr = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
1769  paddr = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_PFN_MASK;
1770 
1771  memblock = memory_paddr_to_hostaddr(cpu->mem, paddr, 0);
1772 
1773  /* Invalidate any code translation, if we are writing
1774  a Dirty page to the TLB: */
1775  if (wf) {
1776  cpu->invalidate_code_translation(cpu, paddr,
1778  }
1779 
1780  /* Set new last_written_tlb_index hint: */
1781  cpu->cd.mips.last_written_tlb_index = index;
1782 
1783  if (cp->reg[COP0_STATUS] & MIPS1_ISOL_CACHES) {
1784  fatal("Wow! Interesting case; tlbw* while caches"
1785  " are isolated. TODO\n");
1786  /* Don't update the translation table in this
1787  case... */
1788  exit(1);
1789  }
1790 
1791  /* If we have a memblock (host page) for the physical
1792  page, then add a translation for it immediately: */
1793  if (memblock != NULL &&
1795  cpu->update_translation_table(cpu, vaddr, memblock,
1796  wf, paddr);
1797  } else {
1798  /* R4000 etc.: */
1799  unsigned char *memblock = NULL;
1800  int pfn_shift = 12, vpn_shift = 12;
1801  int wf0, wf1, mask;
1802  uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp;
1803  uint64_t psize;
1804 
1805  cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];
1806  cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
1807  cp->tlbs[index].lo1 = cp->reg[COP0_ENTRYLO1];
1808  cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
1809 
1810  wf0 = cp->tlbs[index].lo0 & ENTRYLO_D;
1811  wf1 = cp->tlbs[index].lo1 & ENTRYLO_D;
1812 
1813  mask = cp->reg[COP0_PAGEMASK];
1814  if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1815  pfn_shift = 10;
1816  mask |= 0x07ff;
1817  } else {
1818  mask |= 0x1fff;
1819  }
1820  switch (mask) {
1821  case 0x00007ff:
1822  if (cp->tlbs[index].lo0 & ENTRYLO_V ||
1823  cp->tlbs[index].lo1 & ENTRYLO_V) {
1824  fatal("1KB pages don't work with dyntrans.\n");
1825  exit(1);
1826  }
1827  vpn_shift = 10;
1828  break;
1829  case 0x0001fff: break;
1830  case 0x0007fff: vpn_shift = 14; break;
1831  case 0x001ffff: vpn_shift = 16; break;
1832  case 0x007ffff: vpn_shift = 18; break;
1833  case 0x01fffff: vpn_shift = 20; break;
1834  case 0x07fffff: vpn_shift = 22; break;
1835  case 0x1ffffff: vpn_shift = 24; break;
1836  case 0x7ffffff: vpn_shift = 26; break;
1837  default:fatal("Unimplemented MASK = 0x%016x\n", mask);
1838  exit(1);
1839  }
1840 
1841  pfn_shift = vpn_shift;
1842 
1843  paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK)
1844  >> ENTRYLO_PFN_SHIFT) << pfn_shift
1845  >> vpn_shift << vpn_shift;
1846  paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK)
1847  >> ENTRYLO_PFN_SHIFT) << pfn_shift
1848  >> vpn_shift << vpn_shift;
1849 
1850  if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1851  vaddr0 = cp->tlbs[index].hi &
1853  /* 44 addressable bits: */
1854  if (vaddr0 & 0x80000000000ULL)
1855  vaddr0 |= 0x3ffff00000000000ULL;
1856  } else if (cpu->is_32bit) {
1857  /* MIPS32 etc.: */
1858  vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1859  vaddr0 = (int32_t)vaddr0;
1860  } else {
1861  /* Assume MMU4K */
1862  vaddr0 = cp->tlbs[index].hi &
1864  /* 40 addressable bits: */
1865  if (vaddr0 & 0x8000000000ULL)
1866  vaddr0 |= 0x3fffff0000000000ULL;
1867  }
1868 
1869  vaddr1 = vaddr0 | (1 << vpn_shift);
1870 
1871  g_bit = (cp->reg[COP0_ENTRYLO0] &
1872  cp->reg[COP0_ENTRYLO1]) & ENTRYLO_G;
1873 
1874  if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1875  /* NOTE: The VR4131 (and possibly others) don't have
1876  a Global bit in entryhi */
1877  cp->tlbs[index].hi &= ~cp->reg[COP0_PAGEMASK];
1878  } else {
1879  cp->tlbs[index].lo0 &= ~ENTRYLO_G;
1880  cp->tlbs[index].lo1 &= ~ENTRYLO_G;
1881 
1882  cp->tlbs[index].hi &= ~TLB_G;
1883  if (g_bit)
1884  cp->tlbs[index].hi |= TLB_G;
1885  }
1886 
1887  /*
1888  * Invalidate any code translations, if we are writing Dirty
1889  * pages to the TLB:
1890  */
1891  psize = 1 << pfn_shift;
1892 
1893  if (wf0) {
1894  for (ptmp = 0; ptmp < psize; ptmp += 0x1000)
1895  cpu->invalidate_code_translation(cpu,
1896  paddr0 + ptmp, INVALIDATE_PADDR);
1897  }
1898  if (wf1) {
1899  for (ptmp = 0; ptmp < psize; ptmp += 0x1000)
1900  cpu->invalidate_code_translation(cpu,
1901  paddr1 + ptmp, INVALIDATE_PADDR);
1902  }
1903 
1904  /*
1905  * If we have a memblock (host page) for the physical page,
1906  * then add a translation for it immediately, to save some
1907  * time. (It would otherwise be added later on anyway,
1908  * because of a translation miss.)
1909  *
1910  * NOTE/TODO: This is only for 4KB pages so far. It would
1911  * be too expensive to add e.g. 16MB pages like
1912  * this.
1913  */
1914  if (psize == 0x1000) {
1915  memblock = memory_paddr_to_hostaddr(cpu->mem, paddr0, 0);
1916  if (memblock != NULL && cp->reg[COP0_ENTRYLO0] & ENTRYLO_V)
1917  cpu->update_translation_table(cpu, vaddr0, memblock,
1918  wf0, paddr0);
1919  memblock = memory_paddr_to_hostaddr(cpu->mem, paddr1, 0);
1920  if (memblock != NULL && cp->reg[COP0_ENTRYLO1] & ENTRYLO_V)
1921  cpu->update_translation_table(cpu, vaddr1, memblock,
1922  wf1, paddr1);
1923  }
1924 
1925  /* Set new last_written_tlb_index hint: */
1926  cpu->cd.mips.last_written_tlb_index = index;
1927  }
1928 }
1929 
1930 
1931 /*
1932  * coproc_eret():
1933  *
1934  * Return from exception. (R4000 etc.)
1935  */
1936 void coproc_eret(struct cpu *cpu)
1937 {
1938  if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1939  cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1940  cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1941  } else {
1942  cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1943  cpu->delay_slot = 0;
1944  cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1945  }
1946 
1947  cpu->cd.mips.rmw = 0; /* the "LL bit" */
1948 }
1949 
1950 
1951 /*
1952  * coproc_function():
1953  *
1954  * Execute a coprocessor specific instruction. cp must be != NULL.
1955  * Debug trace should be printed for known instructions, if
1956  * unassemble_only is non-zero. (This will NOT execute the instruction.)
1957  *
1958  * TODO: This is a mess and should be restructured (again).
1959  */
1960 void coproc_function(struct cpu *cpu, struct mips_coproc *cp, int cpnr,
1961  uint32_t function, int unassemble_only, int running)
1962 {
1963  int co_bit, op, rt, rd, fs, copz;
1964  uint64_t tmpvalue;
1965 
1966  if (cp == NULL) {
1967  if (unassemble_only) {
1968  debug("cop%i\t0x%08x (coprocessor not available)\n",
1969  cpnr, (int)function);
1970  return;
1971  }
1972  fatal("[ pc=0x%016llx cop%i\t0x%08x (coprocessor not "
1973  "available)\n", (long long)cpu->pc, cpnr, (int)function);
1974  return;
1975  }
1976 
1977  /* No FPU? */
1978  if (cpnr == 1 && (cpu->cd.mips.cpu_type.flags & NOFPU)) {
1979  mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1980  return;
1981  }
1982 
1983  /* For quick reference: */
1984  copz = (function >> 21) & 31;
1985  rt = (function >> 16) & 31;
1986  rd = (function >> 11) & 31;
1987 
1988  if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21))
1989  || ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) {
1990  if (unassemble_only) {
1991  debug("%s%i\t%s,", copz==COPz_DMFCz? "dmfc" : "mfc",
1992  cpnr, regnames[rt]);
1993  if (cpnr == 0)
1994  debug("%s", cop0_names[rd]);
1995  else
1996  debug("r%i", rd);
1997  if (function & 7)
1998  debug(",%i", (int)(function & 7));
1999  debug("\n");
2000  return;
2001  }
2002  coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr],
2003  rd, &tmpvalue, function & 7);
2004  cpu->cd.mips.gpr[rt] = tmpvalue;
2005  if (copz == COPz_MFCz) {
2006  /* Sign-extend: */
2007  cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
2008  if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
2009  cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
2010  }
2011  return;
2012  }
2013 
2014  if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21))
2015  || ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) {
2016  if (unassemble_only) {
2017  debug("%s%i\t%s,", copz==COPz_DMTCz? "dmtc" : "mtc",
2018  cpnr, regnames[rt]);
2019  if (cpnr == 0)
2020  debug("%s", cop0_names[rd]);
2021  else
2022  debug("r%i", rd);
2023  if (function & 7)
2024  debug(",%i", (int)(function & 7));
2025  debug("\n");
2026  return;
2027  }
2028  tmpvalue = cpu->cd.mips.gpr[rt];
2029  if (copz == COPz_MTCz) {
2030  /* Sign-extend: */
2031  tmpvalue &= 0xffffffffULL;
2032  if (tmpvalue & 0x80000000ULL)
2033  tmpvalue |= 0xffffffff00000000ULL;
2034  }
2035  coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd,
2036  &tmpvalue, copz == COPz_DMTCz, function & 7);
2037  return;
2038  }
2039 
2040  if (cpnr <= 1 && (((function & 0x03e007ff) == (COPz_CFCz << 21))
2041  || ((function & 0x03e007ff) == (COPz_CTCz << 21)))) {
2042  switch (copz) {
2043  case COPz_CFCz: /* Copy from FPU control register */
2044  rt = (function >> 16) & 31;
2045  fs = (function >> 11) & 31;
2046  if (unassemble_only) {
2047  debug("cfc%i\t%s,r%i\n", cpnr,
2048  regnames[rt], fs);
2049  return;
2050  }
2051  cpu->cd.mips.gpr[rt] = (int32_t)cp->fcr[fs];
2052  /* TODO: implement delay for gpr[rt]
2053  (for MIPS I,II,III only) */
2054  return;
2055  case COPz_CTCz: /* Copy to FPU control register */
2056  rt = (function >> 16) & 31;
2057  fs = (function >> 11) & 31;
2058  if (unassemble_only) {
2059  debug("ctc%i\t%s,r%i\n", cpnr,
2060  regnames[rt], fs);
2061  return;
2062  }
2063 
2064  switch (cpnr) {
2065  case 0: /* System coprocessor */
2066  fatal("[ warning: unimplemented ctc%i, "
2067  "0x%08x -> ctl reg %i ]\n", cpnr,
2068  (int)cpu->cd.mips.gpr[rt], fs);
2069  break;
2070  case 1: /* FPU */
2071  if (fs == 0)
2072  fatal("[ Attempt to write to FPU "
2073  "control register 0 (?) ]\n");
2074  else {
2075  uint64_t tmp = cpu->cd.mips.gpr[rt];
2076  cp->fcr[fs] = tmp;
2077 
2078  /* TODO: writing to control register 31
2079  should cause exceptions, depending
2080  on status bits! */
2081 
2082  switch (fs) {
2083  case MIPS_FPU_FCCR:
2084  cp->fcr[MIPS_FPU_FCSR] =
2085  (cp->fcr[MIPS_FPU_FCSR] &
2086  0x017fffffULL) | ((tmp & 1)
2088  | (((tmp & 0xfe) >> 1) <<
2090  break;
2091  case MIPS_FPU_FCSR:
2092  cp->fcr[MIPS_FPU_FCCR] =
2093  (cp->fcr[MIPS_FPU_FCCR] &
2094  0xffffff00ULL) | ((tmp >>
2095  MIPS_FCSR_FCC0_SHIFT) & 1) |
2096  (((tmp >>
2098  & 0x7f) << 1);
2099  break;
2100  default:
2101  ;
2102  }
2103  }
2104  break;
2105  }
2106 
2107  /* TODO: implement delay for gpr[rt]
2108  (for MIPS I,II,III only) */
2109  return;
2110  default:
2111  ;
2112  }
2113  }
2114 
2115  /* Math (Floating point) coprocessor calls: */
2116  if (cpnr==1) {
2117  if (fpu_function(cpu, cp, function, unassemble_only))
2118  return;
2119  }
2120 
2121 
2122  /* Ugly R5900 hacks: */
2123  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2124  if ((function & 0xfffff) == COP0_EI) {
2125  if (unassemble_only) {
2126  debug("ei\n");
2127  return;
2128  }
2129  cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |=
2131  return;
2132  }
2133 
2134  if ((function & 0xfffff) == COP0_DI) {
2135  if (unassemble_only) {
2136  debug("di\n");
2137  return;
2138  }
2139  cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &=
2141  return;
2142  }
2143  }
2144 
2145  co_bit = (function >> 25) & 1;
2146 
2147  /* TLB operations and other things: */
2148  if (cp->coproc_nr == 0) {
2149  if (!unassemble_only) {
2150  fatal("FATAL INTERNAL ERROR: Should be implemented"
2151  " with dyntrans instead.\n");
2152  exit(1);
2153  }
2154 
2155  switch (co_bit) {
2156  case 0:
2157  if ((function & 0x03e0ffdf) == 0x01606000) {
2158  debug("%ci", function & 0x20? 'e' : 'd');
2159  if (rt != MIPS_GPR_ZERO)
2160  debug("\t%s", regnames[rt]);
2161  debug("\n");
2162  return;
2163  }
2164  break;
2165  case 1:
2166  op = (function) & 0xff;
2167  switch (op) {
2168  case COP0_TLBR: /* Read indexed TLB entry */
2169  debug("tlbr\n");
2170  return;
2171  case COP0_TLBWI: /* Write indexed */
2172  case COP0_TLBWR: /* Write random */
2173  if (op == COP0_TLBWI)
2174  debug("tlbwi");
2175  else
2176  debug("tlbwr");
2177  if (!running) {
2178  debug("\n");
2179  return;
2180  }
2181  debug("\tindex=%08llx",
2182  (long long)cp->reg[COP0_INDEX]);
2183  debug(", random=%08llx",
2184  (long long)cp->reg[COP0_RANDOM]);
2185  debug(", mask=%016llx",
2186  (long long)cp->reg[COP0_PAGEMASK]);
2187  debug(", hi=%016llx",
2188  (long long)cp->reg[COP0_ENTRYHI]);
2189  debug(", lo0=%016llx",
2190  (long long)cp->reg[COP0_ENTRYLO0]);
2191  debug(", lo1=%016llx\n",
2192  (long long)cp->reg[COP0_ENTRYLO1]);
2193  return;
2194  case COP0_TLBP: /* Probe TLB for
2195  matching entry */
2196  debug("tlbp\n");
2197  return;
2198  case COP0_RFE: /* R2000/R3000 only:
2199  Return from Exception */
2200  debug("rfe\n");
2201  return;
2202  case COP0_ERET: /* R4000: Return from exception */
2203  debug("eret\n");
2204  return;
2205  case COP0_DERET:
2206  debug("deret\n");
2207  return;
2208  case COP0_WAIT:
2209  {
2210  int code = (function >> 6) & 0x7ffff;
2211  debug("wait");
2212  if (code > 0)
2213  debug("\t0x%x", code);
2214  debug("\n");
2215  }
2216  return;
2217  case COP0_STANDBY:
2218  debug("standby\n");
2219  return;
2220  case COP0_SUSPEND:
2221  debug("suspend\n");
2222  return;
2223  case COP0_HIBERNATE:
2224  debug("hibernate\n");
2225  return;
2226  default:
2227  ;
2228  }
2229  break;
2230  }
2231  }
2232 
2233  /* TODO: coprocessor R2020 on DECstation? */
2234  if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x0100ffff) {
2235  if (unassemble_only) {
2236  debug("decstation_r2020_writeback\n");
2237  return;
2238  }
2239  /* TODO */
2240  return;
2241  }
2242 
2243  if (unassemble_only) {
2244  debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);
2245  return;
2246  }
2247 
2248  fatal("cpu%i: UNIMPLEMENTED coproc%i function %08" PRIx32" "
2249  "(pc = %016" PRIx64")\n", cpu->cpu_id, cp->coproc_nr,
2250  (uint32_t)function, cpu->pc);
2251 
2252  mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0);
2253 }
2254 
#define MIPS_REGISTER_NAMES
#define IEEE_FMT_S
Definition: float_emul.h:43
void * zeroed_alloc(size_t s)
Definition: memory.cc:118
#define MIPS_R4600
Definition: mips_cpuregs.h:712
void fatal(const char *fmt,...)
Definition: main.cc:152
#define COP0_BADVADDR
Definition: cop0.h:91
int emulated_hz
Definition: machine.h:165
int cache_secondary_linesize
Definition: cpu_mips.h:264
int nr_of_tlbs
Definition: cpu_mips.h:106
int prom_emulation
Definition: machine.h:149
#define ENTRYHI_VPN2_MASK_R10K
Definition: cop0.h:98
#define R2K3K_ENTRYLO_D
Definition: cop0.h:74
#define INVALIDATE_VADDR
Definition: cpu.h:480
#define FPU_OP_SUB
#define COP0_DERET
Definition: opcodes_mips.h:295
uint8_t delay_slot
Definition: cpu.h:356
uint8_t is_32bit
Definition: cpu.h:350
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)
#define MIPS_FPU_FCSR
#define COP1_REVISION_SINGLE
Definition: cop0.h:168
#define R2K3K_ENTRYHI_ASID_MASK
Definition: cop0.h:106
#define MIPS1_ISOL_CACHES
Definition: mips_cpuregs.h:180
#define INVALIDATE_ALL
Definition: cpu.h:478
void coproc_function(struct cpu *cpu, struct mips_coproc *cp, int cpnr, uint32_t function, int unassemble_only, int running)
#define COPz_MTCz
Definition: opcodes_mips.h:271
#define STATUS_ERL
Definition: cop0.h:124
#define COP0_TLBR
Definition: opcodes_mips.h:289
#define R2K3K_ENTRYLO_PFN_MASK
Definition: cop0.h:71
#define R2K3K_ENTRYLO_G
Definition: cop0.h:76
void coproc_tlbwri(struct cpu *cpu, int randomflag)
#define COP0_EI
Definition: opcodes_mips.h:300
union cpu::@1 cd
struct memory * mem
Definition: cpu.h:362
#define COP0_COUNT
Definition: cop0.h:92
#define COP0_CONFIG
Definition: cop0.h:142
#define MIPS_R4000
Definition: mips_cpuregs.h:700
#define COP0_STATUS
Definition: cop0.h:109
uint64_t fcr[N_MIPS_FCRS]
Definition: cpu_mips.h:110
#define R2K3K_ENTRYLO_V
Definition: cop0.h:75
#define COP0_ENTRYLO0
Definition: cop0.h:60
struct machine * machine
Definition: cpu.h:328
#define FPU_OP_NEG
void f(int s, int func, int only_name)
#define IEEE_FMT_W
Definition: float_emul.h:45
#define MIPS_SOFT
Definition: mips_cpuregs.h:800
#define COP0_ERET
Definition: opcodes_mips.h:294
#define R2K3K_INDEX_SHIFT
Definition: cop0.h:55
void ieee_interpret_float_value(uint64_t x, struct ieee_float_value *fvp, int fmt)
Definition: float_emul.cc:49
#define R2K3K_ENTRYHI_ASID_SHIFT
Definition: cop0.h:107
#define COP1_FMT_S
Definition: opcodes_mips.h:283
#define CONTEXT_BADVPN2_MASK_R4100
Definition: cop0.h:79
#define ENTRYLO_G
Definition: cop0.h:69
#define COP0_XCONTEXT
Definition: cop0.h:146
int cache_secondary
Definition: cpu_mips.h:261
#define ENTRYHI_VPN2_MASK
Definition: cop0.h:99
#define ENTRYHI_ASID
Definition: cop0.h:101
int cache_pdcache_linesize
Definition: cpu_mips.h:263
#define COP0_ERROREPC
Definition: cop0.h:160
Definition: timer.cc:45
#define STATUS_BEV
Definition: cop0.h:115
#define FPU_OP_DIV
char * cond[16]
#define COP0_TAGDATA_LO
Definition: cop0.h:158
#define COP0_WAIT
Definition: opcodes_mips.h:296
#define ENTRYHI_R_MASK
Definition: cop0.h:95
#define FPU_OP_C
#define MIPS_R3010
Definition: mips_cpuregs.h:803
int rmw
Definition: cpu_mips.h:231
struct timer * timer
Definition: cpu_mips.h:229
#define COPz_CFCz
Definition: opcodes_mips.h:279
#define ENTRYLO_C_SHIFT
Definition: cop0.h:66
int32_t count_register_read_count
Definition: cpu_mips.h:227
uint64_t pc
Definition: cpu.h:383
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
void timer_update_frequency(struct timer *t, double new_freq)
Definition: timer.cc:132
#define STATUS_IM_SHIFT
Definition: cop0.h:118
uint64_t mask
Definition: cpu_mips.h:83
#define COPz_DMTCz
Definition: opcodes_mips.h:272
uint64_t hi
Definition: cpu_mips.h:80
#define COP0_DEPC
Definition: cop0.h:154
#define COP1_FMT_D
Definition: opcodes_mips.h:284
#define FPU_OP_MUL
struct mips_tlb * tlbs
Definition: cpu_mips.h:105
#define COP0_COMPARE
Definition: cop0.h:108
#define INDEX_MASK
Definition: cop0.h:52
uint64_t reg[N_MIPS_COPROC_REGS]
Definition: cpu_mips.h:102
#define COP0_WIRED
Definition: cop0.h:89
#define R5900_STATUS_EIE
Definition: cop0.h:128
#define IC
#define EXC3K
#define COP0_TLBWI
Definition: opcodes_mips.h:290
#define MIPS_R5900
Definition: mips_cpuregs.h:723
int cache_picache
Definition: cpu_mips.h:259
#define COP1_FMT_W
Definition: opcodes_mips.h:285
#define MMU10K
#define MIPS_R4010
Definition: mips_cpuregs.h:805
int cache_picache_linesize
Definition: cpu_mips.h:262
int instruction_trace
Definition: machine.h:162
#define COP0_STANDBY
Definition: opcodes_mips.h:297
#define R2K3K_ENTRYHI_VPN_MASK
Definition: cop0.h:104
#define COP0_HIBERNATE
Definition: opcodes_mips.h:299
void coproc_eret(struct cpu *cpu)
#define FPU_OP_SQRT
int compare_interrupts_pending
Definition: cpu_mips.h:226
struct timer * timer_add(double freq, void(*timer_tick)(struct timer *timer, void *extra), void *extra)
Definition: timer.cc:75
#define ENTRYLO_PFN_SHIFT
Definition: cop0.h:64
#define COP0_PRID
Definition: cop0.h:141
#define MIPS_RM5200
Definition: mips_cpuregs.h:721
#define MIPS_R12000
Definition: mips_cpuregs.h:708
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:1714
int coproc_nr
Definition: cpu_mips.h:101
#define COP0_CAUSE
Definition: cop0.h:129
#define R2K3K_RANDOM_SHIFT
Definition: cop0.h:59
volatile int single_step
Definition: debugger.cc:68
struct mips_coproc * coproc[N_MIPS_COPROCS]
Definition: cpu_mips.h:219
#define MIPS_FCSR_FCC0_SHIFT
#define COP0_ENTRYLO1
Definition: cop0.h:61
#define COPz_MFCz
Definition: opcodes_mips.h:269
#define CONTEXT_BADVPN2_MASK
Definition: cop0.h:78
#define MIPS_R6010
Definition: mips_cpuregs.h:804
void coproc_register_write(struct cpu *cpu, struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64, int select)
struct mips_coproc * mips_coproc_new(struct cpu *cpu, int coproc_nr)
#define MIPS_R10000
Definition: mips_cpuregs.h:704
#define COPz_DMFCz
Definition: opcodes_mips.h:270
#define ENTRYLO_D
Definition: cop0.h:67
#define ENTRYLO_PFN_MASK
Definition: cop0.h:63
#define MIPS_R4100
Definition: mips_cpuregs.h:707
#define EXCEPTION_FPE
Definition: cop0.h:198
#define EXCEPTION_CPU
Definition: cop0.h:194
#define MIPS_R6000
Definition: mips_cpuregs.h:699
#define FPU_OP_ADD
#define debug
Definition: dev_adb.cc:57
int cpu_id
Definition: cpu.h:359
#define COP0_PAGEMASK
Definition: cop0.h:83
#define MIPS_5Kc
Definition: mips_cpuregs.h:757
Definition: cpu.h:326
int cache_pdcache
Definition: cpu_mips.h:260
#define COP0_CONTEXT
Definition: cop0.h:77
#define COPz_CTCz
Definition: opcodes_mips.h:280
#define MIPS_GPR_ZERO
#define INDEX_P
Definition: cop0.h:51
uint64_t lo1
Definition: cpu_mips.h:82
#define FPU_OP_MOV
#define PAGEMASK_SHIFT
Definition: cop0.h:85
#define INVALIDATE_PADDR
Definition: cpu.h:479
#define FPU_OP_CVT
#define R2K3K_RANDOM_MASK
Definition: cop0.h:58
uint64_t cop0_config_select1
Definition: cpu_mips.h:220
uint64_t ieee_store_float_value(double nf, int fmt, int nan)
Definition: float_emul.cc:185
#define COP0_LLADDR
Definition: cop0.h:143
#define MIPS_R2010
Definition: mips_cpuregs.h:802
#define COP0_FRAMEMASK
Definition: cop0.h:151
#define COP0_INDEX
Definition: cop0.h:50
#define STATUS_EXL
Definition: cop0.h:125
#define MIPS_R5000
Definition: mips_cpuregs.h:717
#define ENTRYLO_C_MASK
Definition: cop0.h:65
#define MIPS_FPU_FCCR
#define COP0_RANDOM
Definition: cop0.h:56
#define FPU_OP_ABS
#define COP0_TLBP
Definition: opcodes_mips.h:292
#define COP0_DI
Definition: opcodes_mips.h:301
#define MIPS_R14000
Definition: mips_cpuregs.h:709
#define COP0_RESERV22
Definition: cop0.h:152
uint8_t byte_order
Definition: cpu.h:347
#define COP1_FMT_L
Definition: opcodes_mips.h:286
#define MIPS_R3000
Definition: mips_cpuregs.h:698
#define RANDOM_MASK
Definition: cop0.h:57
#define COP0_ENTRYHI
Definition: cop0.h:93
#define COP0_NAMES
Definition: cop0.h:40
void(* update_translation_table)(struct cpu *, uint64_t vaddr_page, unsigned char *host_page, int writeflag, uint64_t paddr_page)
Definition: cpu.h:371
#define COP0_TAGDATA_HI
Definition: cop0.h:159
uint64_t gpr[N_MIPS_GPRS]
Definition: cpu_mips.h:209
void coproc_register_read(struct cpu *cpu, struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int select)
#define STATUS_CU_SHIFT
Definition: cop0.h:111
#define R2K3K_ENTRYLO_N
Definition: cop0.h:73
struct mips_cpu mips
Definition: cpu.h:443
#define COP0_RFE
Definition: opcodes_mips.h:293
#define COP0_TLBWR
Definition: opcodes_mips.h:291
addr & if(addr >=0x24 &&page !=NULL)
#define COP0_DEBUG
Definition: cop0.h:153
#define COP0_WATCHHI
Definition: cop0.h:145
#define COP0_EPC
Definition: cop0.h:140
#define MIPS_R2000
Definition: mips_cpuregs.h:697
#define IEEE_FMT_L
Definition: float_emul.h:46
uint64_t lo0
Definition: cpu_mips.h:81
#define COP1_REVISION
Definition: cop0.h:164
#define TLB_G
Definition: cop0.h:102
#define MIPS_4Kc
Definition: mips_cpuregs.h:756
#define IEEE_FMT_D
Definition: float_emul.h:44
void(* invalidate_code_translation)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:376
struct mips_cpu_type_def cpu_type
Definition: cpu_mips.h:206
#define COP0_PERFCNT
Definition: cop0.h:155
#define COP0_ERRCTL
Definition: cop0.h:156
#define COP0_CACHEERR
Definition: cop0.h:157
#define MMU3K
#define COP0_SUSPEND
Definition: opcodes_mips.h:298
char * op[16]
#define MMU4K
#define R2K3K_CONTEXT_BADVPN_MASK
Definition: cop0.h:81
#define R2K3K_INDEX_MASK
Definition: cop0.h:54
#define NOFPU
#define COP0_WATCHLO
Definition: cop0.h:144
#define COP0_DESAVE
Definition: cop0.h:161
int compare_register_set
Definition: cpu_mips.h:225
void(* invalidate_translation_caches)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:374
#define ENTRYLO_V
Definition: cop0.h:68
#define MIPS_FCSR_FCC1_SHIFT
int last_written_tlb_index
Definition: cpu_mips.h:222
void coproc_tlbpr(struct cpu *cpu, int readflag)
#define EMUL_BIG_ENDIAN
Definition: misc.h:165
unsigned char * memory_paddr_to_hostaddr(struct memory *mem, uint64_t paddr, int writeflag)
Definition: memory.cc:495
#define COP1_REVISION_DOUBLE
Definition: cop0.h:167

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13