163 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
		
		
			
		
	
	
			163 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * File      : context_gcc.S
							 | 
						||
| 
								 | 
							
								 * This file is part of RT-Thread RTOS
							 | 
						||
| 
								 | 
							
								 * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The license and distribution terms for this file may be
							 | 
						||
| 
								 | 
							
								 * found in the file LICENSE in this distribution or at
							 | 
						||
| 
								 | 
							
								 * http://www.rt-thread.org/license/LICENSE
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Change Logs:
							 | 
						||
| 
								 | 
							
								 * Date           Author       Notes
							 | 
						||
| 
								 | 
							
								 * 2010-05-17     swkyer       first version
							 | 
						||
| 
								 | 
							
								 * 2010-09-11     bernard      port to Loongson SoC3210
							 | 
						||
| 
								 | 
							
								 * 2011-08-08     lgnq         port to Loongson LS1B
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "../common/mips.inc"
							 | 
						||
| 
								 | 
							
								#include "../common/stackframe.h"
							 | 
						||
| 
								 | 
							
								#include "stackframe_fpu.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    .section ".text", "ax"
							 | 
						||
| 
								 | 
							
								    .set noreorder
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * rt_base_t rt_hw_interrupt_disable()
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								    .globl rt_hw_interrupt_disable
							 | 
						||
| 
								 | 
							
								rt_hw_interrupt_disable:
							 | 
						||
| 
								 | 
							
								    mfc0    v0, CP0_STATUS
							 | 
						||
| 
								 | 
							
								    and     v1, v0, 0xfffffffe
							 | 
						||
| 
								 | 
							
								    mtc0    v1, CP0_STATUS
							 | 
						||
| 
								 | 
							
								    jr      ra
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * void rt_hw_interrupt_enable(rt_base_t level)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								    .globl rt_hw_interrupt_enable
							 | 
						||
| 
								 | 
							
								rt_hw_interrupt_enable:
							 | 
						||
| 
								 | 
							
								    ori     a0, 0x00000800   
							 | 
						||
| 
								 | 
							
								    mtc0    a0, CP0_STATUS
							 | 
						||
| 
								 | 
							
								    ehb
							 | 
						||
| 
								 | 
							
								    mfc0    v0, CP0_CAUSE
							 | 
						||
| 
								 | 
							
								    ehb
							 | 
						||
| 
								 | 
							
								    or      v1, v0, 0x800000                 //EBASE + 0x200                                                                                                 
							 | 
						||
| 
								 | 
							
								    mtc0    v1, CP0_CAUSE
							 | 
						||
| 
								 | 
							
								    ehb
							 | 
						||
| 
								 | 
							
								    jr      ra
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)
							 | 
						||
| 
								 | 
							
								 * a0 --> from
							 | 
						||
| 
								 | 
							
								 * a1 --> to
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								    .globl rt_hw_context_switch
							 | 
						||
| 
								 | 
							
								rt_hw_context_switch:
							 | 
						||
| 
								 | 
							
								    mtc0    ra, CP0_EPC
							 | 
						||
| 
								 | 
							
								    SAVE_ALL
							 | 
						||
| 
								 | 
							
								    SAVE_FPU
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    sw      sp, 0(a0)       /* store sp in preempted tasks TCB */
							 | 
						||
| 
								 | 
							
								    lw      sp, 0(a1)       /* get new task stack pointer */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    RESTORE_FPU
							 | 
						||
| 
								 | 
							
								    RESTORE_ALL_AND_RET
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * void rt_hw_context_switch_to(rt_uint32 to)/*
							 | 
						||
| 
								 | 
							
								 * a0 --> to
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								    .globl rt_hw_context_switch_to
							 | 
						||
| 
								 | 
							
								rt_hw_context_switch_to:
							 | 
						||
| 
								 | 
							
								    lw      sp, 0(a0)       /* get new task stack pointer */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    RESTORE_FPU
							 | 
						||
