1*10465441SEvalZero/* 2*10465441SEvalZero * File : context_gcc.S 3*10465441SEvalZero * This file is part of RT-Thread RTOS 4*10465441SEvalZero * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team 5*10465441SEvalZero * 6*10465441SEvalZero * The license and distribution terms for this file may be 7*10465441SEvalZero * found in the file LICENSE in this distribution or at 8*10465441SEvalZero * http://www.rt-thread.org/license/LICENSE 9*10465441SEvalZero * 10*10465441SEvalZero * Change Logs: 11*10465441SEvalZero * Date Author Notes 12*10465441SEvalZero * 2010-05-17 swkyer first version 13*10465441SEvalZero * 2010-09-11 bernard port to Loongson SoC3210 14*10465441SEvalZero * 2011-08-08 lgnq port to Loongson LS1B 15*10465441SEvalZero */ 16*10465441SEvalZero 17*10465441SEvalZero#include "../common/mips.inc" 18*10465441SEvalZero#include "../common/stackframe.h" 19*10465441SEvalZero 20*10465441SEvalZero .section ".text", "ax" 21*10465441SEvalZero .set noreorder 22*10465441SEvalZero 23*10465441SEvalZero/* 24*10465441SEvalZero * rt_base_t rt_hw_interrupt_disable() 25*10465441SEvalZero */ 26*10465441SEvalZero .globl rt_hw_interrupt_disable 27*10465441SEvalZerort_hw_interrupt_disable: 28*10465441SEvalZero mfc0 v0, CP0_STATUS 29*10465441SEvalZero and v1, v0, 0xfffffffe 30*10465441SEvalZero mtc0 v1, CP0_STATUS 31*10465441SEvalZero jr ra 32*10465441SEvalZero nop 33*10465441SEvalZero 34*10465441SEvalZero/* 35*10465441SEvalZero * void rt_hw_interrupt_enable(rt_base_t level) 36*10465441SEvalZero */ 37*10465441SEvalZero .globl rt_hw_interrupt_enable 38*10465441SEvalZerort_hw_interrupt_enable: 39*10465441SEvalZero mtc0 a0, CP0_STATUS 40*10465441SEvalZero jr ra 41*10465441SEvalZero nop 42*10465441SEvalZero 43*10465441SEvalZero/* 44*10465441SEvalZero * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to) 45*10465441SEvalZero * a0 --> from 46*10465441SEvalZero * a1 --> to 47*10465441SEvalZero */ 48*10465441SEvalZero .globl rt_hw_context_switch 49*10465441SEvalZerort_hw_context_switch: 50*10465441SEvalZero mtc0 ra, CP0_EPC 51*10465441SEvalZero SAVE_ALL 52*10465441SEvalZero 53*10465441SEvalZero sw sp, 0(a0) /* store sp in preempted tasks TCB */ 54*10465441SEvalZero lw sp, 0(a1) /* get new task stack pointer */ 55*10465441SEvalZero 56*10465441SEvalZero RESTORE_ALL_AND_RET 57*10465441SEvalZero 58*10465441SEvalZero/* 59*10465441SEvalZero * void rt_hw_context_switch_to(rt_uint32 to)/* 60*10465441SEvalZero * a0 --> to 61*10465441SEvalZero */ 62*10465441SEvalZero .globl rt_hw_context_switch_to 63*10465441SEvalZerort_hw_context_switch_to: 64*10465441SEvalZero lw sp, 0(a0) /* get new task stack pointer */ 65*10465441SEvalZero 66*10465441SEvalZero RESTORE_ALL_AND_RET 67*10465441SEvalZero 68*10465441SEvalZero/* 69*10465441SEvalZero * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/* 70*10465441SEvalZero */ 71*10465441SEvalZero .globl rt_thread_switch_interrupt_flag 72*10465441SEvalZero .globl rt_interrupt_from_thread 73*10465441SEvalZero .globl rt_interrupt_to_thread 74*10465441SEvalZero .globl rt_hw_context_switch_interrupt 75*10465441SEvalZerort_hw_context_switch_interrupt: 76*10465441SEvalZero la t0, rt_thread_switch_interrupt_flag 77*10465441SEvalZero lw t1, 0(t0) 78*10465441SEvalZero nop 79*10465441SEvalZero bnez t1, _reswitch 80*10465441SEvalZero nop 81*10465441SEvalZero li t1, 0x01 /* set rt_thread_switch_interrupt_flag to 1 */ 82*10465441SEvalZero sw t1, 0(t0) 83*10465441SEvalZero la t0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */ 84*10465441SEvalZero sw a0, 0(t0) 85*10465441SEvalZero_reswitch: 86*10465441SEvalZero la t0, rt_interrupt_to_thread /* set rt_interrupt_to_thread */ 87*10465441SEvalZero sw a1, 0(t0) 88*10465441SEvalZero jr ra 89*10465441SEvalZero nop 90*10465441SEvalZero 91*10465441SEvalZero/* 92*10465441SEvalZero * void rt_hw_context_switch_interrupt_do(rt_base_t flag) 93*10465441SEvalZero */ 94*10465441SEvalZero .globl rt_interrupt_enter 95*10465441SEvalZero .globl rt_interrupt_leave 96*10465441SEvalZero .globl mips_irq_handle 97*10465441SEvalZeromips_irq_handle: 98*10465441SEvalZero SAVE_ALL 99*10465441SEvalZero 100*10465441SEvalZero mfc0 t0, CP0_CAUSE 101*10465441SEvalZero and t1, t0, 0xff 102*10465441SEvalZero bnez t1, spurious_interrupt /* check exception */ 103*10465441SEvalZero nop 104*10465441SEvalZero 105*10465441SEvalZero /* let k0 keep the current context sp */ 106*10465441SEvalZero move k0, sp 107*10465441SEvalZero /* switch to kernel stack */ 108*10465441SEvalZero li sp, SYSTEM_STACK 109*10465441SEvalZero 110*10465441SEvalZero jal rt_interrupt_enter 111*10465441SEvalZero nop 112*10465441SEvalZero jal rt_interrupt_dispatch 113*10465441SEvalZero nop 114*10465441SEvalZero jal rt_interrupt_leave 115*10465441SEvalZero nop 116*10465441SEvalZero 117*10465441SEvalZero /* switch sp back to thread's context */ 118*10465441SEvalZero move sp, k0 119*10465441SEvalZero 120*10465441SEvalZero /* 121*10465441SEvalZero * if rt_thread_switch_interrupt_flag set, jump to 122*10465441SEvalZero * rt_hw_context_switch_interrupt_do and don't return 123*10465441SEvalZero */ 124*10465441SEvalZero la k0, rt_thread_switch_interrupt_flag 125*10465441SEvalZero lw k1, 0(k0) 126*10465441SEvalZero beqz k1, spurious_interrupt 127*10465441SEvalZero nop 128*10465441SEvalZero sw zero, 0(k0) /* clear flag */ 129*10465441SEvalZero nop 130*10465441SEvalZero 131*10465441SEvalZero /* 132*10465441SEvalZero * switch to the new thread 133*10465441SEvalZero */ 134*10465441SEvalZero la k0, rt_interrupt_from_thread 135*10465441SEvalZero lw k1, 0(k0) 136*10465441SEvalZero nop 137*10465441SEvalZero sw sp, 0(k1) /* store sp in preempted tasks's TCB */ 138*10465441SEvalZero 139*10465441SEvalZero la k0, rt_interrupt_to_thread 140*10465441SEvalZero lw k1, 0(k0) 141*10465441SEvalZero nop 142*10465441SEvalZero lw sp, 0(k1) /* get new task's stack pointer */ 143*10465441SEvalZero j spurious_interrupt 144*10465441SEvalZero nop 145*10465441SEvalZero 146*10465441SEvalZerospurious_interrupt: 147*10465441SEvalZero RESTORE_ALL_AND_RET 148*10465441SEvalZero 149*10465441SEvalZero .set reorder 150