Table of Contents

TLB Assemble Example 1

Reference: {{:mywiki:hw:mips:mips_tlb.pdf|}}

tlb1.asm
1 /*      $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $        */
    2 /*-
    3  * Copyright (c) 1992, 1993
    4  *      The Regents of the University of California.  All rights reserved.
    5  *
    6  * This code is derived from software contributed to Berkeley by
    7  * Digital Equipment Corporation and Ralph Campbell.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  * Copyright (C) 1989 Digital Equipment Corporation.
   34  * Permission to use, copy, modify, and distribute this software and
   35  * its documentation for any purpose and without fee is hereby granted,
   36  * provided that the above copyright notice appears in all copies.
   37  * Digital Equipment Corporation makes no representations about the
   38  * suitability of this software for any purpose.  It is provided "as is"
   39  * without express or implied warranty.
   40  *
   41  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
   42  *      v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
   43  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
   44  *      v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
   45  * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
   46  *      v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
   47  *
   48  *      from: @(#)locore.s      8.5 (Berkeley) 1/4/94
   49  *      JNPR: tlb.S,v 1.1.4.2 2007/09/10 09:02:05 girish
   50  * $FreeBSD: releng/8.1/sys/mips/mips/tlb.S 178172 2008-04-13 07:27:37Z imp $
   51  */
   52 
   53 /*
   54  *      Contains code that is the first executed at boot time plus
   55  *      assembly language support routines.
   56  */
   57 
   58 #include "opt_cputype.h"
   59 
   60 #include <machine/asm.h>
   61 #include <machine/cpu.h>
   62 #include <machine/cpuregs.h>
   63 #include <machine/regnum.h>
   64 #include <machine/pte.h>
   65 
   66 #include "assym.s"
   67 
   68 #if defined(ISA_MIPS32)
   69 #undef WITH_64BIT_CP0
   70 #elif defined(ISA_MIPS64)
   71 #define WITH_64BIT_CP0
   72 #elif defined(ISA_MIPS3)
   73 #define WITH_64BIT_CP0
   74 #else
   75 #error "Please write the code for this ISA"
   76 #endif
   77 
   78 #ifdef WITH_64BIT_CP0
   79 #define _SLL    dsll
   80 #define _SRL    dsrl
   81 #define _MFC0   dmfc0
   82 #define _MTC0   dmtc0
   83 #define WIRED_SHIFT 34
   84 #define PAGE_SHIFT 34
   85 #else
   86 #define _SLL    sll
   87 #define _SRL    srl
   88 #define _MFC0   mfc0
   89 #define _MTC0   mtc0
   90 #define WIRED_SHIFT 2
   91 #define PAGE_SHIFT 2
   92 #endif
   93         .set    noreorder                       # Noreorder is default style!
   94 #if defined(ISA_MIPS32)
   95         .set    mips32
   96 #elif defined(ISA_MIPS64)
   97         .set    mips64
   98 #elif defined(ISA_MIPS3)
   99         .set    mips3
  100 #endif
  101 
  102 #define ITLBNOPFIX      nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
  103 
  104 /*
  105  * FREEBSD_DEVELOPERS_FIXME
  106  * Some MIPS CPU may need delays using nops between executing CP0 Instructions
  107  */
  108 #define MIPS_CPU_NOP_DELAY      nop;nop;nop;nop;
  109 
  110 /*--------------------------------------------------------------------------
  111  *
  112  * Mips_TLBWriteIndexed(unsigned index, tlb *tlb);
  113  *
  114  *      Write the given entry into the TLB at the given index.
  115  *
  116  * Results:
  117  *      None.
  118  *
  119  * Side effects:
  120  *      TLB entry set.
  121  *
  122  *--------------------------------------------------------------------------
  123  */
  124 LEAF(Mips_TLBWriteIndexed)
  125         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
  126         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
  127         ITLBNOPFIX
  128         lw      a2, 8(a1)
  129         lw      a3, 12(a1)
  130         _MFC0   t0, COP_0_TLB_HI                # Save the current PID.
  131 
  132         _MTC0   a2, COP_0_TLB_LO0               # Set up entry low0.
  133         _MTC0   a3, COP_0_TLB_LO1               # Set up entry low1.
  134         lw      a2, 0(a1)
  135         lw      a3, 4(a1)
  136         mtc0    a0, COP_0_TLB_INDEX             # Set the index.
  137         _MTC0   a2, COP_0_TLB_PG_MASK           # Set up entry mask.
  138         _MTC0   a3, COP_0_TLB_HI                # Set up entry high.
  139         MIPS_CPU_NOP_DELAY
  140         tlbwi                                   # Write the TLB
  141         MIPS_CPU_NOP_DELAY
  142 
  143         _MTC0   t0, COP_0_TLB_HI                # Restore the PID.
  144         nop
  145         _MTC0   zero, COP_0_TLB_PG_MASK         # Default mask value.
  146         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
  147         ITLBNOPFIX
  148         j       ra
  149         nop
  150 END(Mips_TLBWriteIndexed)
  151 
  152 /*--------------------------------------------------------------------------
  153  *
  154  * Mips_SetPID(int pid);
  155  *
  156  *      Write the given pid into the TLB pid reg.
  157  *
  158  * Results:
  159  *      None.
  160  *
  161  * Side effects:
  162  *      PID set in the entry hi register.
  163  *
  164  *--------------------------------------------------------------------------
  165  */
  166 LEAF(Mips_SetPID)
  167         _MTC0   a0, COP_0_TLB_HI                # Write the hi reg value
  168         nop                                     # required for QED5230
  169         nop                                     # required for QED5230
  170         j       ra
  171         nop
  172 END(Mips_SetPID)
  173 
  174 /*--------------------------------------------------------------------------
  175  *
  176  * Mips_SetWIRED(int wired);
  177  *
  178  *      Write the given value into the TLB wired reg.
  179  *
  180  * Results:
  181  *      None.
  182  *
  183  * Side effects:
  184  *      WIRED set in the wired register.
  185  *
  186  *--------------------------------------------------------------------------
  187  */
  188 LEAF(Mips_SetWIRED)
  189         mtc0    a0, COP_0_TLB_WIRED
  190         j       ra
  191         nop
  192 END(Mips_SetWIRED)
  193 
  194 /*--------------------------------------------------------------------------
  195  *
  196  * Mips_GetWIRED(void);
  197  *
  198  *      Get the value from the TLB wired reg.
  199  *
  200  * Results:
  201  *      Value of wired reg.
  202  *
  203  * Side effects:
  204  *      None.
  205  *
  206  *--------------------------------------------------------------------------
  207  */
  208 LEAF(Mips_GetWIRED)
  209         mfc0    v0, COP_0_TLB_WIRED
  210         j       ra
  211         nop
  212 END(Mips_GetWIRED)
  213 
  214 /*--------------------------------------------------------------------------
  215  *
  216  * Mips_TLBFlush(tlbsize);
  217  *
  218  *      Flush the "random" entries from the TLB.
  219  *      Uses "wired" register to determine what register to start with.
  220  *      Arg "tlbsize" is the number of entries to flush.
  221  *
  222  * Results:
  223  *      None.
  224  *
  225  * Side effects:
  226  *      The TLB is flushed.
  227  *
  228  *--------------------------------------------------------------------------
  229  */
  230 LEAF(Mips_TLBFlush)
  231         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
  232         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
  233         ITLBNOPFIX
  234         mfc0    t1, COP_0_TLB_WIRED
  235         li      v0, MIPS_KSEG3_START + 0x0fff0000 # invalid address
  236         _MFC0   t0, COP_0_TLB_HI                # Save the PID
  237 
  238         _MTC0   v0, COP_0_TLB_HI                # Mark entry high as invalid
  239         _MTC0   zero, COP_0_TLB_LO0             # Zero out low entry0.
  240         _MTC0   zero, COP_0_TLB_LO1             # Zero out low entry1.
  241         mtc0    zero, COP_0_TLB_PG_MASK         # Zero out mask entry.
  242 /*
  243  * Align the starting value (t1) and the upper bound (a0).
  244  */
  245 1:
  246         mtc0    t1, COP_0_TLB_INDEX             # Set the index register.
  247         ITLBNOPFIX
  248         _MTC0   t0, COP_0_TLB_HI                # Restore the PID
  249         addu    t1, t1, 1                       # Increment index.
  250         addu    t0, t0, 8 * 1024
  251         MIPS_CPU_NOP_DELAY
  252         tlbwi                                   # Write the TLB entry.
  253         MIPS_CPU_NOP_DELAY
  254         bne     t1, a0, 1b
  255         nop
  256 
  257         _MTC0   t0, COP_0_TLB_HI                # Restore the PID
  258         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
  259         ITLBNOPFIX
  260         j       ra
  261         nop
  262 END(Mips_TLBFlush)
  263 
  264 
  265 /*--------------------------------------------------------------------------
  266  *
  267  * Mips_TLBFlushAddr(unsigned TLBhi);
  268  *
  269  *      Flush any TLB entries for the given address and TLB PID.
  270  *
  271  * Results:
  272  *      None.
  273  *
  274  * Side effects:
  275  *      The process's page is flushed from the TLB.
  276  *
  277  *--------------------------------------------------------------------------
  278  */
  279 LEAF(Mips_TLBFlushAddr)
  280         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
  281         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
  282         ITLBNOPFIX
  283         li      v0, (PTE_HVPN | PTE_ASID)
  284         and     a0, a0, v0                      # Make shure valid hi value.
  285         _MFC0   t0, COP_0_TLB_HI                # Get current PID
  286         mfc0    t3, COP_0_TLB_PG_MASK           # Save current pgMask
  287         _MTC0   a0, COP_0_TLB_HI                # look for addr & PID
  288         MIPS_CPU_NOP_DELAY
  289         tlbp                                    # Probe for the entry.
  290         MIPS_CPU_NOP_DELAY
  291         mfc0    v0, COP_0_TLB_INDEX             # See what we got
  292         li      t1, MIPS_KSEG0_START + 0x0fff0000
  293         bltz    v0, 1f                          # index < 0 => !found
  294         nop
  295         # Load invalid entry, each TLB entry should have it's own bogus 
  296         # address calculated by following expression:
  297         # MIPS_KSEG0_START + 0x0fff0000 + 2 * i * PAGE_SIZE;
  298         # One bogus value for every TLB entry might cause MCHECK exception
  299         sll     v0, PAGE_SHIFT + 1
  300         addu    t1, v0
  301         _MTC0   t1, COP_0_TLB_HI                # Mark entry high as invalid
  302 
  303         _MTC0   zero, COP_0_TLB_LO0             # Zero out low entry.
  304         _MTC0   zero, COP_0_TLB_LO1             # Zero out low entry.
  305         MIPS_CPU_NOP_DELAY
  306         tlbwi
  307         MIPS_CPU_NOP_DELAY
  308 1:
  309         _MTC0   t0, COP_0_TLB_HI                # restore PID
  310         mtc0    t3, COP_0_TLB_PG_MASK           # Restore pgMask
  311         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
  312         ITLBNOPFIX
  313         j       ra
  314         nop
  315 END(Mips_TLBFlushAddr)
  316 
  317 /*--------------------------------------------------------------------------
  318  *
  319  * Mips_TLBUpdate(unsigned virpageadr, lowregx);
  320  *
  321  *      Update the TLB if highreg is found; otherwise, enter the data.
  322  *
  323  * Results:
  324  *      < 0 if loaded >= 0 if updated.
  325  *
  326  * Side effects:
  327  *      None.
  328  *
  329  *--------------------------------------------------------------------------
  330  */
  331 LEAF(Mips_TLBUpdate)
  332         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
  333         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
  334         ITLBNOPFIX
  335         and     t1, a0, 0x1000                  # t1 = Even/Odd flag
  336         li      v0, (PTE_HVPN | PTE_ASID)
  337         and     a0, a0, v0
  338         _MFC0   t0, COP_0_TLB_HI                # Save current PID
  339         _MTC0   a0, COP_0_TLB_HI                # Init high reg
  340         and     a2, a1, PTE_G                   # Copy global bit
  341         MIPS_CPU_NOP_DELAY
  342         tlbp                                    # Probe for the entry.
  343         _SLL    a1, a1, WIRED_SHIFT
  344         _SRL    a1, a1, WIRED_SHIFT
  345         nop
  346         mfc0    v0, COP_0_TLB_INDEX             # See what we got
  347         bne     t1, zero, 2f                    # Decide even odd
  348 # EVEN
  349         nop
  350         bltz    v0, 1f                          # index < 0 => !found
  351         MIPS_CPU_NOP_DELAY
  352 
  353         tlbr                                    # update, read entry first
  354         MIPS_CPU_NOP_DELAY
  355         _MTC0   a1, COP_0_TLB_LO0               # init low reg0.
  356         MIPS_CPU_NOP_DELAY
  357         tlbwi                                   # update slot found
  358         b       4f
  359         nop
  360 1:
  361         mtc0    zero, COP_0_TLB_PG_MASK         # init mask.
  362         _MTC0   a0, COP_0_TLB_HI                # init high reg.
  363         _MTC0   a1, COP_0_TLB_LO0               # init low reg0.
  364         _MTC0   a2, COP_0_TLB_LO1               # init low reg1.
  365         MIPS_CPU_NOP_DELAY
  366         tlbwr                                   # enter into a random slot
  367         MIPS_CPU_NOP_DELAY
  368         b       4f
  369         nop
  370 # ODD
  371 2:
  372         nop
  373         bltz    v0, 3f                          # index < 0 => !found
  374         MIPS_CPU_NOP_DELAY
  375 
  376         tlbr                                    # read the entry first
  377         MIPS_CPU_NOP_DELAY
  378         _MTC0   a1, COP_0_TLB_LO1               # init low reg1.
  379         MIPS_CPU_NOP_DELAY
  380         tlbwi                                   # update slot found
  381         MIPS_CPU_NOP_DELAY
  382         b       4f
  383         nop
  384 3:
  385         mtc0    zero, COP_0_TLB_PG_MASK         # init mask.
  386         _MTC0   a0, COP_0_TLB_HI                # init high reg.
  387         _MTC0   a2, COP_0_TLB_LO0               # init low reg0.
  388         _MTC0   a1, COP_0_TLB_LO1               # init low reg1.
  389         MIPS_CPU_NOP_DELAY
  390         tlbwr                                   # enter into a random slot
  391 
  392 4:                                              # Make shure pipeline
  393         MIPS_CPU_NOP_DELAY
  394         _MTC0   t0, COP_0_TLB_HI                # restore PID
  395         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
  396         ITLBNOPFIX
  397         j       ra
  398         nop
  399 END(Mips_TLBUpdate)
  400 
  401 /*--------------------------------------------------------------------------
  402  *
  403  * Mips_TLBRead(unsigned entry, struct tlb *tlb);
  404  *
  405  *      Read the TLB entry.
  406  *
  407  * Results:
  408  *      None.
  409  *
  410  * Side effects:
  411  *      tlb will contain the TLB entry found.
  412  *
  413  *--------------------------------------------------------------------------
  414  */
  415 LEAF(Mips_TLBRead)
  416         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
  417         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
  418         ITLBNOPFIX
  419         _MFC0   t0, COP_0_TLB_HI                # Get current PID
  420 
  421         mtc0    a0, COP_0_TLB_INDEX             # Set the index register
  422         MIPS_CPU_NOP_DELAY
  423         tlbr                                    # Read from the TLB
  424         MIPS_CPU_NOP_DELAY
  425         mfc0    t2, COP_0_TLB_PG_MASK           # fetch the hi entry
  426         _MFC0   t3, COP_0_TLB_HI                # fetch the hi entry
  427         _MFC0   t4, COP_0_TLB_LO0               # See what we got
  428         _MFC0   t5, COP_0_TLB_LO1               # See what we got
  429         _MTC0   t0, COP_0_TLB_HI                # restore PID
  430         MIPS_CPU_NOP_DELAY
  431         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
  432         ITLBNOPFIX
  433         sw      t2, 0(a1)
  434         sw      t3, 4(a1)
  435         sw      t4, 8(a1)
  436         j       ra
  437         sw      t5, 12(a1)
  438 END(Mips_TLBRead)
  439 
  440 /*--------------------------------------------------------------------------
  441  *
  442  * Mips_TLBGetPID(void);
  443  *
  444  * Results:
  445  *      Returns the current TLB pid reg.
  446  *
  447  * Side effects:
  448  *      None.
  449  *
  450  *--------------------------------------------------------------------------
  451  */
  452 LEAF(Mips_TLBGetPID)
  453         _MFC0   v0, COP_0_TLB_HI                # get PID
  454         j       ra
  455         and     v0, v0, VMTLB_PID               # mask off PID
  456 END(Mips_TLBGetPID)
  457 
  458 
  459 
  460 /*--------------------------------------------------------------------------
  461  *
  462  * void mips_TBIAP(int sizeofTLB);
  463  *
  464  * Invalidate TLB entries belong to per process user spaces while
  465  * leaving entries for kernel space marked global intact.
  466  *
  467  *--------------------------------------------------------------------------
  468  */
  469 LEAF(mips_TBIAP)
  470         mfc0    v1, COP_0_STATUS_REG            # save status register
  471         mtc0    zero, COP_0_STATUS_REG          # disable interrupts
  472 
  473         _MFC0   t4, COP_0_TLB_HI                # Get current PID
  474         move    t2, a0
  475         mfc0    t1, COP_0_TLB_WIRED
  476         li      v0, MIPS_KSEG0_START + 0x0fff0000       # invalid address
  477         mfc0    t3, COP_0_TLB_PG_MASK           # save current pgMask
  478 
  479         # do {} while (t1 < t2)
  480 1:
  481         mtc0    t1, COP_0_TLB_INDEX             # set index
  482         MIPS_CPU_NOP_DELAY
  483         tlbr                                    # obtain an entry
  484         MIPS_CPU_NOP_DELAY
  485         _MFC0   a0, COP_0_TLB_LO1
  486         and     a0, a0, PTE_G                   # check to see it has G bit
  487         bnez    a0, 2f
  488         nop
  489 
  490         _MTC0   v0, COP_0_TLB_HI                # make entryHi invalid
  491         _MTC0   zero, COP_0_TLB_LO0             # zero out entryLo0
  492         _MTC0   zero, COP_0_TLB_LO1             # zero out entryLo1
  493         mtc0    zero, COP_0_TLB_PG_MASK         # zero out mask entry
  494         MIPS_CPU_NOP_DELAY
  495         tlbwi                                   # invalidate the TLB entry
  496 2:
  497         addu    t1, t1, 1
  498         addu    v0, 1 << (PAGE_SHIFT + 1)
  499         bne     t1, t2, 1b
  500         nop
  501 
  502         _MTC0   t4, COP_0_TLB_HI                # restore PID
  503         mtc0    t3, COP_0_TLB_PG_MASK           # restore pgMask
  504         MIPS_CPU_NOP_DELAY
  505         mtc0    v1, COP_0_STATUS_REG            # restore status register
  506         j       ra                              # new ASID will be set soon
  507         nop
  508         .set    mips2
  509 END(mips_TBIAP)

