OpenCores
URL https://opencores.org/ocsvn/mips32r1/mips32r1/trunk

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Software/] [demos/] [XD5_Threads/] [src/] [os/] [kernel.asm] - Rev 2

Compare with Previous | Blame | View Log

###############################################################################
# TITLE: Thread kernel demo
# AUTHOR: Grant Ayers (ayers@cs.utah.edu)
# DATE: 30 June 2012
# FILENAME: kernel.asm
# PROJECT: University of Utah XUM Single Core
# DESCRIPTION:
#    Switches between 8 simultaneously-running threads.
#    Demonstrates interrupts and llsc atomic operations.
#
###############################################################################


        .text
        .balign 4
        .global kernel
        .ent    kernel
        .set    noreorder
        .set    noat
kernel:
        addiu   $sp, $sp, -1152         # Room for 9*32 registers
        
        # Set the stack pointer ($29) for each of 8 threads
        lui     $t0, 0x0007
        ori     $t0, $t0, 0x4000
        sw      $t0, 1140($sp)
        addiu   $t0, $t0, 0x4000
        sw      $t0, 1012($sp)
        addiu   $t0, $t0, 0x4000
        sw      $t0, 884($sp)
        addiu   $t0, $t0, 0x4000
        sw      $t0, 756($sp)
        addiu   $t0, $t0, 0x4000
        sw      $t0, 628($sp)
        addiu   $t0, $t0, 0x4000
        sw      $t0, 500($sp)
        addiu   $t0, $t0, 0x4000
        sw      $t0, 372($sp)
        addiu   $t0, $t0, 0x4000
        sw      $t0, 244($sp)

        # Set the global pointer ($28) for each of 8 threads
        sw      $gp, 240($sp)
        sw      $gp, 368($sp)
        sw      $gp, 496($sp)
        sw      $gp, 624($sp)
        sw      $gp, 752($sp)
        sw      $gp, 880($sp)
        sw      $gp, 1008($sp)
        sw      $gp, 1136($sp)

        # Set the EPC for each of 8 threads to start at main
        lui     $t0, main
        ori     $t0, $t0, main
        sw      $t0, 128($sp)
        sw      $t0, 256($sp)
        sw      $t0, 384($sp)
        sw      $t0, 512($sp)
        sw      $t0, 640($sp)
        sw      $t0, 768($sp)
        sw      $t0, 896($sp)
        sw      $t0, 1024($sp)

        sw      $zero, 0($sp)           # Current thread stored in 0($sp)
        mfc0    $k0, $12, 0             # Enable timer interrupt
        ori     $k0, $k0, 0x8000
        mtc0    $k0, $12, 0

$wait:
        j       $wait                   # Wait for interrupt to begin schedule
        nop
        .end    kernel




        .global scheduler
        .ent    scheduler
scheduler:
        addu    $k0, $0, $sp            # Recover the kernel stack pointer
        la      $sp, _sp
        addiu   $sp, $sp, -1152
        sw      $25, 4($sp)             # Free four registers for use
        sw      $28, 8($sp)
        sw      $30, 12($sp)
        sw      $31, 16($sp)
        lw      $k1, 0($sp)             # Current TID to k1
        beq     $k1, $zero, $skip_save  # Don't save kernel's registers
        nop     
        jal     save_registers
        nop
$skip_save:
        lw      $t0, 0($sp)             # Increment TID
        addiu   $t0, $t0, 1
        addiu   $t1, $zero, 9           # Move TID back to 1 if it reaches 9
        beq     $t0, $t1, $reset_tid
        nop
$tid_done:
        sw      $t0, 0($sp)
        jal     restore_registers       # Load registers for next thread
        nop
        la      $k1, _sp                # Recover kernel stack pointer again
        addiu   $k1, $k1, -1152
        lw      $k1, 0($k1)             # Load TID to k1 for main function
        mfc0    $26, $9, 0              # Read Count to clear timer interrupt
        eret                            # Run thread
$reset_tid:
        addiu   $t0, $zero, 1
        j       $tid_done
        nop
        .end    scheduler


save_registers:
        # Requires: k0 hold thread stack pointer
        #           k1 holds TID
        #           sp points to kernel stack
        # Destroys:

        # Find offset for register table in kernel space
        addiu   $25, $zero, 128
        mul     $25, $25, $k1
        addu    $25, $25, $sp

        # Store thread stack pointer
        sw      $k0, 116($25)
        addu    $k0, $0, $25

        # Store EPC from CP0
        mfc0    $25, $14, 0
        sw      $25, 0($k0)

        # Store remaining registers
        sw      $1, 4($k0)
        sw      $2, 8($k0)
        sw      $3, 12($k0)
        sw      $4, 16($k0)
        sw      $5, 20($k0)
        sw      $6, 24($k0)
        sw      $7, 28($k0)
        sw      $8, 32($k0)
        sw      $9, 36($k0)
        sw      $10, 40($k0)
        sw      $11, 44($k0)
        sw      $12, 48($k0)
        sw      $13, 52($k0)
        sw      $14, 56($k0)
        sw      $15, 60($k0)
        sw      $16, 64($k0)
        sw      $17, 68($k0)
        sw      $18, 72($k0)
        sw      $19, 76($k0)
        sw      $20, 80($k0)
        sw      $21, 84($k0)
        sw      $22, 88($k0)
        sw      $23, 92($k0)
        sw      $24, 96($k0)
        lw      $25, 4($sp)
        sw      $25, 100($k0)
        lw      $28, 8($sp)
        sw      $28, 112($k0)
        lw      $30, 12($sp)
        sw      $30, 120($k0)
        addu    $k1, $0, $31
        lw      $31, 16($sp)
        sw      $31, 124($k0)
        jr      $k1
        nop


restore_registers:
        # Requires: t0 specifies which thread (1-8)
        #           sp points to kernel stack
        # Destroys: All registers

        # Find offset for register table in kernel space
        addiu   $k1, $zero, 128
        mul     $k0, $t0, $k1
        addu    $k0, $k0, $sp


        # Load EPC to CP0
        lw      $k1, 0($k0)
        mtc0    $k1, $14, 0
        # Load remaining registers
        lw      $1, 4($k0)
        lw      $2, 8($k0)
        lw      $3, 12($k0)
        lw      $4, 16($k0)
        lw      $5, 20($k0)
        lw      $6, 24($k0)
        lw      $7, 28($k0)
        lw      $8, 32($k0)
        lw      $9, 36($k0)
        lw      $10, 40($k0)
        lw      $11, 44($k0)
        lw      $12, 48($k0)
        lw      $13, 52($k0)
        lw      $14, 56($k0)
        lw      $15, 60($k0)
        lw      $16, 64($k0)
        lw      $17, 68($k0)
        lw      $18, 72($k0)
        lw      $19, 76($k0)
        lw      $20, 80($k0)
        lw      $21, 84($k0)
        lw      $22, 88($k0)
        lw      $23, 92($k0)
        lw      $24, 96($k0)
        lw      $25, 100($k0)
        lw      $28, 112($k0)
        lw      $29, 116($k0)
        lw      $30, 120($k0)
        addu    $k1, $0, $31
        lw      $31, 124($k0)
        jr      $k1
        nop

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.