/[dynamips]/trunk/mips64_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 /trunk/mips64_cp0.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 7 /*
2     * Cisco router 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 "device.h"
19     #include "mips64.h"
20     #include "mips64_cp0.h"
21     #include "dynamips.h"
22     #include "memory.h"
23    
24     /* MIPS cp0 registers names */
25     char *mips64_cp0_reg_names[MIPS64_CP0_REG_NR] = {
26     "index" ,
27     "random",
28     "entry_lo0",
29     "entry_lo1",
30     "context",
31     "pagemask",
32     "wired",
33     "info",
34     "badvaddr",
35     "count",
36     "entry_hi",
37     "compare",
38     "status",
39     "cause",
40     "epc",
41     "prid",
42     "config",
43     "ll_addr",
44     "watch_lo",
45     "watch_hi",
46     "xcontext",
47     "cp0_r21",
48     "cp0_r22",
49     "cp0_r23",
50     "cp0_r24",
51     "cp0_r25",
52     "ecc",
53     "cache_err",
54     "tag_lo",
55     "tag_hi",
56     "err_epc",
57     "cp0_r31",
58     };
59    
60     /* Get cp0 register index given its name */
61     int mips64_cp0_get_reg_index(char *name)
62     {
63     int i;
64    
65     for(i=0;i<MIPS64_CP0_REG_NR;i++)
66     if (!strcmp(mips64_cp0_reg_names[i],name))
67     return(i);
68    
69     return(-1);
70     }
71    
72     /* Get the CPU operating mode (User,Supervisor or Kernel) - inline version */
73     static forced_inline u_int mips64_cp0_get_mode_inline(cpu_mips_t *cpu)
74     {
75     mips_cp0_t *cp0 = &cpu->cp0;
76     u_int cpu_mode;
77    
78     cpu_mode = cp0->reg[MIPS_CP0_STATUS] >> MIPS_CP0_STATUS_KSU_SHIFT;
79     cpu_mode &= MIPS_CP0_STATUS_KSU_MASK;
80     return(cpu_mode);
81     }
82    
83     /* Get the CPU operating mode (User,Supervisor or Kernel) */
84     u_int mips64_cp0_get_mode(cpu_mips_t *cpu)
85     {
86     return(mips64_cp0_get_mode_inline(cpu));
87     }
88    
89     /* Check that we are running in kernel mode */
90     int mips64_cp0_check_kernel_mode(cpu_mips_t *cpu)
91     {
92     u_int cpu_mode;
93    
94     cpu_mode = mips64_cp0_get_mode(cpu);
95    
96     if (cpu_mode != MIPS_CP0_STATUS_KM) {
97     /* XXX Branch delay slot */
98     mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_ILLOP,0);
99     return(1);
100     }
101    
102     return(0);
103     }
104    
105     /* Get value of random register */
106     static inline u_int mips64_cp0_get_random_reg(cpu_mips_t *cpu)
107     {
108     u_int wired;
109    
110     /* We use the virtual count register as a basic "random" value */
111     wired = cpu->cp0.reg[MIPS_CP0_WIRED];
112     return(wired + (cpu->cp0_virt_cnt_reg % (cpu->cp0.tlb_entries - wired)));
113     }
114    
115     /* Get a cp0 register (fast version) */
116     static inline m_uint64_t mips64_cp0_get_reg_fast(cpu_mips_t *cpu,u_int cp0_reg)
117     {
118     mips_cp0_t *cp0 = &cpu->cp0;
119     m_uint32_t delta,res;
120    
121     switch(cp0_reg) {
122     case MIPS_CP0_COUNT:
123     delta = cpu->cp0_virt_cmp_reg - cpu->cp0_virt_cnt_reg;
124     res = (m_uint32_t)cp0->reg[MIPS_CP0_COMPARE];
125     res -= cpu->vm->clock_divisor * delta;
126     return(sign_extend(res,32));
127    
128     #if 1
129     case MIPS_CP0_COMPARE:
130     return(sign_extend(cp0->reg[MIPS_CP0_COMPARE],32));
131     #else
132     /* really useful and logical ? */
133     case MIPS_CP0_COMPARE:
134     delta = cpu->cp0_virt_cmp_reg - cpu->cp0_virt_cnt_reg;
135     res = (m_uint32_t)cp0->reg[MIPS_CP0_COUNT];
136     res += (cpu->vm->clock_divisor * delta);
137     return(res);
138     #endif
139     case MIPS_CP0_INFO:
140     return(MIPS64_R7000_TLB64_ENABLE);
141    
142     case MIPS_CP0_RANDOM:
143     return(mips64_cp0_get_random_reg(cpu));
144    
145     default:
146     return(cp0->reg[cp0_reg]);
147     }
148     }
149    
150     /* Get a cp0 register */
151     m_uint64_t mips64_cp0_get_reg(cpu_mips_t *cpu,u_int cp0_reg)
152     {
153     return(mips64_cp0_get_reg_fast(cpu,cp0_reg));
154     }
155    
156     /* Set a cp0 register */
157     static inline void mips64_cp0_set_reg(cpu_mips_t *cpu,u_int cp0_reg,
158     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 mips64_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->gen,"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 mips64_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->gen,
275     "CP0_S1","trying to set unknown register %u (val=0x%x)\n",
276     cp0_s1_reg,val);
277     }
278     }
279    
280     /* DMFC0 */
281     fastcall void mips64_cp0_exec_dmfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
282     {
283     cpu->gpr[gp_reg] = mips64_cp0_get_reg_fast(cpu,cp0_reg);
284     }
285    
286     /* DMTC0 */
287     fastcall void mips64_cp0_exec_dmtc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
288     {
289     mips64_cp0_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg]);
290     }
291    
292     /* MFC0 */
293     fastcall void mips64_cp0_exec_mfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
294     {
295     cpu->gpr[gp_reg] = sign_extend(mips64_cp0_get_reg_fast(cpu,cp0_reg),32);
296     }
297    
298     /* MTC0 */
299     fastcall void mips64_cp0_exec_mtc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
300     {
301     mips64_cp0_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg] & 0xffffffff);
302     }
303    
304     /* CFC0 */
305     fastcall void mips64_cp0_exec_cfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
306     {
307     cpu->gpr[gp_reg] = sign_extend(mips64_cp0_s1_get_reg(cpu,cp0_reg),32);
308     }
309    
310     /* CTC0 */
311     fastcall void mips64_cp0_exec_ctc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
312     {
313     mips64_cp0_s1_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg] & 0xffffffff);
314     }
315    
316     /* Get the page size corresponding to a page mask */
317     static inline m_uint32_t get_page_size(m_uint32_t page_mask)
318     {
319     return((page_mask + 0x2000) >> 1);
320     }
321    
322     /* Write page size in buffer */
323     static char *get_page_size_str(char *buffer,size_t len,m_uint32_t page_mask)
324     {
325     m_uint32_t page_size;
326    
327     page_size = get_page_size(page_mask);
328    
329     /* Mb ? */
330     if (page_size >= (1024*1024))
331     snprintf(buffer,len,"%uMB",page_size >> 20);
332     else
333     snprintf(buffer,len,"%uKB",page_size >> 10);
334    
335     return buffer;
336     }
337    
338     /* Get the VPN2 mask */
339     static forced_inline m_uint64_t mips64_cp0_get_vpn2_mask(cpu_mips_t *cpu)
340     {
341     if (cpu->addr_mode == 64)
342     return(MIPS_TLB_VPN2_MASK_64);
343     else
344     return(MIPS_TLB_VPN2_MASK_32);
345     }
346    
347     /* TLB lookup */
348     int mips64_cp0_tlb_lookup(cpu_mips_t *cpu,m_uint64_t vaddr,mts_map_t *res)
349     {
350     mips_cp0_t *cp0 = &cpu->cp0;
351     m_uint64_t vpn_addr,vpn2_mask;
352     m_uint64_t page_mask,hi_addr;
353     m_uint32_t page_size,pca;
354     tlb_entry_t *entry;
355     u_int asid;
356     int i;
357    
358     vpn2_mask = mips64_cp0_get_vpn2_mask(cpu);
359     vpn_addr = vaddr & vpn2_mask;
360    
361     asid = cp0->reg[MIPS_CP0_TLB_HI] & MIPS_TLB_ASID_MASK;
362    
363     for(i=0;i<cp0->tlb_entries;i++) {
364     entry = &cp0->tlb[i];
365    
366     page_mask = ~(entry->mask + 0x1FFF);
367     hi_addr = entry->hi & vpn2_mask;
368    
369     if (((vpn_addr & page_mask) == hi_addr) &&
370     ((entry->hi & MIPS_TLB_G_MASK) ||
371     ((entry->hi & MIPS_TLB_ASID_MASK) == asid)))
372     {
373     page_size = get_page_size(entry->mask);
374    
375     if ((vaddr & page_size) == 0) {
376     /* Even Page */
377     if (entry->lo0 & MIPS_TLB_V_MASK) {
378     res->vaddr = vaddr & MIPS_MIN_PAGE_MASK;
379     res->paddr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6;
380     res->paddr += (res->vaddr & (page_size-1));
381     res->paddr &= cpu->addr_bus_mask;
382    
383 dpavlin 11 res->offset = vaddr & MIPS_MIN_PAGE_IMASK;
384    
385 dpavlin 7 pca = (entry->lo0 & MIPS_TLB_C_MASK);
386     pca >>= MIPS_TLB_C_SHIFT;
387     res->cached = mips64_cca_cached(pca);
388    
389     res->tlb_index = i;
390     return(TRUE);
391     }
392     } else {
393     /* Odd Page */
394     if (entry->lo1 & MIPS_TLB_V_MASK) {
395    
396     res->vaddr = vaddr & MIPS_MIN_PAGE_MASK;
397     res->paddr = (entry->lo1 & MIPS_TLB_PFN_MASK) << 6;
398     res->paddr += (res->vaddr & (page_size-1));
399     res->paddr &= cpu->addr_bus_mask;
400    
401 dpavlin 11 res->offset = vaddr & MIPS_MIN_PAGE_IMASK;
402    
403 dpavlin 7 pca = (entry->lo1 & MIPS_TLB_C_MASK);
404     pca >>= MIPS_TLB_C_SHIFT;
405     res->cached = mips64_cca_cached(pca);
406    
407     res->tlb_index = i;
408     return(TRUE);
409     }
410     }
411    
412     /* Invalid entry */
413     return(FALSE);
414     }
415     }
416    
417     /* No matching entry */
418     return(FALSE);
419     }
420    
421     /*
422     * Map a TLB entry into the MTS.
423     *
424     * We apply the physical address bus masking here.
425     *
426     * TODO: - Manage ASID
427     * - Manage CPU Mode (user,supervisor or kernel)
428     */
429     void mips64_cp0_map_tlb_to_mts(cpu_mips_t *cpu,int index)
430     {
431     m_uint64_t v0_addr,v1_addr,p0_addr,p1_addr;
432     m_uint32_t page_size,pca;
433     tlb_entry_t *entry;
434     int cacheable;
435    
436     entry = &cpu->cp0.tlb[index];
437    
438     page_size = get_page_size(entry->mask);
439     v0_addr = entry->hi & mips64_cp0_get_vpn2_mask(cpu);
440     v1_addr = v0_addr + page_size;
441    
442     if (entry->lo0 & MIPS_TLB_V_MASK) {
443     pca = (entry->lo0 & MIPS_TLB_C_MASK);
444     pca >>= MIPS_TLB_C_SHIFT;
445     cacheable = mips64_cca_cached(pca);
446    
447     p0_addr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6;
448     cpu->mts_map(cpu,v0_addr,p0_addr & cpu->addr_bus_mask,page_size,
449     cacheable,index);
450     }
451    
452     if (entry->lo1 & MIPS_TLB_V_MASK) {
453     pca = (entry->lo1 & MIPS_TLB_C_MASK);
454     pca >>= MIPS_TLB_C_SHIFT;
455     cacheable = mips64_cca_cached(pca);
456    
457     p1_addr = (entry->lo1 & MIPS_TLB_PFN_MASK) << 6;
458     cpu->mts_map(cpu,v1_addr,p1_addr & cpu->addr_bus_mask,page_size,
459     cacheable,index);
460     }
461     }
462    
463     /*
464     * Unmap a TLB entry in the MTS.
465     */
466     void mips64_cp0_unmap_tlb_to_mts(cpu_mips_t *cpu,int index)
467     {
468     m_uint64_t v0_addr,v1_addr;
469     m_uint32_t page_size;
470     tlb_entry_t *entry;
471    
472     entry = &cpu->cp0.tlb[index];
473    
474     page_size = get_page_size(entry->mask);
475     v0_addr = entry->hi & mips64_cp0_get_vpn2_mask(cpu);
476     v1_addr = v0_addr + page_size;
477    
478     if (entry->lo0 & MIPS_TLB_V_MASK)
479     cpu->mts_unmap(cpu,v0_addr,page_size,MTS_ACC_T,index);
480    
481     if (entry->lo1 & MIPS_TLB_V_MASK)
482     cpu->mts_unmap(cpu,v1_addr,page_size,MTS_ACC_T,index);
483     }
484    
485     /* Map all TLB entries into the MTS */
486     void mips64_cp0_map_all_tlb_to_mts(cpu_mips_t *cpu)
487     {
488     int i;
489    
490     for(i=0;i<cpu->cp0.tlb_entries;i++)
491     mips64_cp0_map_tlb_to_mts(cpu,i);
492     }
493    
494     /* TLBP: Probe a TLB entry */
495     fastcall void mips64_cp0_exec_tlbp(cpu_mips_t *cpu)
496     {
497     mips_cp0_t *cp0 = &cpu->cp0;
498     m_uint64_t hi_reg,asid;
499     m_uint64_t vpn2,vpn2_mask;
500     tlb_entry_t *entry;
501     int i;
502    
503     vpn2_mask = mips64_cp0_get_vpn2_mask(cpu);
504     hi_reg = cp0->reg[MIPS_CP0_TLB_HI];
505     asid = hi_reg & MIPS_TLB_ASID_MASK;
506     vpn2 = hi_reg & vpn2_mask;
507    
508     cp0->reg[MIPS_CP0_INDEX] = 0xffffffff80000000ULL;
509    
510     for(i=0;i<cp0->tlb_entries;i++) {
511     entry = &cp0->tlb[i];
512    
513     if (((entry->hi & vpn2_mask) == vpn2) &&
514     ((entry->hi & MIPS_TLB_G_MASK) ||
515     ((entry->hi & MIPS_TLB_ASID_MASK) == asid)))
516     {
517     cp0->reg[MIPS_CP0_INDEX] = i;
518     #if DEBUG_TLB_ACTIVITY
519     printf("CPU: CP0_TLBP returned %u\n",i);
520     tlb_dump(cpu);
521     #endif
522     }
523     }
524     }
525    
526     /* TLBR: Read Indexed TLB entry */
527     fastcall void mips64_cp0_exec_tlbr(cpu_mips_t *cpu)
528     {
529     mips_cp0_t *cp0 = &cpu->cp0;
530     tlb_entry_t *entry;
531     u_int index;
532    
533     index = cp0->reg[MIPS_CP0_INDEX];
534    
535     #if DEBUG_TLB_ACTIVITY
536     cpu_log(cpu,"TLB","CP0_TLBR: reading entry %u.\n",index);
537     #endif
538    
539     if (index < cp0->tlb_entries)
540     {
541     entry = &cp0->tlb[index];
542    
543     cp0->reg[MIPS_CP0_PAGEMASK] = entry->mask;
544     cp0->reg[MIPS_CP0_TLB_HI] = entry->hi;
545     cp0->reg[MIPS_CP0_TLB_LO_0] = entry->lo0;
546     cp0->reg[MIPS_CP0_TLB_LO_1] = entry->lo1;
547    
548     /*
549     * The G bit must be reported in both Lo0 and Lo1 registers,
550     * and cleared in Hi register.
551     */
552     if (entry->hi & MIPS_TLB_G_MASK) {
553     cp0->reg[MIPS_CP0_TLB_LO_0] |= MIPS_CP0_LO_G_MASK;
554     cp0->reg[MIPS_CP0_TLB_LO_1] |= MIPS_CP0_LO_G_MASK;
555     cp0->reg[MIPS_CP0_TLB_HI] &= ~MIPS_TLB_G_MASK;
556     }
557     }
558     }
559    
560     /* TLBW: Write a TLB entry */
561     static inline void mips64_cp0_exec_tlbw(cpu_mips_t *cpu,u_int index)
562     {
563     mips_cp0_t *cp0 = &cpu->cp0;
564     tlb_entry_t *entry;
565    
566     #if DEBUG_TLB_ACTIVITY
567     cpu_log(cpu,"TLB","CP0_TLBWI: writing entry %u "
568     "[mask=0x%8.8llx,hi=0x%8.8llx,lo0=0x%8.8llx,lo1=0x%8.8llx]\n",
569     index,cp0->reg[MIPS_CP0_PAGEMASK],cp0->reg[MIPS_CP0_TLB_HI],
570     cp0->reg[MIPS_CP0_TLB_LO_0],cp0->reg[MIPS_CP0_TLB_LO_1]);
571     #endif
572    
573     if (index < cp0->tlb_entries)
574     {
575     entry = &cp0->tlb[index];
576    
577     /* Unmap the old entry if it was valid */
578     mips64_cp0_unmap_tlb_to_mts(cpu,index);
579    
580     entry->mask = cp0->reg[MIPS_CP0_PAGEMASK] & MIPS_TLB_PAGE_MASK;
581     entry->hi = cp0->reg[MIPS_CP0_TLB_HI] & ~entry->mask;
582     entry->hi &= MIPS_CP0_HI_SAFE_MASK; /* clear G bit */
583     entry->lo0 = cp0->reg[MIPS_CP0_TLB_LO_0];
584     entry->lo1 = cp0->reg[MIPS_CP0_TLB_LO_1];
585    
586     /* if G bit is set in lo0 and lo1, set it in hi */
587     if ((entry->lo0 & entry->lo1) & MIPS_CP0_LO_G_MASK)
588     entry->hi |= MIPS_TLB_G_MASK;
589    
590     /* Clear G bit in TLB lo0 and lo1 */
591     entry->lo0 &= ~MIPS_CP0_LO_G_MASK;
592     entry->lo1 &= ~MIPS_CP0_LO_G_MASK;
593    
594     /* Inform the MTS subsystem */
595     mips64_cp0_map_tlb_to_mts(cpu,index);
596    
597     #if DEBUG_TLB_ACTIVITY
598     mips64_tlb_dump_entry(cpu,index);
599     #endif
600     }
601     }
602    
603     /* TLBWI: Write Indexed TLB entry */
604     fastcall void mips64_cp0_exec_tlbwi(cpu_mips_t *cpu)
605     {
606     mips64_cp0_exec_tlbw(cpu,cpu->cp0.reg[MIPS_CP0_INDEX]);
607     }
608    
609     /* TLBWR: Write Random TLB entry */
610     fastcall void mips64_cp0_exec_tlbwr(cpu_mips_t *cpu)
611     {
612     mips64_cp0_exec_tlbw(cpu,mips64_cp0_get_random_reg(cpu));
613     }
614    
615     /* Raw dump of the TLB */
616     void mips64_tlb_raw_dump(cpu_gen_t *cpu)
617     {
618     cpu_mips_t *mcpu = CPU_MIPS64(cpu);
619     tlb_entry_t *entry;
620     u_int i;
621    
622     printf("TLB dump:\n");
623    
624     for(i=0;i<mcpu->cp0.tlb_entries;i++) {
625     entry = &mcpu->cp0.tlb[i];
626     printf(" %2d: mask=0x%16.16llx hi=0x%16.16llx "
627     "lo0=0x%16.16llx lo1=0x%16.16llx\n",
628     i, entry->mask, entry->hi, entry->lo0, entry->lo1);
629     }
630    
631     printf("\n");
632     }
633    
634     /* Dump the specified TLB entry */
635     void mips64_tlb_dump_entry(cpu_mips_t *cpu,u_int index)
636     {
637     tlb_entry_t *entry;
638     char buffer[256];
639    
640     entry = &cpu->cp0.tlb[index];
641    
642     /* virtual Address */
643     printf(" %2d: vaddr=0x%8.8llx ",
644     index, entry->hi & mips64_cp0_get_vpn2_mask(cpu));
645    
646     /* global or ASID */
647     if (entry->hi & MIPS_TLB_G_MASK)
648     printf("(global) ");
649     else
650     printf("(asid 0x%2.2llx) ",entry->hi & MIPS_TLB_ASID_MASK);
651    
652     /* 1st page: Lo0 */
653     printf("p0=");
654    
655     if (entry->lo0 & MIPS_TLB_V_MASK)
656     printf("0x%9.9llx",(entry->lo0 & MIPS_TLB_PFN_MASK) << 6);
657     else
658     printf("(invalid) ");
659    
660     printf(" %c ",(entry->lo0 & MIPS_TLB_D_MASK) ? 'D' : ' ');
661    
662     /* 2nd page: Lo1 */
663     printf("p1=");
664    
665     if (entry->lo1 & MIPS_TLB_V_MASK)
666     printf("0x%9.9llx",(entry->lo1 & MIPS_TLB_PFN_MASK) << 6);
667     else
668     printf("(invalid) ");
669    
670     printf(" %c ",(entry->lo1 & MIPS_TLB_D_MASK) ? 'D' : ' ');
671    
672     /* page size */
673     printf(" (%s)\n",get_page_size_str(buffer,sizeof(buffer),entry->mask));
674     }
675    
676     /* Human-Readable dump of the TLB */
677     void mips64_tlb_dump(cpu_gen_t *cpu)
678     {
679     cpu_mips_t *mcpu = CPU_MIPS64(cpu);
680     u_int i;
681    
682     printf("TLB dump:\n");
683    
684     for(i=0;i<mcpu->cp0.tlb_entries;i++)
685     mips64_tlb_dump_entry(mcpu,i);
686    
687     printf("\n");
688     }

  ViewVC Help
Powered by ViewVC 1.1.26