TLB example 2

tlb2.asm
/*
 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
 *	The President and Fellows of Harvard College.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
 
#include <kern/mips/regdefs.h>
#include <mips/specialreg.h>
 
/*
 * TLB handling for mips-1 (r2000/r3000)
 */
 
   .text
   .set noreorder
 
   /*
    * tlb_random: use the "tlbwr" instruction to write a TLB entry
    * into a (very pseudo-) random slot in the TLB.
    *
    * Pipeline hazard: must wait between setting entryhi/lo and
    * doing the tlbwr. Use two cycles; some processors may vary.
    */
   .globl tlb_random
   .type tlb_random,@function
   .ent tlb_random
tlb_random:
   mtc0 a0, c0_entryhi	/* store the passed entry into the */
   mtc0 a1, c0_entrylo	/*   tlb entry registers */
   nop			/* wait for pipeline hazard */
   nop
   tlbwr		/* do it */
   j ra
   nop
   .end tlb_random
 
   /*
    * tlb_write: use the "tlbwi" instruction to write a TLB entry
    * into a selected slot in the TLB.
    *
    * Pipeline hazard: must wait between setting entryhi/lo and
    * doing the tlbwi. Use two cycles; some processors may vary.
    */
   .text   
   .globl tlb_write
   .type tlb_write,@function
   .ent tlb_write
