- 931B5FD9AC59730BBCB95E9A9D3DBA41483BBE6B3FC204AD8194397191795BACF3EF76DF5335F8F17B3479A007DE3A808DF640FCA949A7802B183BC25E7FE0C3+ 343FF34A3CBC7CD5D51C465B8B91754C546C841055B6E84DFC8E928262E958534E727DC20EC0900B103F82F57895CBFB372D0789FAE1410B593746F76125187Am/mipsinst/m_instrs.asm(92 . 25)(92 . 6)
201 _m_tlbwr:
202 ; no fields
203 mov ecx, Sr(CP0_Wired) ; ecx := CP0_Wired
204 %ifdef TLBWR_CHEAT ; 'Cheat' behaviour (see knobs.asm for rationale) :
205 mov AUX, ecx ; save this index in AUX, we will use
206 mov edx, TLB_ENTRIES_COUNT - 1 ; index of last entry
207 ; Move all TLB entries after the Wired entries down by one slot:
208 .tlbwr_slide: ; Start by replacing the last entry with the next-to-last:
209 cmp edx, AUX ; time to stop?
210 je .tlbr_slide_done ; ... then stop.
211 mov ecx, edx ; ecx := edx
212 dec ecx ; ecx := ecx - 1 (prev. TLB index)
213 mov eax, TLB_E(ecx) ; eax := current TLB entry
214 mov TLB_E(edx), eax ; move the current into the next
215 mov eax, TLB_PFN_E(ecx) ; eax := current PFN_EVEN entry
216 mov TLB_PFN_E(edx), eax ; move the current into the next
217 mov eax, TLB_PFN_O(ecx) ; eax := current PFN_ODD entry
218 mov TLB_PFN_O(edx), eax ; move the current into the next
219 dec edx ; move back by one
220 jmp .tlbwr_slide ; Continue the slide.
221 .tlbr_slide_done: ; Now we freed up the top-most non-wired slot in TLB table:
222 %else ; 'Traditional' behaviour per the MIPS Standard:
223 mov ebx, TLB_ENTRIES_COUNT ; ebx := #tlbentries
224 sub ebx, ecx ; ebx := #tlbentries - Wired
225 mov edx, 0 ; edx (upper half of dividend) := 0
(118 . 7)(99 . 6)
227 div ebx ; edx:eax / ebx
228 add edx, ecx ; edx (remainder) := edx + wired
229 mov AUX, edx ; make edx the index for tlb write
230 %endif
231 call _write_tlb_entry ; Write the AUX-indexed TLB entry.
232 jmp _end_cycle
233 ;-----------------------------------------------------------------------------
(136 . 38)(116 . 77)
235 align GRAIN, db 0x90
236 _m_tlbp:
237 ; no fields
238 mov Sr(CP0_Index), 0x80000000 ; CP0_Index := 0x80000000
239 ;; Get the active ASID:
240 mov edx, Sr(CP0_EntryHi) ; edx := CP0_EntryHi
241 mov ecx, edx ; ecx := edx
242 and edx, 0xFF ; edx := edx & 0xFF (get current ASID)
243 ;; Get the desired tag:
244 and ecx, 0xFFFFF000 ; ecx := ecx & 0xFFFFF000
245 shr ecx, 13 ; ecx := ecx >> 13 (current Tag)
246 ;; For each slot in table (0 .. 15), attempt lookup
247 xor AUX, AUX ; Start with the 0-th entry in table
248 _m_tlbp_lookup_entry:
249 mov eax, TLB_E(AUX) ; eax := current TLB entry
250 mov ebx, eax ; ebx := eax
251 and ebx, TLB_VPN2_Mask ; get VPN2 of this entry
252 cmp ebx, ecx ; cmp(entry.VPN2, vAddr.tag)
253 jne _m_tlbp_lookup_nope ; if entry.VPN2 != vAddr.tag: no match
254 bt eax, TLB_G ; is entry.G = 1?
255 jc _m_tlbp_lookup_match ; then match.
256 shr eax, TLB_ASID_Shift ; eax := eax >> TLB_ASID_Shift
257 and eax, TLB_ASID_Mask ; eax := entry.ASID
258 cmp eax, edx ; entry.ASID = current ASID ?
259 jne _m_tlbp_lookup_nope ; if neither G=1 nor ASID match.
260 ;; otherwise:
261 _m_tlbp_lookup_match: ; TLB Match:
262 mov Sr(CP0_Index), AUX ; Save the index
263 jmp _end_cycle ; Fin.
264 _m_tlbp_lookup_nope: ; try next one in the table, if any
265 inc AUX ; index := index + 1
266 cmp AUX, TLB_ENTRIES_COUNT ; see if still in range 0 .. n-1
267 jb _m_tlbp_lookup_entry ; if in range, go to next entry
268 ;; if we found nothing, we end up with CP0_Index = 0x80000000
269 jmp _end_cycle ; Fin.
270 mov AUX, Sr(CP0_EntryHi) ; AUX := CP0_EntryHi
271 ;; ecx := desired Tag:
272 mov edx, AUX ; edx := CP0_EntryHi
273 and edx, 0xFFFFF000 ; edx := edx & 0xFFFFF000
274 shr edx, 13 ; edx := edx >> 13 (wanted Tag)
275 ; Search for Byte 0 of Tag:
276 mov eax, edx ; eax := edx (wanted Tag)
277 and eax, 0xFF ; Byte 0 (lowest) of wanted Tag
278 ; Fill T0 with 16 copies of Tag Byte 0:
279 movd XMM_T0, eax
280 punpcklbw XMM_T0, XMM_T0
281 punpcklwd XMM_T0, XMM_T0
282 pshufd XMM_T0, XMM_T0, 0
283 ; Now SIMD-compare:
284 pcmpeqb XMM_T0, TLB_TAG_BYTE_0
285 ; Get the result mask of the compare:
286 pmovmskb ecx, XMM_T0 ; i-th bit in ecx = 1 where match B0
287 test ecx, ecx ; if Byte 0 of Tag not found:
288 jz ._m_tlbp_lookup_nope ; ... then go straight to 'not found'
289 ; Search for Byte 1 of Tag:
290 mov eax, edx ; eax := edx (wanted Tag)
291 shr eax, 8 ; Byte 1 (middle) of wanted Tag
292 and eax, 0xFF
293 ; Fill T0 with 16 copies of Tag Byte 1:
294 movd XMM_T0, eax
295 punpcklbw XMM_T0, XMM_T0
296 punpcklwd XMM_T0, XMM_T0
297 pshufd XMM_T0, XMM_T0, 0
298 ; Now SIMD-compare:
299 pcmpeqb XMM_T0, TLB_TAG_BYTE_1
300 ; Get the result mask of the compare:
301 pmovmskb eax, XMM_T0 ; i-th bit in ecx = 1 where match B1
302 and ecx, eax ; Keep only where B0 also matched
303 test ecx, ecx ; if Bytes 0+1 of Tag not found:
304 jz ._m_tlbp_lookup_nope ; ... then go straight to 'not found'
305 ; Search for Byte 2 of Tag:
306 mov eax, edx ; eax := edx (wanted Tag)
307 shr eax, 16 ; Byte 2 (top) of wanted Tag
308 and eax, 0xFF
309 ; Fill T0 with 16 copies of Tag Byte 2:
310 movd XMM_T0, eax
311 punpcklbw XMM_T0, XMM_T0
312 punpcklwd XMM_T0, XMM_T0
313 pshufd XMM_T0, XMM_T0, 0
314 ; Now SIMD-compare:
315 pcmpeqb XMM_T0, TLB_TAG_BYTE_2
316 ; Get the result mask of the compare:
317 pmovmskb eax, XMM_T0 ; i-th bit in ecx = 1 where match B2
318 and ecx, eax ; Keep only where B0,B1 also matched
319 test ecx, ecx ; if Bytes 0+1+2 of Tag not found:
320 jz ._m_tlbp_lookup_nope ; ... then go straight to 'not found'
321 ; If we're here, Tag WAS found; so get the TLB index where it lies :
322 bsf ebx, ecx ; ebx := index of found TLB entry
323 mov edx, ebx ; edx := ebx
324 add edx, 16 ; G's start at bit 16 of Flag_Reg
325 bt Flag_Reg, edx ; See whether i-th G bit is set
326 jc ._m_tlbp_lookup_found ; Now if G is set, we've found it!
327 ; Otherwise, index of found Tag is still in bl (0 .. 0xF)
328 ; G was not set, so get the requested ASID and test whether it matches:
329 mov eax, AUX ; eax := CP0_EntryHi (al : our ASID)
330 lea rdx, [TLB_ASID_COPY]; Load address of ASID Copy
331 cmp byte [rdx + rbx], al ; Compare stored ASID to current
332 jne ._m_tlbp_lookup_nope ; ... if not equal, 'not found'
333 ; If we're here, we FOUND a matching TLB entry:
334 ._m_tlbp_lookup_found:
335 mov Sr(CP0_Index), ebx ; Save the index of the found entry.
336 jmp _end_cycle ; Fin!
337 ._m_tlbp_lookup_nope: ; not found:
338 mov Sr(CP0_Index), 0x80000000 ; CP0_Index := 0x80000000
339 ; if we found nothing, we end up with CP0_Index = 0x80000000
340 jmp _end_cycle ; Fin.
341 ;-----------------------------------------------------------------------------
342
343 ;-----------------------------------------------------------------------------
(279 . 7)(298 . 7)
345 _mfc0_r11: ; 0x0b
346 test ecx, ecx ; Sel != 0 ?
347 jnz _mfc0_unknown ; ... then unknown; else:
348 mov TMP, CP0_Compare ; return CP0_Compare ('fast reg')
349 mov TMP, Sr(CP0_Compare) ; return CP0_Compare ('fast reg')
350 jmp _mfc0_writeback ; Done
351 ;-----------------------------------------------------------------------------
352 _mfc0_r12: ; 0x0c
(478 . 7)(497 . 7)
354 test ecx, ecx ; Sel != 0 ?
355 jnz _mtc0_unknown ; ... then unknown; else:
356 ClrIRQ TIMER_IRQ ; Clear MIPS Timer IRQ
357 mov CP0_Compare, ebx ; CP0_Compare := T ('fast reg')
358 mov Sr(CP0_Compare), ebx ; CP0_Compare := T ('fast reg')
359 jmp _end_cycle ; Done
360 ;-----------------------------------------------------------------------------
361 _mtc0_r12: ; 0x0c