xref: /nrf52832-nimble/rt-thread/libcpu/mips/loongson_1c/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#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