tlb_write:
   mtc0 a0, c0_entryhi	/* store the passed entry into the */
   mtc0 a1, c0_entrylo	/*   tlb entry registers */
   sll  t0, a2, CIN_INDEXSHIFT  /* shift the passed index into place */
   mtc0 t0, c0_index	/* store the shifted index into the index register */
   nop			/* wait for pipeline hazard */
   nop
   tlbwi		/* do it */
   j ra
   nop
   .end tlb_write
 
   /*
    * tlb_read: use the "tlbr" instruction to read a TLB entry
    * from a selected slot in the TLB.
    *
    * Pipeline hazard: must wait between setting c0_index and
    * doing the tlbr. Use two cycles; some processors may vary.
    * Similarly, three more cycles before reading c0_entryhi/lo.
    */
   .text
   .globl tlb_read
   .type tlb_read,@function
   .ent tlb_read
tlb_read:
   sll  t0, a2, CIN_INDEXSHIFT  /* shift the passed index into place */
   mtc0 t0, c0_index	/* store the shifted index into the index register */
   nop			/* wait for pipeline hazard */
   nop
   tlbr			/* do it */
   nop			/* wait for pipeline hazard */
   nop
   nop
   mfc0 t0, c0_entryhi	/* get the tlb entry out of the */
   mfc0 t1, c0_entrylo	/*   tlb entry registers */
   sw t0, 0(a0)		/* store through the passed pointer */
   j ra
   sw t1, 0(a1)		/* store (in delay slot) */
   .end tlb_read
 
   /*
    * tlb_probe: use the "tlbp" instruction to find the index in the
    * TLB of a TLB entry matching the relevant parts of the one supplied.
    *
    * Pipeline hazard: must wait between setting c0_entryhi/lo and
    * doing the tlbp. Use two cycles; some processors may vary.
    * Similarly, two more cycles before reading c0_index.
    */
   .text
   .globl tlb_probe
   .type tlb_probe,@function
   .ent tlb_probe
