334 |
return buffer; |
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 */ |
/* TLB lookup */ |
347 |
int cp0_tlb_lookup(cpu_mips_t *cpu,m_uint64_t vaddr,mts_map_t *res) |
int cp0_tlb_lookup(cpu_mips_t *cpu,m_uint64_t vaddr,mts_map_t *res) |
348 |
{ |
{ |
349 |
mips_cp0_t *cp0 = &cpu->cp0; |
mips_cp0_t *cp0 = &cpu->cp0; |
350 |
m_uint64_t v0_addr,v1_addr; |
m_uint64_t vpn_addr,vpn2_mask; |
351 |
|
m_uint64_t page_mask,hi_addr; |
352 |
m_uint32_t page_size,pca; |
m_uint32_t page_size,pca; |
353 |
tlb_entry_t *entry; |
tlb_entry_t *entry; |
354 |
|
u_int asid; |
355 |
int i; |
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++) { |
for(i=0;i<cp0->tlb_entries;i++) { |
362 |
entry = &cp0->tlb[i]; |
entry = &cp0->tlb[i]; |
363 |
|
|
364 |
page_size = get_page_size(entry->mask); |
page_mask = ~(entry->mask + 0x1FFF); |
365 |
v0_addr = entry->hi & MIPS_TLB_VPN2_MASK; |
hi_addr = entry->hi & vpn2_mask; |
|
v1_addr = v0_addr + page_size; |
|
|
|
|
|
/* virtual address in entry 0 ? */ |
|
|
if ((entry->lo0 & MIPS_TLB_V_MASK) && |
|
|
(vaddr >= v0_addr) && (vaddr < v1_addr)) |
|
|
{ |
|
|
res->vaddr = v0_addr; |
|
|
res->paddr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6; |
|
|
res->paddr &= cpu->addr_bus_mask; |
|
|
res->len = page_size; |
|
|
|
|
|
pca = (entry->lo0 & MIPS_TLB_C_MASK); |
|
|
pca >>= MIPS_TLB_C_SHIFT; |
|
|
res->cached = mips64_cca_cached(pca); |
|
|
|
|
|
res->tlb_index = i; |
|
|
return(TRUE); |
|
|
} |
|
366 |
|
|
367 |
/* virtual address in entry 1 ? */ |
if (((vpn_addr & page_mask) == hi_addr) && |
368 |
if ((entry->lo1 & MIPS_TLB_V_MASK) && |
((entry->hi & MIPS_TLB_G_MASK) || |
369 |
(vaddr >= v1_addr) && ((vaddr - v1_addr) < page_size)) |
((entry->hi & MIPS_TLB_ASID_MASK) == asid))) |
370 |
{ |
{ |
371 |
res->vaddr = v1_addr; |
page_size = get_page_size(entry->mask); |
372 |
res->paddr = (entry->lo1 & MIPS_TLB_PFN_MASK) << 6; |
|
373 |
res->paddr &= cpu->addr_bus_mask; |
if ((vaddr & page_size) == 0) { |
374 |
res->len = page_size; |
/* Even Page */ |
375 |
|
if (entry->lo0 & MIPS_TLB_V_MASK) { |
376 |
pca = (entry->lo1 & MIPS_TLB_C_MASK); |
res->vaddr = vaddr & page_mask; |
377 |
pca >>= MIPS_TLB_C_SHIFT; |
res->paddr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6; |
378 |
res->cached = mips64_cca_cached(pca); |
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 |
res->tlb_index = i; |
/* Invalid entry */ |
406 |
return(TRUE); |
return(FALSE); |
407 |
} |
} |
408 |
} |
} |
409 |
|
|
410 |
|
/* No matching entry */ |
411 |
return(FALSE); |
return(FALSE); |
412 |
} |
} |
413 |
|
|
429 |
entry = &cpu->cp0.tlb[index]; |
entry = &cpu->cp0.tlb[index]; |
430 |
|
|
431 |
page_size = get_page_size(entry->mask); |
page_size = get_page_size(entry->mask); |
432 |
v0_addr = entry->hi & MIPS_TLB_VPN2_MASK; |
v0_addr = entry->hi & cp0_get_vpn2_mask(cpu); |
433 |
v1_addr = v0_addr + page_size; |
v1_addr = v0_addr + page_size; |
434 |
|
|
435 |
if (entry->lo0 & MIPS_TLB_V_MASK) { |
if (entry->lo0 & MIPS_TLB_V_MASK) { |
465 |
entry = &cpu->cp0.tlb[index]; |
entry = &cpu->cp0.tlb[index]; |
466 |
|
|
467 |
page_size = get_page_size(entry->mask); |
page_size = get_page_size(entry->mask); |
468 |
v0_addr = entry->hi & MIPS_TLB_VPN2_MASK; |
v0_addr = entry->hi & cp0_get_vpn2_mask(cpu); |
469 |
v1_addr = v0_addr + page_size; |
v1_addr = v0_addr + page_size; |
470 |
|
|
471 |
if (entry->lo0 & MIPS_TLB_V_MASK) |
if (entry->lo0 & MIPS_TLB_V_MASK) |
488 |
fastcall void cp0_exec_tlbp(cpu_mips_t *cpu) |
fastcall void cp0_exec_tlbp(cpu_mips_t *cpu) |
489 |
{ |
{ |
490 |
mips_cp0_t *cp0 = &cpu->cp0; |
mips_cp0_t *cp0 = &cpu->cp0; |
491 |
m_uint64_t hi_reg,asid,vpn2; |
m_uint64_t hi_reg,asid; |
492 |
|
m_uint64_t vpn2,vpn2_mask; |
493 |
tlb_entry_t *entry; |
tlb_entry_t *entry; |
494 |
int i; |
int i; |
495 |
|
|
496 |
|
vpn2_mask = cp0_get_vpn2_mask(cpu); |
497 |
hi_reg = cp0->reg[MIPS_CP0_TLB_HI]; |
hi_reg = cp0->reg[MIPS_CP0_TLB_HI]; |
498 |
asid = hi_reg & MIPS_TLB_ASID_MASK; |
asid = hi_reg & MIPS_TLB_ASID_MASK; |
499 |
vpn2 = hi_reg & MIPS_TLB_VPN2_MASK; |
vpn2 = hi_reg & vpn2_mask; |
500 |
|
|
501 |
cp0->reg[MIPS_CP0_INDEX] = 0xffffffff80000000ULL; |
cp0->reg[MIPS_CP0_INDEX] = 0xffffffff80000000ULL; |
502 |
|
|
503 |
for(i=0;i<cp0->tlb_entries;i++) { |
for(i=0;i<cp0->tlb_entries;i++) { |
504 |
entry = &cp0->tlb[i]; |
entry = &cp0->tlb[i]; |
505 |
|
|
506 |
if (((entry->hi & MIPS_TLB_VPN2_MASK) == vpn2) && |
if (((entry->hi & vpn2_mask) == vpn2) && |
507 |
((entry->hi & MIPS_TLB_G_MASK) || |
((entry->hi & MIPS_TLB_G_MASK) || |
508 |
((entry->hi & MIPS_TLB_ASID_MASK) == asid))) |
((entry->hi & MIPS_TLB_ASID_MASK) == asid))) |
509 |
{ |
{ |
632 |
entry = &cpu->cp0.tlb[index]; |
entry = &cpu->cp0.tlb[index]; |
633 |
|
|
634 |
/* virtual Address */ |
/* virtual Address */ |
635 |
printf(" %2d: vaddr=0x%8.8llx ", index, entry->hi & MIPS_TLB_VPN2_MASK); |
printf(" %2d: vaddr=0x%8.8llx ", index, entry->hi & cp0_get_vpn2_mask(cpu)); |
636 |
|
|
637 |
/* global or ASID */ |
/* global or ASID */ |
638 |
if (entry->hi & MIPS_TLB_G_MASK) |
if (entry->hi & MIPS_TLB_G_MASK) |