/[dynamips]/upstream/dynamips-0.2.6-RC1/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-RC1/cp0.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations)
Sat Oct 6 16:03:58 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 16121 byte(s)
import dynamips-0.2.6-RC1

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     /* TLB lookup */
338     int cp0_tlb_lookup(cpu_mips_t *cpu,m_uint64_t vaddr,mts_map_t *res)
339     {
340     mips_cp0_t *cp0 = &cpu->cp0;
341     m_uint64_t v0_addr,v1_addr;
342     m_uint32_t page_size,pca;
343     tlb_entry_t *entry;
344     int i;
345    
346     for(i=0;i<cp0->tlb_entries;i++) {
347     entry = &cp0->tlb[i];
348    
349     page_size = get_page_size(entry->mask);
350     v0_addr = entry->hi & MIPS_TLB_VPN2_MASK;
351     v1_addr = v0_addr + page_size;
352    
353     /* virtual address in entry 0 ? */
354     if ((entry->lo0 & MIPS_TLB_V_MASK) &&
355     (vaddr >= v0_addr) && (vaddr < v1_addr))
356     {
357     res->vaddr = v0_addr;
358     res->paddr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6;
359     res->paddr &= cpu->addr_bus_mask;
360     res->len = page_size;
361    
362     pca = (entry->lo0 & MIPS_TLB_C_MASK);
363     pca >>= MIPS_TLB_C_SHIFT;
364     res->cached = mips64_cca_cached(pca);
365    
366     res->tlb_index = i;
367     return(TRUE);
368     }
369    
370     /* virtual address in entry 1 ? */
371     if ((entry->lo1 & MIPS_TLB_V_MASK) &&
372     (vaddr >= v1_addr) && ((vaddr - v1_addr) < page_size))
373     {
374     res->vaddr = v1_addr;
375     res->paddr = (entry->lo1 & MIPS_TLB_PFN_MASK) << 6;
376     res->paddr &= cpu->addr_bus_mask;
377     res->len = page_size;
378    
379     pca = (entry->lo1 & MIPS_TLB_C_MASK);
380     pca >>= MIPS_TLB_C_SHIFT;
381     res->cached = mips64_cca_cached(pca);
382    
383     res->tlb_index = i;
384     return(TRUE);
385     }
386     }
387    
388     return(FALSE);
389     }
390    
391     /*
392     * Map a TLB entry into the MTS.
393     *
394     * We apply the physical address bus masking here.
395     *
396     * TODO: - Manage ASID
397     * - Manage CPU Mode (user,supervisor or kernel)
398     */
399     void cp0_map_tlb_to_mts(cpu_mips_t *cpu,int index)
400     {
401     m_uint64_t v0_addr,v1_addr,p0_addr,p1_addr;
402     m_uint32_t page_size,pca;
403     tlb_entry_t *entry;
404     int cacheable;
405    
406     entry = &cpu->cp0.tlb[index];
407    
408     page_size = get_page_size(entry->mask);
409     v0_addr = entry->hi & MIPS_TLB_VPN2_MASK;
410     v1_addr = v0_addr + page_size;
411    
412     if (entry->lo0 & MIPS_TLB_V_MASK) {
413     pca = (entry->lo0 & MIPS_TLB_C_MASK);
414     pca >>= MIPS_TLB_C_SHIFT;
415     cacheable = mips64_cca_cached(pca);
416    
417     p0_addr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6;
418     cpu->mts_map(cpu,v0_addr,p0_addr & cpu->addr_bus_mask,page_size,
419     cacheable,index);
420     }
421    
422     if (entry->lo1 & MIPS_TLB_V_MASK) {
423     pca = (entry->lo1 & MIPS_TLB_C_MASK);
424     pca >>= MIPS_TLB_C_SHIFT;
425     cacheable = mips64_cca_cached(pca);
426    
427     p1_addr = (entry->lo1 & MIPS_TLB_PFN_MASK) << 6;
428     cpu->mts_map(cpu,v1_addr,p1_addr & cpu->addr_bus_mask,page_size,
429     cacheable,index);
430     }
431     }
432    
433     /*
434     * Unmap a TLB entry in the MTS.
435     */
436     void cp0_unmap_tlb_to_mts(cpu_mips_t *cpu,int index)
437     {
438     m_uint64_t v0_addr,v1_addr;
439     m_uint32_t page_size;
440     tlb_entry_t *entry;
441    
442     entry = &cpu->cp0.tlb[index];
443    
444     page_size = get_page_size(entry->mask);
445     v0_addr = entry->hi & MIPS_TLB_VPN2_MASK;
446     v1_addr = v0_addr + page_size;
447    
448     if (entry->lo0 & MIPS_TLB_V_MASK)
449     cpu->mts_unmap(cpu,v0_addr,page_size,MTS_ACC_T,index);
450    
451     if (entry->lo1 & MIPS_TLB_V_MASK)
452     cpu->mts_unmap(cpu,v1_addr,page_size,MTS_ACC_T,index);
453     }
454    
455     /* Map all TLB entries into the MTS */
456     void cp0_map_all_tlb_to_mts(cpu_mips_t *cpu)
457     {
458     int i;
459    
460     for(i=0;i<cpu->cp0.tlb_entries;i++)
461     cp0_map_tlb_to_mts(cpu,i);
462     }
463    
464     /* TLBP: Probe a TLB entry */
465     fastcall void cp0_exec_tlbp(cpu_mips_t *cpu)
466     {
467     mips_cp0_t *cp0 = &cpu->cp0;
468     m_uint64_t hi_reg,asid,vpn2;
469     tlb_entry_t *entry;
470     int i;
471    
472     hi_reg = cp0->reg[MIPS_CP0_TLB_HI];
473     asid = hi_reg & MIPS_TLB_ASID_MASK;
474     vpn2 = hi_reg & MIPS_TLB_VPN2_MASK;
475    
476     cp0->reg[MIPS_CP0_INDEX] = 0xffffffff80000000ULL;
477    
478     for(i=0;i<cp0->tlb_entries;i++) {
479     entry = &cp0->tlb[i];
480    
481     if (((entry->hi & MIPS_TLB_VPN2_MASK) == vpn2) &&
482     ((entry->hi & MIPS_TLB_G_MASK) ||
483     ((entry->hi & MIPS_TLB_ASID_MASK) == asid)))
484     {
485     cp0->reg[MIPS_CP0_INDEX] = i;
486     #if DEBUG_TLB_ACTIVITY
487     printf("CPU: CP0_TLBP returned %u\n",i);
488     tlb_dump(cpu);
489     #endif
490     }
491     }
492     }
493    
494     /* TLBR: Read Indexed TLB entry */
495     fastcall void cp0_exec_tlbr(cpu_mips_t *cpu)
496     {
497     mips_cp0_t *cp0 = &cpu->cp0;
498     tlb_entry_t *entry;
499     u_int index;
500    
501     index = cp0->reg[MIPS_CP0_INDEX];
502    
503     #if DEBUG_TLB_ACTIVITY
504     cpu_log(cpu,"TLB","CP0_TLBR: reading entry %u.\n",index);
505     #endif
506    
507     if (index < cp0->tlb_entries)
508     {
509     entry = &cp0->tlb[index];
510    
511     cp0->reg[MIPS_CP0_PAGEMASK] = entry->mask;
512     cp0->reg[MIPS_CP0_TLB_HI] = entry->hi;
513     cp0->reg[MIPS_CP0_TLB_LO_0] = entry->lo0;
514     cp0->reg[MIPS_CP0_TLB_LO_1] = entry->lo1;
515    
516     /*
517     * The G bit must be reported in both Lo0 and Lo1 registers,
518     * and cleared in Hi register.
519     */
520     if (entry->hi & MIPS_TLB_G_MASK) {
521     cp0->reg[MIPS_CP0_TLB_LO_0] |= MIPS_CP0_LO_G_MASK;
522     cp0->reg[MIPS_CP0_TLB_LO_1] |= MIPS_CP0_LO_G_MASK;
523     cp0->reg[MIPS_CP0_TLB_HI] &= ~MIPS_TLB_G_MASK;
524     }
525     }
526     }
527    
528     /* TLBW: Write a TLB entry */
529     static inline void cp0_exec_tlbw(cpu_mips_t *cpu,u_int index)
530     {
531     mips_cp0_t *cp0 = &cpu->cp0;
532     tlb_entry_t *entry;
533    
534     #if DEBUG_TLB_ACTIVITY
535     cpu_log(cpu,"TLB","CP0_TLBWI: writing entry %u "
536     "[mask=0x%8.8llx,hi=0x%8.8llx,lo0=0x%8.8llx,lo1=0x%8.8llx]\n",
537     index,cp0->reg[MIPS_CP0_PAGEMASK],cp0->reg[MIPS_CP0_TLB_HI],
538     cp0->reg[MIPS_CP0_TLB_LO_0],cp0->reg[MIPS_CP0_TLB_LO_1]);
539     #endif
540    
541     if (index < cp0->tlb_entries)
542     {
543     entry = &cp0->tlb[index];
544    
545     /* Unmap the old entry if it was valid */
546     cp0_unmap_tlb_to_mts(cpu,index);
547    
548     entry->mask = cp0->reg[MIPS_CP0_PAGEMASK] & MIPS_TLB_PAGE_MASK;
549     entry->hi = cp0->reg[MIPS_CP0_TLB_HI] & ~entry->mask;
550     entry->hi &= MIPS_CP0_HI_SAFE_MASK; /* clear G bit */
551     entry->lo0 = cp0->reg[MIPS_CP0_TLB_LO_0];
552     entry->lo1 = cp0->reg[MIPS_CP0_TLB_LO_1];
553    
554     /* if G bit is set in lo0 and lo1, set it in hi */
555     if ((entry->lo0 & entry->lo1) & MIPS_CP0_LO_G_MASK)
556     entry->hi |= MIPS_TLB_G_MASK;
557    
558     /* Clear G bit in TLB lo0 and lo1 */
559     entry->lo0 &= ~MIPS_CP0_LO_G_MASK;
560     entry->lo1 &= ~MIPS_CP0_LO_G_MASK;
561    
562     /* Inform the MTS subsystem */
563     cp0_map_tlb_to_mts(cpu,index);
564    
565     #if DEBUG_TLB_ACTIVITY
566     tlb_dump_entry(cpu,index);
567     #endif
568     }
569     }
570    
571     /* TLBWI: Write Indexed TLB entry */
572     fastcall void cp0_exec_tlbwi(cpu_mips_t *cpu)
573     {
574     cp0_exec_tlbw(cpu,cpu->cp0.reg[MIPS_CP0_INDEX]);
575     }
576    
577     /* TLBWR: Write Random TLB entry */
578     fastcall void cp0_exec_tlbwr(cpu_mips_t *cpu)
579     {
580     cp0_exec_tlbw(cpu,cp0_get_random_reg(cpu));
581     }
582    
583     /* Raw dump of the TLB */
584     void tlb_raw_dump(cpu_mips_t *cpu)
585     {
586     tlb_entry_t *entry;
587     u_int i;
588    
589     printf("TLB dump:\n");
590    
591     for(i=0;i<cpu->cp0.tlb_entries;i++) {
592     entry = &cpu->cp0.tlb[i];
593     printf(" %2d: mask=0x%16.16llx hi=0x%16.16llx "
594     "lo0=0x%16.16llx lo1=0x%16.16llx\n",
595     i, entry->mask, entry->hi, entry->lo0, entry->lo1);
596     }
597    
598     printf("\n");
599     }
600    
601     /* Dump the specified TLB entry */
602     void tlb_dump_entry(cpu_mips_t *cpu,u_int index)
603     {
604     tlb_entry_t *entry;
605     char buffer[256];
606    
607     entry = &cpu->cp0.tlb[index];
608    
609     /* virtual Address */
610     printf(" %2d: vaddr=0x%8.8llx ", index, entry->hi & MIPS_TLB_VPN2_MASK);
611    
612     /* global or ASID */
613     if (entry->hi & MIPS_TLB_G_MASK)
614     printf("(global) ");
615     else
616     printf("(asid 0x%2.2llx) ",entry->hi & MIPS_TLB_ASID_MASK);
617    
618     /* 1st page: Lo0 */
619     printf("p0=");
620    
621     if (entry->lo0 & MIPS_TLB_V_MASK)
622     printf("0x%9.9llx",(entry->lo0 & MIPS_TLB_PFN_MASK) << 6);
623     else
624     printf("(invalid) ");
625    
626     printf(" %c ",(entry->lo0 & MIPS_TLB_D_MASK) ? 'D' : ' ');
627    
628     /* 2nd page: Lo1 */
629     printf("p1=");
630    
631     if (entry->lo1 & MIPS_TLB_V_MASK)
632     printf("0x%9.9llx",(entry->lo1 & MIPS_TLB_PFN_MASK) << 6);
633     else
634     printf("(invalid) ");
635    
636     printf(" %c ",(entry->lo1 & MIPS_TLB_D_MASK) ? 'D' : ' ');
637    
638     /* page size */
639     printf(" (%s)\n",get_page_size_str(buffer,sizeof(buffer),entry->mask));
640     }
641    
642     /* Human-Readable dump of the TLB */
643     void tlb_dump(cpu_mips_t *cpu)
644     {
645     u_int i;
646    
647     printf("TLB dump:\n");
648    
649     for(i=0;i<cpu->cp0.tlb_entries;i++)
650     tlb_dump_entry(cpu,i);
651    
652     printf("\n");
653     }

  ViewVC Help
Powered by ViewVC 1.1.26