tlb_probe:
   mtc0 a0, c0_entryhi	/* store the passed entry into the */
   mtc0 a1, c0_entrylo	/*   tlb entry registers */
   nop			/* wait for pipeline hazard */
   nop
   tlbp			/* do it */
   nop			/* wait for pipeline hazard */
   nop
   mfc0 t0, c0_index	/* fetch the index back in t0 */
 
   /*
    * If the high bit (CIN_P) of c0_index is set, the probe failed.
    * The high bit is not set <--> c0_index (now in t0) >= 0.
    */
 
   bgez t0, 1f		/* did probe succeed? if so, skip forward */
   nop			/* delay slot */
   addi v0, z0, -1	/* set return value to -1 to indicate failure */
   j ra			/* done */
   nop			/* delay slot */
 
1:
   /* succeeded - get the index field from the index register value */
   andi t1, t0, CIN_INDEX       /* mask off the field */
   j ra				/* done */
   sra  v0, t1, CIN_INDEXSHIFT  /* shift it (in delay slot) */
   .end tlb_probe
 
 
   /*
    * tlb_reset
    *
    * Initialize the TLB. At processor startup, the TLB state is completely
    * undefined. So be sure to avoid creating any duplicates. Also make sure
    * that the initialization entries don't duplicate the INVALID entries
    * defined in tlb.h. (This way you can write the invalid entries in
    * without having to use tlbp to find out if they're going to cause dups.)
    *
    * This function is not defined in tlb.h because it's only called from
    * start.S.
    *
    * Pipeline hazards are as above.
    */
   .text
   .globl tlb_reset
   .type tlb_reset,@function
   .ent tlb_reset
