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 * 2011-05-24     aozima       first version
9 * 2019-07-19     Zhou Yanjie  clean up code
10 */
11
12#ifndef __ASSEMBLY__
13#define __ASSEMBLY__
14#endif
15
16#include <p32xxxx.h>
17#include "../common/mips_def.h"
18#include "../common/stackframe.h"
19
20    .section ".text", "ax"
21    .set        noat
22    .set noreorder
23
24/*
25 * rt_base_t rt_hw_interrupt_disable()
26 */
27    .globl rt_hw_interrupt_disable
28rt_hw_interrupt_disable:
29    mfc0    v0, CP0_STATUS    /* v0 = status */
30    addiu   v1, zero,   -2    /* v1 = 0-2 = 0xFFFFFFFE */
31    and     v1, v0, v1        /* v1 = v0 & 0xFFFFFFFE */
32    mtc0    v1, CP0_STATUS    /* status = v1 */
33    jr      ra
34    nop
35
36/*
37 * void rt_hw_interrupt_enable(rt_base_t level)
38 */
39    .globl rt_hw_interrupt_enable
40rt_hw_interrupt_enable:
41    mtc0    a0, CP0_STATUS
42    jr      ra
43    nop
44
45/*
46 * void rt_hw_context_switch_to(rt_uint32 to)/*
47 * a0 --> to
48 */
49    .globl rt_hw_context_switch_to
50rt_hw_context_switch_to:
51    lw      sp, 0(a0)       /* get new task stack pointer */
52
53    RESTORE_ALL_AND_RET
54
55/*
56 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)
57 * a0 --> from
58 * a1 --> to
59 */
60    .globl rt_hw_context_switch
61rt_hw_context_switch:
62    mtc0    ra, CP0_EPC
63    SAVE_ALL
64
65    sw      sp, 0(a0)       /* store sp in preempted tasks TCB */
66    lw      sp, 0(a1)       /* get new task stack pointer */
67
68    RESTORE_ALL_AND_RET
69
70/*
71 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/*
72 */
73    .globl rt_thread_switch_interrupt_flag
74    .globl rt_interrupt_from_thread
75    .globl rt_interrupt_to_thread
76    .globl rt_hw_context_switch_interrupt
77rt_hw_context_switch_interrupt:
78    la      t0, rt_thread_switch_interrupt_flag
79    lw      t1, 0(t0)
80    nop
81    bnez    t1, _reswitch
82    nop
83    li      t1, 0x01                       /* set rt_thread_switch_interrupt_flag to 1 */
84    sw      t1, 0(t0)
85    la      t0, rt_interrupt_from_thread   /* set rt_interrupt_from_thread */
86    sw      a0, 0(t0)
87_reswitch:
88    la      t0, rt_interrupt_to_thread     /* set rt_interrupt_to_thread */
89    sw      a1, 0(t0)
90
91    /* trigger the soft exception (causes context switch) */
92    mfc0    t0, CP0_CAUSE                  /* t0 = Cause */
93    ori     t0, t0, (1<<8)                 /* t0 |= (1<<8) */
94    mtc0    t0, CP0_CAUSE                  /* cause = t0 */
95    addiu   t1, zero,   -257               /* t1 = ~(1<<8) */
96    and     t0, t0, t1                     /* t0 &= t1 */
97    mtc0    t0, CP0_CAUSE                  /* cause = t0 */
98    jr      ra
99    nop
100
101/*
102 * void __ISR(_CORE_SOFTWARE_0_VECTOR, ipl2) CoreSW0Handler(void)
103 */
104    .section ".text", "ax"
105    .set noreorder
106    .set        noat
107    .ent        CoreSW0Handler
108
109        .globl CoreSW0Handler
110CoreSW0Handler:
111    SAVE_ALL
112
113    /* mCS0ClearIntFlag(); */
114    la      t0, IFS0CLR             /* t0 = IFS0CLR */
115    addiu   t1,zero,0x02            /* t1 = (1<<2) */
116    sw      t1, 0(t0)               /* IFS0CLR = t1 */
117
118    la      k0, rt_thread_switch_interrupt_flag
119    sw      zero, 0(k0)                     /* clear flag */
120
121    /*
122     * switch to the new thread
123     */
124    la      k0, rt_interrupt_from_thread
125    lw      k1, 0(k0)
126    nop
127    sw      sp, 0(k1)                       /* store sp in preempted tasks's TCB */
128
129    la      k0, rt_interrupt_to_thread
130    lw      k1, 0(k0)
131    nop
132    lw      sp, 0(k1)                       /* get new task's stack pointer */
133
134    RESTORE_ALL_AND_RET
135
136    .end        CoreSW0Handler
137