context_gcc.S 9.0 KB
Newer Older
1 2
/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
3
 * Copyright (c) 2021, Alibaba Group Holding Limited
4 5 6 7 8 9
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020/08/20     zx.chen      The T-HEAD RISC-V CPU E906 porting implementation
10
 * 2021/08/13     zx.chen      update T-HEAD E9xx-series(E906/7/F/D/P) CPU porting code.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 */

#include "cpuport.h"

#ifdef RT_USING_SMP
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
#define rt_hw_interrupt_enable  rt_hw_local_irq_enable
#endif

/*
 * Functions: vPortYield
 */
.global vPortYield
.type   vPortYield, %function
vPortYield:
    li      t0, 0xE080100C
    lb      t1, (t0)
    li      t2, 0x01
    or      t1, t1, t2
    sb      t1, (t0)

    ret

/*
 * #ifdef RT_USING_SMP
 * void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
 * #else
 * void rt_hw_context_switch_to(rt_ubase_t to);
 * #endif
 * a0 --> to
 * a1 --> to_thread
 */
    .globl rt_hw_context_switch_to
rt_hw_context_switch_to:
    /* save a0 to to_thread */
    la      t0, rt_interrupt_to_thread
    STORE   a0, (t0)
48

49 50 51 52
    /* save 0 to from_thread */
    la      t0, rt_interrupt_from_thread
    li      t1, 0
    STORE   t1, (t0)
53

54 55 56 57 58
    /* set rt_thread_switch_interrupt_flag=1 */
    la      t0, rt_thread_switch_interrupt_flag
    li      t1, 1
    STORE   t1, (t0)

59 60 61 62
    /* enable mexstatus SPUSHEN */
#ifdef CONFIG_THEAD_EXT_SPUSHEN
    li      t0, 0x10000
    csrs    mexstatus, t0
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
#endif

    csrw    mscratch, sp
    /* set software interrupt */
    li      t0, 0xE080100C
    lb      t1, (t0)
    li      t2, 0x01
    or      t1, t1, t2
    sb      t1, (t0)

    /* enable global interrup */
    csrsi   mstatus, 8

    ret

/*
 * #ifdef RT_USING_SMP
 * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
 * #else
 * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
 * #endif
 *
 * a0 --> from
 * a1 --> to
 * a2 --> to_thread
 */
    .globl rt_hw_context_switch
rt_hw_context_switch:
    .globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
    /* check rt_thread_switch_interrupt_flag */
    la      t0, rt_thread_switch_interrupt_flag
    lw      t1, (t0)
    li      t2, 1
    beq     t1, t2, .reswitch
    /*  set rt_thread_switch_interrupt_flag=1 */
    STORE   t2, (t0)
100

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    /* update from_thread */
    la      t0, rt_interrupt_from_thread
    STORE   a0, (t0)

.reswitch:
    /* update to_thread */
    la      t0, rt_interrupt_to_thread
    STORE   a1, (t0)
    /* set software interrupt */
    li      t0, 0xE080100C
    lb      t1, (t0)
    li      t2, 0x01
    or      t1, t1, t2
    sb      t1, (t0)

    ret

/*
 *    PendSV_Handler
 */
.global PendSV_Handler
.type   PendSV_Handler, %function
PendSV_Handler:

    /* check rt_thread_switch_interrupt_flag */
    sw      t0, (-4)(sp)
    sw      t1, (-8)(sp)
    la      t0, rt_thread_switch_interrupt_flag
    lw      t1, (t0)
    beqz    t1, .pendsv_exit

    /* clear rt_thread_switch_interrupt_flag */
    li      t1, 0x0
    sw      t1, (t0)

    /* check rt_interrupt_from_thread */
    la      t0, rt_interrupt_from_thread
    lw      t1, (t0)
    beqz    t1, .switch_to_thead
140

141
    /* restore from thread context t0,t1 */
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
    lw      t0, (-4)(sp)
    lw      t1, (-8)(sp)