tlb_reset:
   li t0, 0			/* t0 <- tlb index number (shifted) */
   li t1, 0x81000000		/* t1 <- tlb reset vaddr */
1:
   mtc0 $0, c0_entrylo 		/* set up proposed tlb entry for reset */
   mtc0 t1, c0_entryhi
   nop				/* wait for pipeline hazard */
   nop
   tlbp				/* check if it already exists */
   nop				/* wait for pipeline hazard */
   nop
   mfc0 t2, c0_index
   bgez t2, 1b			/* if it does, loop back */
   addiu t1, t1, 0x1000		/* next vaddr (in delay slot) */
   mtc0 t0, c0_index		/* doesn't exist, set index to write to */
   /* nop */			/* don't wait for pipeline hazard */
   /* nop */			/*   (have enough other instructions) */
   addiu t0, t0, 0x100		/* next tlb index (shifted) */
   bne t0, 0x4000, 1b		/* if it's not the last tlb index, loop */
   tlbwi			/* write tlb entry (in delay slot) */
   j ra				/* done */
   nop				/* delay slot */	
   .end tlb_reset

Shao Guohua TLB ASM test

tlb.asm
##probe failure
#define TLB_INDEX_P_OFFSET 31
#define TLB_INDEX_P_MAKS 0x80000000
 
