1/*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date           Author       Notes
8 * 2019-12-04     Jiaxun Yang  Initial version
9 * 2020-07-26     lizhirui     Fixed some problems
10 */
11
12#ifndef __ASSEMBLY__
13#define __ASSEMBLY__
14#endif
15
16#include "mips_regs.h"
17#include "stackframe.h"
18
19    .section ".text", "ax"
20    .set noreorder
21
22/*
23 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)
24 * a0 --> from
25 * a1 --> to
26 */
27    .globl rt_hw_context_switch
28rt_hw_context_switch:
29    MTC0    ra, CP0_EPC
30    SAVE_ALL
31
32    REG_S      sp, 0(a0)       /* store sp in preempted tasks TCB */
33    REG_L      sp, 0(a1)       /* get new task stack pointer */
34
35    RESTORE_ALL_AND_RET
36
37/*
38 * void rt_hw_context_switch_to(rt_uint32 to)/*
39 * a0 --> to
40 */
41    .globl rt_hw_context_switch_to
42rt_hw_context_switch_to:
43    REG_L      sp, 0(a0)       /* get new task stack pointer */
44    RESTORE_ALL_AND_RET
45
46/*
47 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/*
48 */
49    .globl rt_thread_switch_interrupt_flag
50    .globl rt_interrupt_from_thread
51    .globl rt_interrupt_to_thread
52    .globl rt_hw_context_switch_interrupt
53rt_hw_context_switch_interrupt:
54    PTR_LA      t0, rt_thread_switch_interrupt_flag
55    REG_L       t1, 0(t0)
56    nop
57    bnez    t1, _reswitch
58    nop
59    li      t1, 0x01                       /* set rt_thread_switch_interrupt_flag to 1 */
60    LONG_S      t1, 0(t0)
61    PTR_LA      t0, rt_interrupt_from_thread   /* set rt_interrupt_from_thread */
62    LONG_S      a0, 0(t0)
63_reswitch:
64    PTR_LA      t0, rt_interrupt_to_thread     /* set rt_interrupt_to_thread */
65    LONG_S      a1, 0(t0)
66    jr      ra
67    nop
68
69/*
70 * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
71 */
72    .globl rt_interrupt_enter
73    .globl rt_interrupt_leave
74    .globl rt_general_exc_dispatch
75    .globl mips_irq_handle
76mips_irq_handle:
77    SAVE_ALL
78
79    /* let k0 keep the current context sp */
80    move    k0, sp
81    /* switch to kernel stack */
82    PTR_LA  sp, _system_stack
83
84    jal     rt_interrupt_enter
85    nop
86    /* Get Old SP from k0 as paremeter in a0 */
87    move    a0, k0
88    jal     rt_general_exc_dispatch
89    nop
90    jal     rt_interrupt_leave
91    nop
92
93    /* switch sp back to thread context */
94    move    sp, k0
95
96    /*
97    * if rt_thread_switch_interrupt_flag set, jump to
98    * rt_hw_context_switch_interrupt_do and do not return
99    */
100    PTR_LA  k0, rt_thread_switch_interrupt_flag
101    LONG_L  k1, 0(k0)
102    beqz    k1, spurious_interrupt
103    nop
104    LONG_S  zero, 0(k0)                     /* clear flag */
105    nop
106
107    /*
108    * switch to the new thread
109    */
110    PTR_LA  k0, rt_interrupt_from_thread
111    LONG_L  k1, 0(k0)
112    nop
113    LONG_S  sp, 0(k1)                       /* store sp in preempted task TCB */
114
115    PTR_LA  k0, rt_interrupt_to_thread
116    LONG_L  k1, 0(k0)
117    nop
118    LONG_L  sp, 0(k1)                       /* get new task stack pointer */
119    j       spurious_interrupt
120    nop
121
122spurious_interrupt:
123    RESTORE_ALL_AND_RET
124    .set reorder
125