/[dynamips]/upstream/dynamips-0.2.6-RC3/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

Annotation of /upstream/dynamips-0.2.6-RC3/cp0.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations)
Sat Oct 6 16:06:49 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 16910 byte(s)
dynamips-0.2.6-RC3

1 dpavlin 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 dpavlin 4 /* 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 dpavlin 1 /* 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 dpavlin 4 m_uint64_t vpn_addr,vpn2_mask;
351     m_uint64_t page_mask,hi_addr;
352 dpavlin 1 m_uint32_t page_size,pca;
353     tlb_entry_t *entry;
354 dpavlin 4 u_int asid;
355 dpavlin 1 int i;
356    
357 dpavlin 4 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 dpavlin 1 for(i=0;i<cp0->tlb_entries;i++) {
362     entry = &cp0->tlb[i];
363    
364 dpavlin 4 page_mask = ~(entry->mask + 0x1FFF);
365     hi_addr = entry->hi & vpn2_mask;
366 dpavlin 1
367 dpavlin 4 if (((vpn_addr & page_mask) == hi_addr) &&
368     ((entry->hi & MIPS_TLB_G_MASK) ||
369     ((entry->hi & MIPS_TLB_ASID_MASK) == asid)))
370 dpavlin 1 {
371 dpavlin 4 page_size = get_page_size(entry->mask);
372 dpavlin 1
373 dpavlin 4 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 dpavlin 1
381 dpavlin 4 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 dpavlin 1
396 dpavlin 4 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 dpavlin 1
405 dpavlin 4 /* Invalid entry */
406     return(FALSE);
407 dpavlin 1 }
408     }
409    
410 dpavlin 4 /* No matching entry */
411 dpavlin 1 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 dpavlin 4 v0_addr = entry->hi & cp0_get_vpn2_mask(cpu);
433 dpavlin 1 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 dpavlin 4 v0_addr = entry->hi & cp0_get_vpn2_mask(cpu);
469 dpavlin 1 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 dpavlin 4 m_uint64_t hi_reg,asid;
492     m_uint64_t vpn2,vpn2_mask;
493 dpavlin 1 tlb_entry_t *entry;
494     int i;
495    
496 dpavlin 4 vpn2_mask = cp0_get_vpn2_mask(cpu);
497 dpavlin 1 hi_reg = cp0->reg[MIPS_CP0_TLB_HI];
498     asid = hi_reg & MIPS_TLB_ASID_MASK;
499 dpavlin 4 vpn2 = hi_reg & vpn2_mask;
500 dpavlin 1
501     cp0->reg[MIPS_CP0_INDEX] = 0xffffffff80000000ULL;
502    
503     for(i=0;i<cp0->tlb_entries;i++) {
504     entry = &cp0->tlb[i];
505    
506 dpavlin 4 if (((entry->hi & vpn2_mask) == vpn2) &&
507 dpavlin 1 ((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 dpavlin 4 printf(" %2d: vaddr=0x%8.8llx ", index, entry->hi & cp0_get_vpn2_mask(cpu));
636 dpavlin 1
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