#define TLB_INDEX_INDEX_OFFSET 0
#define TLB_INDEX_INDEX_MASK 0x3F
 
 
#define TLB_ENTRYLO_R_OFFSET 30
#define TLB_ENTRYLO_R_MASK   0xC0000000
 
#define TLB_ENTRYLO_PFN_OFFSET 6
#define TLB_ENTRYLO_PFN_MASK   0x3FFFFC0
 
##cache coherency
##3 WB Cacheable, noncoherent, write-back, write allocate
##4 CWBE Cacheable, write-back, write-allocate, coherent, read misses request Exclusive
##5 CWB Cacheable, write-back, write-allocate, coherent, read misses request Shared 
##6 - Reserved
##7 UCA Uncached Accelerated
##
#define TLB_ENTRYLO_C_OFFSET 3
#define TLB_ENTRYLO_C_MASK   0x38
 
##dirt or writable
#define TLB_ENTRYLO_D_OFFSET 2
#define TLB_ENTRYLO_D_MASK   0x4
##valid bit
#define TLB_ENTRYLO_V_OFFSET 1
#define TLB_ENTRYLO_V_MASK   0x2
 
##global
#define TLB_ENTRYLO_G_OFFSET 0
#define TLB_ENTRYLO_G_MASK   0x1
 
