PS2SDK
PS2 Homebrew Libraries
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 #include <mipscopaccess.h>
13 
14 /* // Doesn't work, but here are the COP0 register definitions:
15 #define Index $0
16 #define EntryLo0 $2
17 #define EntryLo1 $3
18 #define PageMask $5
19 #define Wired $6
20 #define EntryHi $10 */
21 
22 struct SyscallPatchData
23 {
24  unsigned int syscall;
25  void *function;
26 };
27 
28 char *_kExecArg[] __attribute__((section(".kExecArg")));
29 char *_kExecArg[] = {NULL}; /* 0x80075330 */
30 
31 // Function prototypes:
32 int PutTLBEntry(unsigned int PageMask, unsigned int EntryHi, unsigned int EntryLo0, unsigned int EntryLo1);
33 int SetTLBEntry(unsigned int index, unsigned int PageMask, unsigned int EntryHi, unsigned int EntryLo0, unsigned int EntryLo1);
34 int GetTLBEntry(unsigned int index, unsigned int *PageMask, unsigned int *EntryHi, unsigned int *EntryLo0, unsigned int *EntryLo1);
35 int ProbeTLBEntry(unsigned int EntryHi, unsigned int *PageMask, unsigned int *EntryLo0, unsigned int *EntryLo1);
36 int ExpandScratchPad(unsigned int page);
37 
38 static const struct SyscallPatchData SyscallPatchData[] = {
39  {0x55, &PutTLBEntry},
40  {0x56, &SetTLBEntry},
41  {0x57, &GetTLBEntry},
42  {0x58, &ProbeTLBEntry},
43  {0x59, &ExpandScratchPad},
44  {0x03, &_kExecArg},
45 };
46 
47 int _start(int syscall) __attribute__((section(".start")));
48 
49 /* 0x80075000 */
50 int _start(int syscall)
51 {
52  unsigned int i;
53 
54  for (i = 0; i < 6; i++) {
55  if (SyscallPatchData[i].syscall == syscall) {
56  return ((unsigned int)SyscallPatchData[i].function);
57  }
58  }
59 
60  return 0;
61 }
62 
63 /* 0x80075038 */
64 int PutTLBEntry(unsigned int PageMask, unsigned int EntryHi, unsigned int EntryLo0, unsigned int EntryLo1)
65 {
66  int result;
67 
68  switch (EntryHi >> 24) {
69  case 0x40:
70  case 0x30:
71  case 0x20:
72  case 0x00:
73  set_mips_cop_reg(0, COP0_REG_PageMask, PageMask);
74  set_mips_cop_reg(0, COP0_REG_EntryHi, EntryHi);
75  set_mips_cop_reg(0, COP0_REG_EntryLo0, EntryLo0);
76  set_mips_cop_reg(0, COP0_REG_EntryLo1, EntryLo1);
77  EE_SYNCP();
78  __asm__ __volatile__("tlbwr\n");
79  EE_SYNCP();
80  __asm__ __volatile__("tlbp\n");
81  EE_SYNCP();
82  result = get_mips_cop_reg(0, COP0_REG_Index);
83  break;
84  case 0x50:
85  case 0x10:
86  default: // SP193: I don't remember seeing a default case. Anyway... Keeping Compilers Happy (TM).
87  result = -1;
88  }
89 
90  return result;
91 }
92 
93 /* 0x800750c8 */
94 int SetTLBEntry(unsigned int index, unsigned int PageMask, unsigned int EntryHi, unsigned int EntryLo0, unsigned int EntryLo1)
95 {
96  int result;
97 
98  if (index < 0x30) {
99  set_mips_cop_reg(0, COP0_REG_Index, index);
100  set_mips_cop_reg(0, COP0_REG_PageMask, PageMask);
101  set_mips_cop_reg(0, COP0_REG_EntryHi, EntryHi);
102  set_mips_cop_reg(0, COP0_REG_EntryLo0, EntryLo0);
103  set_mips_cop_reg(0, COP0_REG_EntryLo1, EntryLo1);
104  EE_SYNCP();
105  __asm__ __volatile__("tlbwi\n");
106  EE_SYNCP();
107 
108  result = index;
109  } else
110  result = -1;
111 
112  return result;
113 }
114 
115 /* 0x80075108 */
116 int GetTLBEntry(unsigned int index, unsigned int *PageMask, unsigned int *EntryHi, unsigned int *EntryLo0, unsigned int *EntryLo1)
117 {
118  int result;
119 
120  if (index < 0x30) {
121  set_mips_cop_reg(0, COP0_REG_Index, index);
122  EE_SYNCP();
123  __asm__ __volatile__("tlbr\n");
124  EE_SYNCP();
125  *PageMask = get_mips_cop_reg(0, COP0_REG_PageMask);
126  *EntryHi = get_mips_cop_reg(0, COP0_REG_EntryHi);
127  *EntryLo0 = get_mips_cop_reg(0, COP0_REG_EntryLo0);
128  *EntryLo1 = get_mips_cop_reg(0, COP0_REG_EntryLo1);
129 
130  result = index;
131  } else
132  result = -1;
133 
134  return result;
135 }
136 
137 /* 0x80075158 */
138 int ProbeTLBEntry(unsigned int EntryHi, unsigned int *PageMask, unsigned int *EntryLo0, unsigned int *EntryLo1)
139 {
140  int result, index;
141 
142  set_mips_cop_reg(0, COP0_REG_EntryHi, EntryHi);
143  EE_SYNCP();
144  __asm__ __volatile__("tlbp\n");
145  EE_SYNCP();
146  index = get_mips_cop_reg(0, COP0_REG_Index);
147 
148  if (index >= 0) {
149  __asm__ __volatile__("tlbr\n");
150  EE_SYNCP();
151  *PageMask = get_mips_cop_reg(0, COP0_REG_PageMask);
152  *EntryLo0 = get_mips_cop_reg(0, COP0_REG_EntryLo0);
153  *EntryLo1 = get_mips_cop_reg(0, COP0_REG_EntryLo1);
154 
155  result = index;
156  } else
157  result = -1;
158 
159  return result;
160 }
161 
162 /* 0x800751a8 */
163 int ExpandScratchPad(unsigned int page)
164 {
165  int result;
166 
167  if (!(page & 0xFFF)) {
168  if (0xFFFFE < page - 1) {
169  int index;
170  unsigned int PageMask, EntryHi, EntryLo0, EntryLo1;
171  if ((index = ProbeTLBEntry(0x70004000, &PageMask, &EntryLo0, &EntryLo1)) >= 0) {
172 #if 0
173  // This condition is always false due to the preceding check on the "page" variable.
174  if (page == 0) {
175  EntryHi = 0xE0010000 + ((index - 1) << 13);
176 
177  set_mips_cop_reg(0, COP0_REG_Wired, get_mips_cop_reg(0, COP0_REG_Wired) + 0xFFFF);
178  set_mips_cop_reg(0, COP0_REG_Index, index);
179  set_mips_cop_reg(0, COP0_REG_PageMask, 0);
180  set_mips_cop_reg(0, COP0_REG_EntryHi, EntryHi);
181  set_mips_cop_reg(0, COP0_REG_EntryLo0, 0);
182  set_mips_cop_reg(0, COP0_REG_EntryLo1, 0);
183  EE_SYNCP();
184  __asm__ __volatile__("tlbwi\n");
185  EE_SYNCP();
186  } else
187 #endif
188  {
189  set_mips_cop_reg(0, COP0_REG_Wired, get_mips_cop_reg(0, COP0_REG_Wired) + 1);
190  }
191  }
192 
193  if (page != 0) {
194  /* 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:
195 
196  0($sp)=0
197  4($sp)=$v0=(page+0x1000&0xFFFFF000)>>6|0x1F
198  8($sp)=$a0=(page&0xFFFFF000)>>6|0x1F */
199 
200  EntryHi = 0x70004000;
201  EntryLo0 = ((page + 0x1000) & 0xFFFFF000) >> 6 | 0x1F;
202  EntryLo1 = (page & 0xFFFFF000) >> 6 | 0x1F;
203 
204  set_mips_cop_reg(0, COP0_REG_Index, index);
205  set_mips_cop_reg(0, COP0_REG_PageMask, 0);
206  set_mips_cop_reg(0, COP0_REG_EntryHi, EntryHi);
207  set_mips_cop_reg(0, COP0_REG_EntryLo0, EntryLo0);
208  set_mips_cop_reg(0, COP0_REG_EntryLo1, EntryLo1);
209  EE_SYNCP();
210  __asm__ __volatile__("tlbwi\n");
211  EE_SYNCP();
212 
213  result = index;
214  } else
215  result = 0;
216  } else
217  result = -1;
218  } else
219  result = -1;
220 
221  return result;
222 }
kernel.h
mipscopaccess.h
COP0_REG_PageMask
@ COP0_REG_PageMask
Definition: mipscopaccess.h:24
__attribute__
typedef __attribute__
Definition: tlbfunc.c:60
SyscallPatchData
Definition: osdsrc.c:16
COP0_REG_EntryHi
@ COP0_REG_EntryHi
Definition: mipscopaccess.h:32
COP0_REG_Index
@ COP0_REG_Index
Definition: mipscopaccess.h:14
ee_cop0_defs.h
COP0_REG_EntryLo1
@ COP0_REG_EntryLo1
Definition: mipscopaccess.h:20
COP0_REG_Wired
@ COP0_REG_Wired
Definition: mipscopaccess.h:26
COP0_REG_EntryLo0
@ COP0_REG_EntryLo0
Definition: mipscopaccess.h:18