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