#define TLB_ENTRYHI_VPN2_OFFSET  13
#define TLB_ENTRYHI_VPN2_MASK    0xFFFFE000
#define TLB_ENTRYHI_EHINV_OFFSET 10
#define TLB_ENTRYHI_EHINV_MASK   0x400
#define TLB_ENTRYHI_ASID_OFFSET  0
#define TLB_ENTRYHI_ASI_MASK     0xFF
 
 
##entry_lo0.reg.field.d = 1;
##entry_lo0.reg.field.v = 1;
##entry_lo0.reg.field.g = 1;
##entry_lo0.reg.field.c = 5;
##entry_lo1.reg.field.d = 1;
##entry_lo1.reg.field.v = 1;
##entry_lo1.reg.field.g = 1;
##entry_lo1.reg.field.c = 5;
##entry_hi.reg.field.asid = 0x1f;
##pagemask = 0x0;
##
##entry_hi.reg.field.vpn2 = (v_addr + (0x2000 * i)) >> 13;        
##entry_lo0.reg.field.pfn = (phy_addr +(0x2000 * i)) >> 12;
##entry_lo1.reg.field.pfn = (phy_addr +(0x2000 * i)+0x1000) >> 12;
 
##tlb->tlb[i].pagemask = pagemask;
##tlb->tlb[i].entryhi = entry_hi.reg.all;
##tlb->tlb[i].entrylo0 = entry_lo0.reg.all;
##if ((i == (pages -1)) && !last_odd_page_vld ) ##last odd page not valid
##{
##   tlb->tlb[i].entrylo1 = 0;
##   entry_lo1.reg.field.v = 0;
##}    
##else
##   tlb->tlb[i].entrylo1 = entry_lo1.reg.all;  
 
.data  
    str_index:	 .asciiz "index: "
	str_entryhi:	 .asciiz "enryhi: "
	str_entrylo0: .asciiz "enrylo0: "
	str_entrylo1: .asciiz "enrylo1: "
	str_pagemask: .asciiz "pagemask: "
	str_newline:  .asciiz "\n"
	str_size:  .asciiz "size:"
 
 
#define MAP_TLB_BASE    0xC0000000
#define TLB_4K_PAGE_OFFSET 12 
#define ENTRYHI_DEFAULT 0x0
#define TLB_ENTRYLO_DEFAULT_G ( (5<< TLB_ENTRYLO_C_OFFSET) | (1<< TLB_ENTRYLO_D_OFFSET) | (1<< TLB_ENTRYLO_V_OFFSET) | (1<< TLB_ENTRYLO_G_OFFSET))
#define TLB_ENTRYLO_DEFAULT_P ( (5<< TLB_ENTRYLO_C_OFFSET) | (1<< TLB_ENTRYLO_D_OFFSET) | (1<< TLB_ENTRYLO_V_OFFSET) )
 
 
.text
	.globl __start    # declaration of main as a global variable
 
