xref: /nrf52832-nimble/rt-thread/libcpu/mips/loongson_1b/context_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
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