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#include "stackframe_fpu.h" 20*10465441SEvalZero 21*10465441SEvalZero .section ".text", "ax" 22*10465441SEvalZero .set noreorder 23*10465441SEvalZero 24*10465441SEvalZero/* 25*10465441SEvalZero * rt_base_t rt_hw_interrupt_disable() 26*10465441SEvalZero */ 27*10465441SEvalZero .globl rt_hw_interrupt_disable 28*10465441SEvalZerort_hw_interrupt_disable: 29*10465441SEvalZero mfc0 v0, CP0_STATUS 30*10465441SEvalZero and v1, v0, 0xfffffffe 31*10465441SEvalZero mtc0 v1, CP0_STATUS 32*10465441SEvalZero jr ra 33*10465441SEvalZero nop 34*10465441SEvalZero 35*10465441SEvalZero/* 36*10465441SEvalZero * void rt_hw_interrupt_enable(rt_base_t level) 37*10465441SEvalZero */ 38*10465441SEvalZero .globl rt_hw_interrupt_enable 39*10465441SEvalZerort_hw_interrupt_enable: 40*10465441SEvalZero ori a0, 0x00000800 41*10465441SEvalZero mtc0 a0, CP0_STATUS 42*10465441SEvalZero ehb 43*10465441SEvalZero mfc0 v0, CP0_CAUSE 44*10465441SEvalZero ehb 45*10465441SEvalZero or v1, v0, 0x800000 //EBASE + 0x200 46*10465441SEvalZero mtc0 v1, CP0_CAUSE 47*10465441SEvalZero ehb 48*10465441SEvalZero jr ra 49*10465441SEvalZero nop 50*10465441SEvalZero 51*10465441SEvalZero/* 52*10465441SEvalZero * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to) 53*10465441SEvalZero * a0 --> from 54*10465441SEvalZero * a1 --> to 55*10465441SEvalZero */ 56*10465441SEvalZero .globl rt_hw_context_switch 57*10465441SEvalZerort_hw_context_switch: 58*10465441SEvalZero mtc0 ra, CP0_EPC 59*10465441SEvalZero SAVE_ALL 60*10465441SEvalZero SAVE_FPU 61*10465441SEvalZero 62*10465441SEvalZero sw sp, 0(a0) /* store sp in preempted tasks TCB */ 63*10465441SEvalZero lw sp, 0(a1) /* get new task stack pointer */ 64*10465441SEvalZero 65*10465441SEvalZero RESTORE_FPU 66*10465441SEvalZero RESTORE_ALL_AND_RET 67*10465441SEvalZero 68*10465441SEvalZero/* 69*10465441SEvalZero * void rt_hw_context_switch_to(rt_uint32 to)/* 70*10465441SEvalZero * a0 --> to 71*10465441SEvalZero */ 72*10465441SEvalZero .globl rt_hw_context_switch_to 73*10465441SEvalZerort_hw_context_switch_to: 74*10465441SEvalZero lw sp, 0(a0) /* get new task stack pointer */ 75*10465441SEvalZero 76*10465441SEvalZero RESTORE_FPU 77*10465441SEvalZero RESTORE_ALL_AND_RET 78*10465441SEvalZero 79*10465441SEvalZero/* 80*10465441SEvalZero * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/* 81*10465441SEvalZero */ 82*10465441SEvalZero .globl rt_thread_switch_interrupt_flag 83*10465441SEvalZero .globl rt_interrupt_from_thread 84*10465441SEvalZero .globl rt_interrupt_to_thread 85*10465441SEvalZero .globl rt_hw_context_switch_interrupt 86*10465441SEvalZerort_hw_context_switch_interrupt: 87*10465441SEvalZero la t0, rt_thread_switch_interrupt_flag 88*10465441SEvalZero lw t1, 0(t0) 89*10465441SEvalZero nop 90*10465441SEvalZero bnez t1, _reswitch 91*10465441SEvalZero nop 92*10465441SEvalZero li t1, 0x01 /* set rt_thread_switch_interrupt_flag to 1 */ 93*10465441SEvalZero sw t1, 0(t0) 94*10465441SEvalZero la t0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */ 95*10465441SEvalZero sw a0, 0(t0) 96*10465441SEvalZero_reswitch: 97*10465441SEvalZero la t0, rt_interrupt_to_thread /* set rt_interrupt_to_thread */ 98*10465441SEvalZero sw a1, 0(t0) 99*10465441SEvalZero jr ra 100*10465441SEvalZero nop 101*10465441SEvalZero 102*10465441SEvalZero/* 103*10465441SEvalZero * void rt_hw_context_switch_interrupt_do(rt_base_t flag) 104*10465441SEvalZero */ 105*10465441SEvalZero .globl rt_interrupt_enter 106*10465441SEvalZero .globl rt_interrupt_leave 107*10465441SEvalZero .globl mips_irq_handle 108*10465441SEvalZeromips_irq_handle: 109*10465441SEvalZero SAVE_ALL 110*10465441SEvalZero SAVE_FPU 111*10465441SEvalZero 112*10465441SEvalZero mfc0 t0, CP0_CAUSE 113*10465441SEvalZero and t1, t0, 0xff 114*10465441SEvalZero bnez t1, spurious_interrupt /* check exception */ 115*10465441SEvalZero nop 116*10465441SEvalZero 117*10465441SEvalZero /* let k0 keep the current context sp */ 118*10465441SEvalZero move k0, sp 119*10465441SEvalZero /* switch to kernel stack */ 120*10465441SEvalZero li sp, SYSTEM_STACK 121*10465441SEvalZero 122*10465441SEvalZero jal rt_interrupt_enter 123*10465441SEvalZero nop 124*10465441SEvalZero jal rt_interrupt_dispatch 125*10465441SEvalZero nop 126*10465441SEvalZero jal rt_interrupt_leave 127*10465441SEvalZero nop 128*10465441SEvalZero 129*10465441SEvalZero /* switch sp back to thread's context */ 130*10465441SEvalZero move sp, k0 131*10465441SEvalZero 132*10465441SEvalZero /* 133*10465441SEvalZero * if rt_thread_switch_interrupt_flag set, jump to 134*10465441SEvalZero * rt_hw_context_switch_interrupt_do and don't return 135*10465441SEvalZero */ 136*10465441SEvalZero la k0, rt_thread_switch_interrupt_flag 137*10465441SEvalZero lw k1, 0(k0) 138*10465441SEvalZero beqz k1, spurious_interrupt 139*10465441SEvalZero nop 140*10465441SEvalZero sw zero, 0(k0) /* clear flag */ 141*10465441SEvalZero nop 142*10465441SEvalZero 143*10465441SEvalZero /* 144*10465441SEvalZero * switch to the new thread 145*10465441SEvalZero */ 146*10465441SEvalZero la k0, rt_interrupt_from_thread 147*10465441SEvalZero lw k1, 0(k0) 148*10465441SEvalZero nop 149*10465441SEvalZero sw sp, 0(k1) /* store sp in preempted tasks's TCB */ 150*10465441SEvalZero 151*10465441SEvalZero la k0, rt_interrupt_to_thread 152*10465441SEvalZero lw k1, 0(k0) 153*10465441SEvalZero nop 154*10465441SEvalZero lw sp, 0(k1) /* get new task's stack pointer */ 155*10465441SEvalZero j spurious_interrupt 156*10465441SEvalZero nop 157*10465441SEvalZero 158*10465441SEvalZerospurious_interrupt: 159*10465441SEvalZero RESTORE_FPU 160*10465441SEvalZero RESTORE_ALL_AND_RET 161*10465441SEvalZero 162*10465441SEvalZero .set reorder 163