__start:	
	li $t6, 0x20060000
	li $t0, 154333
 
_set_tlb_global:		
    #EntryHi:
	#---------------------------------
	#| 31        13| 12   8 | 7    0 |
	#|    VPN2     |  0   0 |  ASID  |
	#---------------------------------
	#Entrylo0/1
	#---------------------------------
	#| 31        6| 5  3 | 2 | 1 | 0 |
	#| PFN        |  C   | D | V | G |
	#---------------------------------
	#Mask
	#---------------------------------
	#| 31  29| 28      13| 12     0 |
	#| 0    0|    Mask   | 0      0 |
	#---------------------------------
	#t0 -- MPE shared code/data size need to map 
	#t1 -- Index
	#t2-- entryhi
	#t3 -- entrylo
	#t4 -- asid
	#t5 -- pagemask
	#t6 -- physical address, virtual address is harded coded here, ie, 0xc000 0000
	#V0 -- tmp register
 
	#prepare $t1 for Index
	li $t1, 0
 
	#prepare $t2 for entryhi	
	li $t2, 0xC0000000    
 
	#prepare $t3 for entrylo
	add $t3, $t6, 0     #PHYsical base
	srl $t3, $t3, 12    #TLB_4K_PAGE_OFFSET
	sll $t3, $t3, 6     #TLB_ENTRYLO_PFN_OFFSET
	addi $t3, $t3, 0x2f #TLB_ENTRYLO_DEFAULT_G
 
	#$t4 for asid
	li $t4, 0
 
	#$t5 for pagemask
	li $t5, 0
 
tlb_g_loop:		
	ble $t0, 0, _set_tlb_global_done
	nop
 
	#print size
		li	$v0, 4
		la	$a0, str_size
		syscall	
		li	$v0, 1
		addi $a0, $t0, 0
		syscall
		li	$v0, 4
		la	$a0, str_newline
		syscall
 
	#write even index
		li	$v0, 4
		la	$a0, str_index
		syscall	
		li	$v0, 1
		addi $a0, $t1, 0
		syscall
		li	$v0, 4
		la	$a0, str_newline
		syscall
 
	#write even entryhi
		li	$v0, 4
		la	$a0, str_entryhi
		syscall	
		li	$v0, 1
		addi $a0, $t2, 0
		syscall
		li	$v0, 4
		la	$a0, str_newline
		syscall
 
	#write even entrylo0	
		li	$v0, 4
		la	$a0, str_entrylo0
		syscall	
		li	$v0, 1
		addi $a0, $t3, 0
		syscall
		li	$v0, 4
		la	$a0, str_newline
		syscall
	#write even pagemask
		li	$v0, 4
		la	$a0, str_pagemask
		syscall	
		li	$v0, 1
		addi $a0, $t5, 0
		syscall
		li	$v0, 4
		la	$a0, str_newline
		syscall
	#wlbwt
 
	#update odd page
	addi $t3, $t3, 0x40
	#write entrylo1	
		li	$v0, 4
		la	$a0, str_entrylo1
		syscall	
		li	$v0, 1
		addi $a0, $t3, 0
		syscall
		li	$v0, 4
		la	$a0, str_newline
		syscall
	#wlbwt
 
	#prepare next tlb index--
	#update size $t0 reduce 2 * 4K since one tlb support 2 pages
	li $v0, 0x2000
	sub $t0, $t0, $v0
 
	#update index $t1
	li $v0, 1
	add $t1, $t1, $v0
 
	#update entryhi $t2
	addi $t2, $t2, 0x2000 #(2<<TLB_ENTRYHI_VPN2_OFFSET)
 
	#update entrylo $t3
	addi $t3, $t3, 0x40
 
	li	$v0, 4
	la	$a0, str_newline
	syscall
 
	j tlb_g_loop
	nop
 
 
_set_tlb_global_done:
	li	$v0, 10	
	syscall