#ifdef ARCH_RISCV_FPU
    addi    sp, sp, -32 * FREGBYTES

    FSTORE  f0, 0 * FREGBYTES(sp)
    FSTORE  f1, 1 * FREGBYTES(sp)
    FSTORE  f2, 2 * FREGBYTES(sp)
    FSTORE  f3, 3 * FREGBYTES(sp)
    FSTORE  f4, 4 * FREGBYTES(sp)
    FSTORE  f5, 5 * FREGBYTES(sp)
    FSTORE  f6, 6 * FREGBYTES(sp)
    FSTORE  f7, 7 * FREGBYTES(sp)
    FSTORE  f8, 8 * FREGBYTES(sp)
    FSTORE  f9, 9 * FREGBYTES(sp)
    FSTORE  f10, 10 * FREGBYTES(sp)
    FSTORE  f11, 11 * FREGBYTES(sp)
    FSTORE  f12, 12 * FREGBYTES(sp)
    FSTORE  f13, 13 * FREGBYTES(sp)
    FSTORE  f14, 14 * FREGBYTES(sp)
    FSTORE  f15, 15 * FREGBYTES(sp)
    FSTORE  f16, 16 * FREGBYTES(sp)
    FSTORE  f17, 17 * FREGBYTES(sp)
    FSTORE  f18, 18 * FREGBYTES(sp)
    FSTORE  f19, 19 * FREGBYTES(sp)
    FSTORE  f20, 20 * FREGBYTES(sp)
    FSTORE  f21, 21 * FREGBYTES(sp)
    FSTORE  f22, 22 * FREGBYTES(sp)
    FSTORE  f23, 23 * FREGBYTES(sp)
    FSTORE  f24, 24 * FREGBYTES(sp)
    FSTORE  f25, 25 * FREGBYTES(sp)
    FSTORE  f26, 26 * FREGBYTES(sp)
    FSTORE  f27, 27 * FREGBYTES(sp)
    FSTORE  f28, 28 * FREGBYTES(sp)
    FSTORE  f29, 29 * FREGBYTES(sp)
    FSTORE  f30, 30 * FREGBYTES(sp)
    FSTORE  f31, 31 * FREGBYTES(sp)
#endif

182 183 184
#ifdef ARCH_RISCV_DSP
    addi    sp, sp, -33 * REGBYTES
#else
185
    addi    sp, sp, -32 * REGBYTES
186
#endif
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221

    STORE   x1, 1 * REGBYTES(sp)
    csrr    x1, mepc
    STORE   x1, 0 * REGBYTES(sp)
    csrr    x1, mstatus
    STORE   x1, 2 * REGBYTES(sp)
    /* x3 don't need save */
    STORE   x4, 4 * REGBYTES(sp)
    STORE   x5, 5 * REGBYTES(sp)
    STORE   x6, 6 * REGBYTES(sp)
    STORE   x7, 7 * REGBYTES(sp)
    STORE   x8, 8 * REGBYTES(sp)
    STORE   x9, 9 * REGBYTES(sp)
    STORE   x10, 10 * REGBYTES(sp)
    STORE   x11, 11 * REGBYTES(sp)
    STORE   x12, 12 * REGBYTES(sp)
    STORE   x13, 13 * REGBYTES(sp)
    STORE   x14, 14 * REGBYTES(sp)
    STORE   x15, 15 * REGBYTES(sp)
    STORE   x16, 16 * REGBYTES(sp)
    STORE   x17, 17 * REGBYTES(sp)
    STORE   x18, 18 * REGBYTES(sp)
    STORE   x19, 19 * REGBYTES(sp)
    STORE   x20, 20 * REGBYTES(sp)
    STORE   x21, 21 * REGBYTES(sp)
    STORE   x22, 22 * REGBYTES(sp)
    STORE   x23, 23 * REGBYTES(sp)
    STORE   x24, 24 * REGBYTES(sp)
    STORE   x25, 25 * REGBYTES(sp)
    STORE   x26, 26 * REGBYTES(sp)
    STORE   x27, 27 * REGBYTES(sp)
    STORE   x28, 28 * REGBYTES(sp)
    STORE   x29, 29 * REGBYTES(sp)
    STORE   x30, 30 * REGBYTES(sp)
    STORE   x31, 31 * REGBYTES(sp)
222 223 224 225
#ifdef ARCH_RISCV_DSP
    csrr    t0, vxsat
    STORE   t0, 32 * REGBYTES(sp)
#endif
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

    /* store from_thread sp */
    la      t0, rt_interrupt_from_thread
    lw      t0, (t0)
    sw      sp, (t0)

.switch_to_thead:
    /* restore to thread context
     * sp(0) -> epc;
     * sp(1) -> ra;
     * sp(i) -> x(i+2)
     */
    la      t0, rt_interrupt_to_thread
    lw      t0, (t0)
    LOAD    sp, (t0)

242 243 244 245 246 247

#ifdef ARCH_RISCV_DSP
    LOAD    a1, 32 * REGBYTES(sp)
    csrw    vxsat, a1
#endif

248 249 250 251 252
    /* restore ra to mepc */
    LOAD    a1, 0 * REGBYTES(sp)
    csrw    mepc, a1
    LOAD    x1, 1 * REGBYTES(sp)

253
    /* force to machine mode(MPP=11) */
254
    LOAD    a1, 2 * REGBYTES(sp)
