summaryrefslogtreecommitdiff
path: root/src/libultra/os/probetlb.s
blob: 4fa8abc38e0ec5cdbfb74f80d28edda900da5014 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "ultra64/asm.h"
#include "ultra64/regdef.h"
#include "ultra64/R4300.h"

.text

/**
 *  u32 __osProbeTLB(void* vaddr);
 *
 *  Searches the TLB for the physical address associated with
 *  the virtual address `vaddr`.
 *
 *  Returns the physical address if found, or -1 if not found.
 */
LEAF(__osProbeTLB)
.set noreorder
    /* Set C0_ENTRYHI based on supplied vaddr */
    mfc0    t0, C0_ENTRYHI
    and     t1, t0, TLBHI_PIDMASK
    and     t2, a0, TLBHI_VPN2MASK
    or      t1, t1, t2
    mtc0    t1, C0_ENTRYHI
    nop
    nop
    nop
    /* TLB probe, sets C0_INX to a value matching C0_ENTRYHI. */
    /* If no match is found the TLBINX_PROBE bit is set to indicate this. */
    tlbp
    nop
    nop
    /* Read result */
    mfc0    t3, C0_INX
    and     t3, t3, TLBINX_PROBE
    /* Branch if no match was found */
    bnez    t3, 3f
     nop

    /* Read TLB, sets C0_ENTRYHI, C0_ENTRYLO0, C0_ENTRYLO1 and C0_PAGEMASK for the TLB */
    /* entry indicated by C0_INX */
    tlbr
    nop
    nop
    nop
    /* Calculate page size = (page mask + 0x2000) >> 1 */
    mfc0    t3, C0_PAGEMASK
    add     t3, t3, 0x2000
    srl     t3, t3, 1
    /* & with vaddr */
    and     t4, t3, a0
    /* Select C0_ENTRYLO0 or C0_ENTRYLO1 */
    bnez    t4, 1f
     add    t3, t3, -1 /* make bitmask out of page size */
    mfc0    v0, C0_ENTRYLO0
    b       2f
     nop
1:
    mfc0    v0, C0_ENTRYLO1
2:
    /* Check valid bit and branch if not valid */
    and     t5, v0, TLBLO_V
    beqz    t5, 3f
     nop

    /* Extract the Page Frame Number from the entry */
    and     v0, v0, TLBLO_PFNMASK
    sll     v0, v0, TLBLO_PFNSHIFT
    /* Mask vaddr with page size mask */
    and     t5, a0, t3
    /* Add masked vaddr to pfn to obtain the physical address */
    add     v0, v0, t5
    b       4f
     nop
3:
    /* No physical address for the supplied virtual address was found, */
    /* return -1 */
    li      v0, -1
4:
    /* Restore original C0_ENTRYHI value before returning */
    mtc0    t0, C0_ENTRYHI
    jr      ra
     nop
.set reorder
END(__osProbeTLB)