PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
tlbsrc.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Licenced under Academic Free License version 2.0
7# Review ps2sdk README & LICENSE files for further details.
8*/
9
10#include <kernel.h>
11#include <ee_cop0_defs.h>
12
13/* // Doesn't work, but here are the COP0 register definitions:
14#define Index $0
15#define EntryLo0 $2
16#define EntryLo1 $3
17#define PageMask $5
18#define Wired $6
19#define EntryHi $10 */
20
22{
23 unsigned int syscall;
24 void *function;
25};
26
27char *_kExecArg[] __attribute__((section(".kExecArg")));
28char *_kExecArg[] = {NULL}; /* 0x80075330 */
29
30// Function prototypes:
31int PutTLBEntry(unsigned int PageMask, unsigned int EntryHi, unsigned int EntryLo0, unsigned int EntryLo1);
32int SetTLBEntry(unsigned int index, unsigned int PageMask, unsigned int EntryHi, unsigned int EntryLo0, unsigned int EntryLo1);
33int GetTLBEntry(unsigned int index, unsigned int *PageMask, unsigned int *EntryHi, unsigned int *EntryLo0, unsigned int *EntryLo1);
34int ProbeTLBEntry(unsigned int EntryHi, unsigned int *PageMask, unsigned int *EntryLo0, unsigned int *EntryLo1);
35int ExpandScratchPad(unsigned int page);
36
37static const struct SyscallPatchData SyscallPatchData[] = {
38 {0x55, &PutTLBEntry},
39 {0x56, &SetTLBEntry},
40 {0x57, &GetTLBEntry},
41 {0x58, &ProbeTLBEntry},
42 {0x59, &ExpandScratchPad},
43 {0x03, &_kExecArg},
44};
45
46int _start(int syscall) __attribute__((section(".start")));
47
48/* 0x80075000 */
49int _start(int syscall)
50{
51 unsigned int i;
52
53 for (i = 0; i < 6; i++) {
54 if (SyscallPatchData[i].syscall == syscall) {
55 return ((unsigned int)SyscallPatchData[i].function);
56 }
57 }
58
59 return 0;
60}
61
62/* 0x80075038 */
63int PutTLBEntry(unsigned int PageMask, unsigned int EntryHi, unsigned int EntryLo0, unsigned int EntryLo1)
64{
65 int result;
66
67 switch (EntryHi >> 24) {
68 case 0x40:
69 case 0x30:
70 case 0x20:
71 case 0x00:
72 __asm volatile("mtc0 %1, $5\n"
73 "mtc0 %2, $10\n"
74 "mtc0 %3, $2\n"
75 "mtc0 %4, $3\n"
76 "sync.p\n"
77 "tlbwr\n"
78 "sync.p\n"
79 "tlbp\n"
80 "sync.p\n"
81 "mfc0 %0, $0\n"
82 : "=r"(result)
83 : "r"(PageMask), "r"(EntryHi), "r"(EntryLo0), "r"(EntryLo1));
84 break;
85 case 0x50:
86 case 0x10:
87 default: // SP193: I don't remember seeing a default case. Anyway... Keeping Compilers Happy (TM).
88 result = -1;
89 }
90
91 return result;
92}
93
94/* 0x800750c8 */
95int SetTLBEntry(unsigned int index, unsigned int PageMask, unsigned int EntryHi, unsigned int EntryLo0, unsigned int EntryLo1)
96{
97 int result;
98
99 if (index < 0x30) {
100 __asm volatile("mtc0 %0, $0\n"
101 "mtc0 %1, $5\n"
102 "mtc0 %2, $10\n"
103 "mtc0 %3, $2\n"
104 "mtc0 %4, $3\n"
105 "sync.p\n"
106 "tlbwi\n"
107 "sync.p\n" ::"r"(index),
108 "r"(PageMask), "r"(EntryHi), "r"(EntryLo0), "r"(EntryLo1));
109
110 result = index;
111 } else
112 result = -1;
113
114 return result;
115}
116
117/* 0x80075108 */
118int GetTLBEntry(unsigned int index, unsigned int *PageMask, unsigned int *EntryHi, unsigned int *EntryLo0, unsigned int *EntryLo1)
119{
120 int result;
121
122 if (index < 0x30) {
123 __asm volatile("mtc0 %0, $0\n"
124 "sync.p\n"
125 "tlbr\n"
126 "sync.p\n"
127 "mfc0 $v0, $5\n"
128 "sw $v0, (%1)\n"
129 "mfc0 $v0, $10\n"
130 "sw $v0, (%2)\n"
131 "mfc0 $v0, $2\n"
132 "sw $v0, (%3)\n"
133 "mfc0 $v0, $3\n"
134 "sw $v0, (%4)\n" ::"r"(index),
135 "r"(PageMask), "r"(EntryHi), "r"(EntryLo0), "r"(EntryLo1));
136
137 result = index;
138 } else
139 result = -1;
140
141 return result;
142}
143
144/* 0x80075158 */
145int ProbeTLBEntry(unsigned int EntryHi, unsigned int *PageMask, unsigned int *EntryLo0, unsigned int *EntryLo1)
146{
147 int result, index;
148
149 __asm volatile("mtc0 %1, $10\n"
150 "sync.p\n"
151 "tlbp\n"
152 "sync.p\n"
153 "mfc0 %0, $0\n"
154 : "=r"(index)
155 : "r"(EntryHi));
156
157 if (index >= 0) {
158 __asm volatile("tlbr\n"
159 "sync.p\n"
160 "mfc0 $v0, $5\n"
161 "sw $v0, (%0)\n"
162 "mfc0 $v1, $2\n"
163 "sw $v1, (%1)\n"
164 "mfc0 $v0, $3\n"
165 "sw $v0, (%2)\n" ::"r"(PageMask),
166 "r"(EntryLo0), "r"(EntryLo1));
167
168 result = index;
169 } else
170 result = -1;
171
172 return result;
173}
174
175/* 0x800751a8 */
176int ExpandScratchPad(unsigned int page)
177{
178 int result;
179
180 if (!(page & 0xFFF)) {
181 if (0xFFFFE < page - 1) {
182 int index;
183 unsigned int PageMask, EntryHi, EntryLo0, EntryLo1;
184 if ((index = ProbeTLBEntry(0x70004000, &PageMask, &EntryLo0, &EntryLo1)) >= 0) {
185#if 0
186 // This condition is always false due to the preceding check on the "page" variable.
187 if (page == 0) {
188 EntryHi = 0xE0010000 + ((index - 1) << 13);
189
190 __asm volatile("mfc0 $v0, $6\n"
191 "addiu $v0, $v0, 0xFFFF\n"
192 "mtc0 $v0, $6\n"
193 "mtc0 %0, $0\n"
194 "mtc0 $zero, $5\n"
195 "mtc0 %1, $10\n"
196 "mtc0 $zero, $2\n"
197 "mtc0 $zero, $3\n"
198 "sync.p\n"
199 "tlbwi\n"
200 "sync.p\n" ::"r"(index),
201 "r"(EntryHi));
202 } else
203#endif
204 {
205 __asm volatile("mfc0 %0, $6\n"
206 "addiu $v0, %0, 1\n"
207 "mtc0 $v0, $6\n" ::"r"(index));
208 }
209 }
210
211 if (page != 0) {
212 /* Not sure why this code saves the EntryLo0 and EntryLo1 values on the stack, and sets a word on the stack to zero, but does not use them:
213
214 0($sp)=0
215 4($sp)=$v0=(page+0x1000&0xFFFFF000)>>6|0x1F
216 8($sp)=$a0=(page&0xFFFFF000)>>6|0x1F */
217
218 EntryHi = 0x70004000;
219 EntryLo0 = ((page + 0x1000) & 0xFFFFF000) >> 6 | 0x1F;
220 EntryLo1 = (page & 0xFFFFF000) >> 6 | 0x1F;
221
222 __asm volatile("mtc0 %0, $0\n"
223 "daddu $v1, $zero, $zero\n"
224 "mtc0 $v1, $5\n"
225 "mtc0 %1, $10\n"
226 "mtc0 %2, $2\n"
227 "mtc0 %3, $3\n"
228 "sync.p\n"
229 "tlbwi\n"
230 "sync.p\n" ::"r"(index),
231 "r"(EntryHi), "r"(EntryLo0), "r"(EntryLo1));
232
233 result = index;
234 } else
235 result = 0;
236 } else
237 result = -1;
238 } else
239 result = -1;
240
241 return result;
242}