255
    csrw    mstatus, a1
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
    /* x3 don't need restore */
    LOAD    x4, 4 * REGBYTES(sp)
    LOAD    x5, 5 * REGBYTES(sp)
    LOAD    x6, 6 * REGBYTES(sp)
    LOAD    x7, 7 * REGBYTES(sp)
    LOAD    x8, 8 * REGBYTES(sp)
    LOAD    x9, 9 * REGBYTES(sp)
    LOAD    x10, 10 * REGBYTES(sp)
    LOAD    x11, 11 * REGBYTES(sp)
    LOAD    x12, 12 * REGBYTES(sp)
    LOAD    x13, 13 * REGBYTES(sp)
    LOAD    x14, 14 * REGBYTES(sp)
    LOAD    x15, 15 * REGBYTES(sp)
    LOAD    x16, 16 * REGBYTES(sp)
    LOAD    x17, 17 * REGBYTES(sp)
    LOAD    x18, 18 * REGBYTES(sp)
    LOAD    x19, 19 * REGBYTES(sp)
    LOAD    x20, 20 * REGBYTES(sp)
    LOAD    x21, 21 * REGBYTES(sp)
    LOAD    x22, 22 * REGBYTES(sp)
    LOAD    x23, 23 * REGBYTES(sp)
    LOAD    x24, 24 * REGBYTES(sp)
    LOAD    x25, 25 * REGBYTES(sp)
    LOAD    x26, 26 * REGBYTES(sp)
    LOAD    x27, 27 * REGBYTES(sp)
    LOAD    x28, 28 * REGBYTES(sp)
    LOAD    x29, 29 * REGBYTES(sp)
    LOAD    x30, 30 * REGBYTES(sp)
    LOAD    x31, 31 * REGBYTES(sp)

286 287 288
#ifdef ARCH_RISCV_DSP
    addi    sp, sp, 33 * REGBYTES
#else
289
    addi    sp, sp, 32 * REGBYTES
290
#endif
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331

#ifdef ARCH_RISCV_FPU
    FLOAD   f0, 0 * FREGBYTES(sp)
    FLOAD   f1, 1 * FREGBYTES(sp)
    FLOAD   f2, 2 * FREGBYTES(sp)
    FLOAD   f3, 3 * FREGBYTES(sp)
    FLOAD   f4, 4 * FREGBYTES(sp)
    FLOAD   f5, 5 * FREGBYTES(sp)
    FLOAD   f6, 6 * FREGBYTES(sp)
    FLOAD   f7, 7 * FREGBYTES(sp)
    FLOAD   f8, 8 * FREGBYTES(sp)
    FLOAD   f9, 9 * FREGBYTES(sp)
    FLOAD   f10, 10 * FREGBYTES(sp)
    FLOAD   f11, 11 * FREGBYTES(sp)
    FLOAD   f12, 12 * FREGBYTES(sp)
    FLOAD   f13, 13 * FREGBYTES(sp)
    FLOAD   f14, 14 * FREGBYTES(sp)
    FLOAD   f15, 15 * FREGBYTES(sp)
    FLOAD   f16, 16 * FREGBYTES(sp)
    FLOAD   f17, 17 * FREGBYTES(sp)
    FLOAD   f18, 18 * FREGBYTES(sp)
    FLOAD   f19, 19 * FREGBYTES(sp)
    FLOAD   f20, 20 * FREGBYTES(sp)
    FLOAD   f21, 21 * FREGBYTES(sp)
    FLOAD   f22, 22 * FREGBYTES(sp)
    FLOAD   f23, 23 * FREGBYTES(sp)
    FLOAD   f24, 24 * FREGBYTES(sp)
    FLOAD   f25, 25 * FREGBYTES(sp)
    FLOAD   f26, 26 * FREGBYTES(sp)
    FLOAD   f27, 27 * FREGBYTES(sp)
    FLOAD   f28, 28 * FREGBYTES(sp)
    FLOAD   f29, 29 * FREGBYTES(sp)
    FLOAD   f30, 30 * FREGBYTES(sp)
    FLOAD   f31, 31 * FREGBYTES(sp)

    addi    sp, sp, 32 * FREGBYTES
#endif

.pendsv_exit:
    mret

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
/*
 * rt_base_t rt_hw_interrupt_disable(void);
 */
    .globl rt_hw_interrupt_disable
    .type   rt_hw_interrupt_disable, %function
rt_hw_interrupt_disable:
    csrrci a0, mstatus, 8
    ret


/*
 * void rt_hw_interrupt_enable(rt_base_t level);
 */
    .globl rt_hw_interrupt_enable
    .type   rt_hw_interrupt_enable, %function
rt_hw_interrupt_enable:
    csrw mstatus, a0
    ret
350