/[dynamips]/trunk/cp0.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/cp0.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (11 years, 11 months ago) by dpavlin
File MIME type: text/plain
File size: 16910 byte(s)
make working copy

1 /*
2 * Cisco 7200 (Predator) simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * MIPS Coprocessor 0 (System Coprocessor) implementation.
6 * We don't use the JIT here, since there is no high performance needed.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <sys/mman.h>
16 #include <fcntl.h>
17
18 #include "rbtree.h"
19 #include "mips64.h"
20 #include "dynamips.h"
21 #include "memory.h"
22 #include "device.h"
23 #include "cp0.h"
24
25 /* MIPS cp0 registers names */
26 char *mips64_cp0_reg_names[MIPS64_CP0_REG_NR] = {
27 "index" ,
28 "random",
29 "entry_lo0",
30 "entry_lo1",
31 "context",
32 "pagemask",
33 "wired",
34 "info",
35 "badvaddr",
36 "count",
37 "entry_hi",
38 "compare",
39 "status",
40 "cause",
41 "epc",
42 "prid",
43 "config",
44 "ll_addr",
45 "watch_lo",
46 "watch_hi",
47 "xcontext",
48 "cp0_r21",
49 "cp0_r22",
50 "cp0_r23",
51 "cp0_r24",
52 "cp0_r25",
53 "ecc",
54 "cache_err",
55 "tag_lo",
56 "tag_hi",
57 "err_epc",
58 "cp0_r31",
59 };
60
61 /* Get cp0 register index given its name */
62 int cp0_get_reg_index(char *name)
63 {
64 int i;
65
66 for(i=0;i<MIPS64_CP0_REG_NR;i++)
67 if (!strcmp(mips64_cp0_reg_names[i],name))
68 return(i);
69
70 return(-1);
71 }
72
73 /* Get the CPU operating mode (User,Supervisor or Kernel) - inline version */
74 static forced_inline u_int cp0_get_mode_inline(cpu_mips_t *cpu)
75 {
76 mips_cp0_t *cp0 = &cpu->cp0;
77 u_int cpu_mode;
78
79 cpu_mode = cp0->reg[MIPS_CP0_STATUS] >> MIPS_CP0_STATUS_KSU_SHIFT;
80 cpu_mode &= MIPS_CP0_STATUS_KSU_MASK;
81 return(cpu_mode);
82 }
83
84 /* Get the CPU operating mode (User,Supervisor or Kernel) */
85 u_int cp0_get_mode(cpu_mips_t *cpu)
86 {
87 return(cp0_get_mode_inline(cpu));
88 }
89
90 /* Check that we are running in kernel mode */
91 int cp0_check_kernel_mode(cpu_mips_t *cpu)
92 {
93 u_int cpu_mode;
94
95 cpu_mode = cp0_get_mode(cpu);
96
97 if (cpu_mode != MIPS_CP0_STATUS_KM) {
98 /* XXX Branch delay slot */
99 mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_ILLOP,0);
100 return(1);
101 }
102
103 return(0);
104 }
105
106 /* Get value of random register */
107 static inline u_int cp0_get_random_reg(cpu_mips_t *cpu)
108 {
109 u_int wired;
110
111 /* We use the virtual count register as a basic "random" value */
112 wired = cpu->cp0.reg[MIPS_CP0_WIRED];
113 return(wired + (cpu->cp0_virt_cnt_reg % (cpu->cp0.tlb_entries - wired)));
114 }
115
116 /* Get a cp0 register (fast version) */
117 static inline m_uint64_t cp0_get_reg_fast(cpu_mips_t *cpu,u_int cp0_reg)
118 {
119 mips_cp0_t *cp0 = &cpu->cp0;
120 m_uint32_t delta,res;
121
122 switch(cp0_reg) {
123 case MIPS_CP0_COUNT:
124 delta = cpu->cp0_virt_cmp_reg - cpu->cp0_virt_cnt_reg;
125 res = (m_uint32_t)cp0->reg[MIPS_CP0_COMPARE];
126 res -= cpu->vm->clock_divisor * delta;
127 return(sign_extend(res,32));
128
129 #if 1
130 case MIPS_CP0_COMPARE:
131 return(sign_extend(cp0->reg[MIPS_CP0_COMPARE],32));
132 #else
133 /* really useful and logical ? */
134 case MIPS_CP0_COMPARE:
135 delta = cpu->cp0_virt_cmp_reg - cpu->cp0_virt_cnt_reg;
136 res = (m_uint32_t)cp0->reg[MIPS_CP0_COUNT];
137 res += (cpu->vm->clock_divisor * delta);
138 return(res);
139 #endif
140 case MIPS_CP0_INFO:
141 return(MIPS64_R7000_TLB64_ENABLE);
142
143 case MIPS_CP0_RANDOM:
144 return(cp0_get_random_reg(cpu));
145
146 default:
147 return(cp0->reg[cp0_reg]);
148 }
149 }
150
151 /* Get a cp0 register */
152 m_uint64_t cp0_get_reg(cpu_mips_t *cpu,u_int cp0_reg)
153 {
154 return(cp0_get_reg_fast(cpu,cp0_reg));
155 }
156
157 /* Set a cp0 register */
158 static inline void cp0_set_reg(cpu_mips_t *cpu,u_int cp0_reg,m_uint64_t val)
159 {
160 mips_cp0_t *cp0 = &cpu->cp0;
161 m_uint32_t delta;
162
163 switch(cp0_reg) {
164 case MIPS_CP0_STATUS:
165 case MIPS_CP0_CAUSE:
166 cp0->reg[cp0_reg] = val;
167 mips64_update_irq_flag(cpu);
168 break;
169
170 case MIPS_CP0_PAGEMASK:
171 cp0->reg[cp0_reg] = val & MIPS_TLB_PAGE_MASK;
172 break;
173
174 case MIPS_CP0_COMPARE:
175 mips64_clear_irq(cpu,7);
176 mips64_update_irq_flag(cpu);
177 cp0->reg[cp0_reg] = val;
178
179 delta = val - cp0->reg[MIPS_CP0_COUNT];
180 cpu->cp0_virt_cnt_reg = 0;
181 cpu->cp0_virt_cmp_reg = delta / cpu->vm->clock_divisor;
182 break;
183
184 case MIPS_CP0_COUNT:
185 cp0->reg[cp0_reg] = val;
186
187 delta = cp0->reg[MIPS_CP0_COMPARE] - val;
188 cpu->cp0_virt_cnt_reg = 0;
189 cpu->cp0_virt_cmp_reg = delta / cpu->vm->clock_divisor;
190 break;
191
192 case MIPS_CP0_TLB_HI:
193 cp0->reg[cp0_reg] = val & MIPS_CP0_HI_SAFE_MASK;
194 break;
195
196 case MIPS_CP0_TLB_LO_0:
197 case MIPS_CP0_TLB_LO_1:
198 cp0->reg[cp0_reg] = val & MIPS_CP0_LO_SAFE_MASK;
199 break;
200
201 case MIPS_CP0_RANDOM:
202 case MIPS_CP0_PRID:
203 case MIPS_CP0_CONFIG:
204 /* read only registers */
205 break;
206
207 case MIPS_CP0_WIRED:
208 cp0->reg[cp0_reg] = val & MIPS64_TLB_IDX_MASK;
209 break;
210
211 default:
212 cp0->reg[cp0_reg] = val;
213 }
214 }
215
216 /* Get a cp0 "set 1" register (R7000) */
217 m_uint64_t cp0_s1_get_reg(cpu_mips_t *cpu,u_int cp0_s1_reg)
218 {
219 switch(cp0_s1_reg) {
220 case MIPS_CP0_S1_CONFIG:
221 return(0x7F << 25);
222
223 case MIPS_CP0_S1_IPLLO:
224 return(cpu->cp0.ipl_lo);
225
226 case MIPS_CP0_S1_IPLHI:
227 return(cpu->cp0.ipl_hi);
228
229 case MIPS_CP0_S1_INTCTL:
230 return(cpu->cp0.int_ctl);
231
232 case MIPS_CP0_S1_DERRADDR0:
233 return(cpu->cp0.derraddr0);
234
235 case MIPS_CP0_S1_DERRADDR1:
236 return(cpu->cp0.derraddr1);
237
238 default:
239 /* undefined register */
240 cpu_log(cpu,"CP0_S1","trying to read unknown register %u\n",
241 cp0_s1_reg);
242 return(0);
243 }
244 }
245
246 /* Set a cp0 "set 1" register (R7000) */
247 static inline void cp0_s1_set_reg(cpu_mips_t *cpu,u_int cp0_s1_reg,
248 m_uint64_t val)
249 {
250 mips_cp0_t *cp0 = &cpu->cp0;
251
252 switch(cp0_s1_reg) {
253 case MIPS_CP0_S1_IPLLO:
254 cp0->ipl_lo = val;
255 break;
256
257 case MIPS_CP0_S1_IPLHI:
258 cp0->ipl_hi = val;
259 break;
260
261 case MIPS_CP0_S1_INTCTL:
262 cp0->int_ctl = val;
263 break;
264
265 case MIPS_CP0_S1_DERRADDR0:
266 cp0->derraddr0 = val;
267 break;
268
269 case MIPS_CP0_S1_DERRADDR1:
270 cp0->derraddr1 = val;
271 break;
272
273 default:
274 cpu_log(cpu,"CP0_S1","trying to set unknown register %u (val=0x%x)\n",
275 cp0_s1_reg,val);
276 }
277 }
278
279 /* DMFC0 */
280 fastcall void cp0_exec_dmfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
281 {
282 cpu->gpr[gp_reg] = cp0_get_reg_fast(cpu,cp0_reg);
283 }
284
285 /* DMTC0 */
286 fastcall void cp0_exec_dmtc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
287 {
288 cp0_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg]);
289 }
290
291 /* MFC0 */
292 fastcall void cp0_exec_mfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
293 {
294 cpu->gpr[gp_reg] = sign_extend(cp0_get_reg_fast(cpu,cp0_reg),32);
295 }
296
297 /* MTC0 */
298 fastcall void cp0_exec_mtc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
299 {
300 cp0_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg] & 0xffffffff);
301 }
302
303 /* CFC0 */
304 fastcall void cp0_exec_cfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
305 {
306 cpu->gpr[gp_reg] = sign_extend(cp0_s1_get_reg(cpu,cp0_reg),32);
307 }
308
309 /* CTC0 */
310 fastcall void cp0_exec_ctc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
311 {
312 cp0_s1_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg] & 0xffffffff);
313 }
314
315 /* Get the page size corresponding to a page mask */
316 static inline m_uint32_t get_page_size(m_uint32_t page_mask)
317 {
318 return((page_mask + 0x2000) >> 1);
319 }
320
321 /* Write page size in buffer */
322 static char *get_page_size_str(char *buffer,size_t len,m_uint32_t page_mask)
323 {
324 m_uint32_t page_size;
325
326 page_size = get_page_size(page_mask);
327
328 /* Mb ? */
329 if (page_size >= (1024*1024))
330 snprintf(buffer,len,"%uMB",page_size >> 20);
331 else
332 snprintf(buffer,len,"%uKB",page_size >> 10);
333
334 return buffer;
335 }
336
337 /* Get the VPN2 mask */
338 static forced_inline m_uint64_t cp0_get_vpn2_mask(cpu_mips_t *cpu)
339 {
340 if (cpu->addr_mode == 64)
341 return(MIPS_TLB_VPN2_MASK_64);
342 else
343 return(MIPS_TLB_VPN2_MASK_32);
344 }
345
346 /* TLB lookup */
347 int cp0_tlb_lookup(cpu_mips_t *cpu,m_uint64_t vaddr,mts_map_t *res)
348 {
349 mips_cp0_t *cp0 = &cpu->cp0;
350 m_uint64_t vpn_addr,vpn2_mask;
351 m_uint64_t page_mask,hi_addr;
352 m_uint32_t page_size,pca;
353 tlb_entry_t *entry;
354 u_int asid;
355 int i;
356
357 vpn2_mask = cp0_get_vpn2_mask(cpu);
358 vpn_addr = vaddr & vpn2_mask;
359 asid = cp0->reg[MIPS_CP0_TLB_HI] & MIPS_TLB_ASID_MASK;
360
361 for(i=0;i<cp0->tlb_entries;i++) {
362 entry = &cp0->tlb[i];
363
364 page_mask = ~(entry->mask + 0x1FFF);
365 hi_addr = entry->hi & vpn2_mask;
366
367 if (((vpn_addr & page_mask) == hi_addr) &&
368 ((entry->hi & MIPS_TLB_G_MASK) ||
369 ((entry->hi & MIPS_TLB_ASID_MASK) == asid)))
370 {
371 page_size = get_page_size(entry->mask);
372
373 if ((vaddr & page_size) == 0) {
374 /* Even Page */
375 if (entry->lo0 & MIPS_TLB_V_MASK) {
376 res->vaddr = vaddr & page_mask;
377 res->paddr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6;
378 res->paddr &= cpu->addr_bus_mask;
379 res->len = page_size;
380
381 pca = (entry->lo0 & MIPS_TLB_C_MASK);
382 pca >>= MIPS_TLB_C_SHIFT;
383 res->cached = mips64_cca_cached(pca);
384
385 res->tlb_index = i;
386 return(TRUE);
387 }
388 } else {
389 /* Odd Page */
390 if (entry->lo1 & MIPS_TLB_V_MASK) {
391 res->vaddr = (vaddr & page_mask) + page_size;
392 res->paddr = (entry->lo1 & MIPS_TLB_PFN_MASK) << 6;
393 res->paddr &= cpu->addr_bus_mask;
394 res->len = page_size;
395
396 pca = (entry->lo1 & MIPS_TLB_C_MASK);
397 pca >>= MIPS_TLB_C_SHIFT;
398 res->cached = mips64_cca_cached(pca);
399
400 res->tlb_index = i;
401 return(TRUE);
402 }
403 }
404
405 /* Invalid entry */
406 return(FALSE);
407 }
408 }
409
410 /* No matching entry */
411 return(FALSE);
412 }
413
414 /*
415 * Map a TLB entry into the MTS.
416 *
417 * We apply the physical address bus masking here.
418 *
419 * TODO: - Manage ASID
420 * - Manage CPU Mode (user,supervisor or kernel)
421 */
422 void cp0_map_tlb_to_mts(cpu_mips_t *cpu,int index)
423 {
424 m_uint64_t v0_addr,v1_addr,p0_addr,p1_addr;
425 m_uint32_t page_size,pca;
426 tlb_entry_t *entry;
427 int cacheable;
428
429 entry = &cpu->cp0.tlb[index];
430
431 page_size = get_page_size(entry->mask);
432 v0_addr = entry->hi & cp0_get_vpn2_mask(cpu);
433 v1_addr = v0_addr + page_size;
434
435 if (entry->lo0 & MIPS_TLB_V_MASK) {
436 pca = (entry->lo0 & MIPS_TLB_C_MASK);
437 pca >>= MIPS_TLB_C_SHIFT;
438 cacheable = mips64_cca_cached(pca);
439
440 p0_addr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6;
441 cpu->mts_map(cpu,v0_addr,p0_addr & cpu->addr_bus_mask,page_size,
442 cacheable,index);
443 }
444
445 if (entry->lo1 & MIPS_TLB_V_MASK) {
446 pca = (entry->lo1 & MIPS_TLB_C_MASK);
447 pca >>= MIPS_TLB_C_SHIFT;
448 cacheable = mips64_cca_cached(pca);
449
450 p1_addr = (entry->lo1 & MIPS_TLB_PFN_MASK) << 6;
451 cpu->mts_map(cpu,v1_addr,p1_addr & cpu->addr_bus_mask,page_size,
452 cacheable,index);
453 }
454 }
455
456 /*
457 * Unmap a TLB entry in the MTS.
458 */
459 void cp0_unmap_tlb_to_mts(cpu_mips_t *cpu,int index)
460 {
461 m_uint64_t v0_addr,v1_addr;
462 m_uint32_t page_size;
463 tlb_entry_t *entry;
464
465 entry = &cpu->cp0.tlb[index];
466
467 page_size = get_page_size(entry->mask);
468 v0_addr = entry->hi & cp0_get_vpn2_mask(cpu);
469 v1_addr = v0_addr + page_size;
470
471 if (entry->lo0 & MIPS_TLB_V_MASK)
472 cpu->mts_unmap(cpu,v0_addr,page_size,MTS_ACC_T,index);
473
474 if (entry->lo1 & MIPS_TLB_V_MASK)
475 cpu->mts_unmap(cpu,v1_addr,page_size,MTS_ACC_T,index);
476 }
477
478 /* Map all TLB entries into the MTS */
479 void cp0_map_all_tlb_to_mts(cpu_mips_t *cpu)
480 {
481 int i;
482
483 for(i=0;i<cpu->cp0.tlb_entries;i++)
484 cp0_map_tlb_to_mts(cpu,i);
485 }
486
487 /* TLBP: Probe a TLB entry */
488 fastcall void cp0_exec_tlbp(cpu_mips_t *cpu)
489 {
490 mips_cp0_t *cp0 = &cpu->cp0;
491 m_uint64_t hi_reg,asid;
492 m_uint64_t vpn2,vpn2_mask;
493 tlb_entry_t *entry;
494 int i;
495
496 vpn2_mask = cp0_get_vpn2_mask(cpu);
497 hi_reg = cp0->reg[MIPS_CP0_TLB_HI];
498 asid = hi_reg & MIPS_TLB_ASID_MASK;
499 vpn2 = hi_reg & vpn2_mask;
500
501 cp0->reg[MIPS_CP0_INDEX] = 0xffffffff80000000ULL;
502
503 for(i=0;i<cp0->tlb_entries;i++) {
504 entry = &cp0->tlb[i];
505
506 if (((entry->hi & vpn2_mask) == vpn2) &&
507 ((entry->hi & MIPS_TLB_G_MASK) ||
508 ((entry->hi & MIPS_TLB_ASID_MASK) == asid)))
509 {
510 cp0->reg[MIPS_CP0_INDEX] = i;
511 #if DEBUG_TLB_ACTIVITY
512 printf("CPU: CP0_TLBP returned %u\n",i);
513 tlb_dump(cpu);
514 #endif
515 }
516 }
517 }
518
519 /* TLBR: Read Indexed TLB entry */
520 fastcall void cp0_exec_tlbr(cpu_mips_t *cpu)
521 {
522 mips_cp0_t *cp0 = &cpu->cp0;
523 tlb_entry_t *entry;
524 u_int index;
525
526 index = cp0->reg[MIPS_CP0_INDEX];
527
528 #if DEBUG_TLB_ACTIVITY
529 cpu_log(cpu,"TLB","CP0_TLBR: reading entry %u.\n",index);
530 #endif
531
532 if (index < cp0->tlb_entries)
533 {
534 entry = &cp0->tlb[index];
535
536 cp0->reg[MIPS_CP0_PAGEMASK] = entry->mask;
537 cp0->reg[MIPS_CP0_TLB_HI] = entry->hi;
538 cp0->reg[MIPS_CP0_TLB_LO_0] = entry->lo0;
539 cp0->reg[MIPS_CP0_TLB_LO_1] = entry->lo1;
540
541 /*
542 * The G bit must be reported in both Lo0 and Lo1 registers,
543 * and cleared in Hi register.
544 */
545 if (entry->hi & MIPS_TLB_G_MASK) {
546 cp0->reg[MIPS_CP0_TLB_LO_0] |= MIPS_CP0_LO_G_MASK;
547 cp0->reg[MIPS_CP0_TLB_LO_1] |= MIPS_CP0_LO_G_MASK;
548 cp0->reg[MIPS_CP0_TLB_HI] &= ~MIPS_TLB_G_MASK;
549 }
550 }
551 }
552
553 /* TLBW: Write a TLB entry */
554 static inline void cp0_exec_tlbw(cpu_mips_t *cpu,u_int index)
555 {
556 mips_cp0_t *cp0 = &cpu->cp0;
557 tlb_entry_t *entry;
558
559 #if DEBUG_TLB_ACTIVITY
560 cpu_log(cpu,"TLB","CP0_TLBWI: writing entry %u "
561 "[mask=0x%8.8llx,hi=0x%8.8llx,lo0=0x%8.8llx,lo1=0x%8.8llx]\n",
562 index,cp0->reg[MIPS_CP0_PAGEMASK],cp0->reg[MIPS_CP0_TLB_HI],
563 cp0->reg[MIPS_CP0_TLB_LO_0],cp0->reg[MIPS_CP0_TLB_LO_1]);
564 #endif
565
566 if (index < cp0->tlb_entries)
567 {
568 entry = &cp0->tlb[index];
569
570 /* Unmap the old entry if it was valid */
571 cp0_unmap_tlb_to_mts(cpu,index);
572
573 entry->mask = cp0->reg[MIPS_CP0_PAGEMASK] & MIPS_TLB_PAGE_MASK;
574 entry->hi = cp0->reg[MIPS_CP0_TLB_HI] & ~entry->mask;
575 entry->hi &= MIPS_CP0_HI_SAFE_MASK; /* clear G bit */
576 entry->lo0 = cp0->reg[MIPS_CP0_TLB_LO_0];
577 entry->lo1 = cp0->reg[MIPS_CP0_TLB_LO_1];
578
579 /* if G bit is set in lo0 and lo1, set it in hi */
580 if ((entry->lo0 & entry->lo1) & MIPS_CP0_LO_G_MASK)
581 entry->hi |= MIPS_TLB_G_MASK;
582
583 /* Clear G bit in TLB lo0 and lo1 */
584 entry->lo0 &= ~MIPS_CP0_LO_G_MASK;
585 entry->lo1 &= ~MIPS_CP0_LO_G_MASK;
586
587 /* Inform the MTS subsystem */
588 cp0_map_tlb_to_mts(cpu,index);
589
590 #if DEBUG_TLB_ACTIVITY
591 tlb_dump_entry(cpu,index);
592 #endif
593 }
594 }
595
596 /* TLBWI: Write Indexed TLB entry */
597 fastcall void cp0_exec_tlbwi(cpu_mips_t *cpu)
598 {
599 cp0_exec_tlbw(cpu,cpu->cp0.reg[MIPS_CP0_INDEX]);
600 }
601
602 /* TLBWR: Write Random TLB entry */
603 fastcall void cp0_exec_tlbwr(cpu_mips_t *cpu)
604 {
605 cp0_exec_tlbw(cpu,cp0_get_random_reg(cpu));
606 }
607
608 /* Raw dump of the TLB */
609 void tlb_raw_dump(cpu_mips_t *cpu)
610 {
611 tlb_entry_t *entry;
612 u_int i;
613
614 printf("TLB dump:\n");
615
616 for(i=0;i<cpu->cp0.tlb_entries;i++) {
617 entry = &cpu->cp0.tlb[i];
618 printf(" %2d: mask=0x%16.16llx hi=0x%16.16llx "
619 "lo0=0x%16.16llx lo1=0x%16.16llx\n",
620 i, entry->mask, entry->hi, entry->lo0, entry->lo1);
621 }
622
623 printf("\n");
624 }
625
626 /* Dump the specified TLB entry */
627 void tlb_dump_entry(cpu_mips_t *cpu,u_int index)
628 {
629 tlb_entry_t *entry;
630 char buffer[256];
631
632 entry = &cpu->cp0.tlb[index];
633
634 /* virtual Address */
635 printf(" %2d: vaddr=0x%8.8llx ", index, entry->hi & cp0_get_vpn2_mask(cpu));
636
637 /* global or ASID */
638 if (entry->hi & MIPS_TLB_G_MASK)
639 printf("(global) ");
640 else
641 printf("(asid 0x%2.2llx) ",entry->hi & MIPS_TLB_ASID_MASK);
642
643 /* 1st page: Lo0 */
644 printf("p0=");
645
646 if (entry->lo0 & MIPS_TLB_V_MASK)
647 printf("0x%9.9llx",(entry->lo0 & MIPS_TLB_PFN_MASK) << 6);
648 else
649 printf("(invalid) ");
650
651 printf(" %c ",(entry->lo0 & MIPS_TLB_D_MASK) ? 'D' : ' ');
652
653 /* 2nd page: Lo1 */
654 printf("p1=");
655
656 if (entry->lo1 & MIPS_TLB_V_MASK)
657 printf("0x%9.9llx",(entry->lo1 & MIPS_TLB_PFN_MASK) << 6);
658 else
659 printf("(invalid) ");
660
661 printf(" %c ",(entry->lo1 & MIPS_TLB_D_MASK) ? 'D' : ' ');
662
663 /* page size */
664 printf(" (%s)\n",get_page_size_str(buffer,sizeof(buffer),entry->mask));
665 }
666
667 /* Human-Readable dump of the TLB */
668 void tlb_dump(cpu_mips_t *cpu)
669 {
670 u_int i;
671
672 printf("TLB dump:\n");
673
674 for(i=0;i<cpu->cp0.tlb_entries;i++)
675 tlb_dump_entry(cpu,i);
676
677 printf("\n");
678 }

  ViewVC Help
Powered by ViewVC 1.1.26