| 
								 | 
							
								    RESTORE_ALL_AND_RET
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/*
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								    .globl rt_thread_switch_interrupt_flag
							 | 
						||
| 
								 | 
							
								    .globl rt_interrupt_from_thread
							 | 
						||
| 
								 | 
							
								    .globl rt_interrupt_to_thread
							 | 
						||
| 
								 | 
							
								    .globl rt_hw_context_switch_interrupt
							 | 
						||
| 
								 | 
							
								rt_hw_context_switch_interrupt:
							 | 
						||
| 
								 | 
							
								    la      t0, rt_thread_switch_interrupt_flag
							 | 
						||
| 
								 | 
							
								    lw      t1, 0(t0)
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								    bnez    t1, _reswitch
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								    li      t1, 0x01                       /* set rt_thread_switch_interrupt_flag to 1 */
							 | 
						||
| 
								 | 
							
								    sw      t1, 0(t0)
							 | 
						||
| 
								 | 
							
								    la      t0, rt_interrupt_from_thread   /* set rt_interrupt_from_thread */
							 | 
						||
| 
								 | 
							
								    sw      a0, 0(t0)
							 | 
						||
| 
								 | 
							
								_reswitch:
							 | 
						||
| 
								 | 
							
								    la      t0, rt_interrupt_to_thread     /* set rt_interrupt_to_thread */
							 | 
						||
| 
								 | 
							
								    sw      a1, 0(t0)
							 | 
						||
| 
								 | 
							
								    jr      ra
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								    .globl rt_interrupt_enter
							 | 
						||
| 
								 | 
							
								    .globl rt_interrupt_leave
							 | 
						||
| 
								 | 
							
								    .globl mips_irq_handle
							 | 
						||
| 
								 | 
							
								mips_irq_handle:
							 | 
						||
| 
								 | 
							
								    SAVE_ALL
							 | 
						||
| 
								 | 
							
								    SAVE_FPU
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mfc0    t0, CP0_CAUSE
							 | 
						||
| 
								 | 
							
								    and     t1, t0, 0xff
							 | 
						||
| 
								 | 
							
									bnez	t1, spurious_interrupt		/* check exception */
							 | 
						||
| 
								 | 
							
									nop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* let k0 keep the current context sp */
							 | 
						||
| 
								 | 
							
								    move    k0, sp 
							 | 
						||
| 
								 | 
							
								    /* switch to kernel stack */
							 | 
						||
| 
								 | 
							
								    li      sp, SYSTEM_STACK
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    jal     rt_interrupt_enter
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								    jal     rt_interrupt_dispatch
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								    jal     rt_interrupt_leave
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* switch sp back to thread's context */
							 | 
						||
| 
								 | 
							
								    move    sp, k0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * if rt_thread_switch_interrupt_flag set, jump to
							 | 
						||
| 
								 | 
							
								     * rt_hw_context_switch_interrupt_do and don't return
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    la      k0, rt_thread_switch_interrupt_flag
							 | 
						||
| 
								 | 
							
								    lw      k1, 0(k0)
							 | 
						||
| 
								 | 
							
								    beqz    k1, spurious_interrupt
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								    sw      zero, 0(k0)                     /* clear flag */
							 | 
						||
| 
								 | 
							
									nop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * switch to the new thread
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    la      k0, rt_interrupt_from_thread
							 | 
						||
| 
								 | 
							
								    lw      k1, 0(k0)
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								    sw      sp, 0(k1)                       /* store sp in preempted tasks's TCB */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    la      k0, rt_interrupt_to_thread
							 | 
						||
| 
								 | 
							
								    lw      k1, 0(k0)
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								    lw      sp, 0(k1)                       /* get new task's stack pointer */
							 | 
						||
| 
								 | 
							
								    j       spurious_interrupt
							 | 
						||
| 
								 | 
							
								    nop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								spurious_interrupt:
							 | 
						||
| 
								 | 
							
								    RESTORE_FPU
							 | 
						||
| 
								 | 
							
								    RESTORE_ALL_AND_RET
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    .set reorder
							 |