1/*
2 * FreeRTOS Kernel V11.1.0
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 * the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * https://www.FreeRTOS.org
25 * https://github.com/FreeRTOS
26 *
27 */
28
29.extern     vTaskSwitchContext
30
31.set noat
32
33# Exported to start the first task.
34.globl restore_sp_from_pxCurrentTCB
35
36# Entry point for exceptions.
37.section .exceptions.entry.user, "xa"
38
39# Save the entire context of a task.
40save_context:
41    addi    sp, sp, -116        # Create space on the stack.
42    stw     ra, 0(sp)
43                                # Leave a gap for muldiv 0
44    stw     at, 8(sp)
45    stw     r2, 12(sp)
46    stw     r3, 16(sp)
47    stw     r4, 20(sp)
48    stw     r5, 24(sp)
49    stw     r6, 28(sp)
50    stw     r7, 32(sp)
51    stw     r8, 36(sp)
52    stw     r9, 40(sp)
53    stw     r10, 44(sp)
54    stw     r11, 48(sp)
55    stw     r12, 52(sp)
56    stw     r13, 56(sp)
57    stw     r14, 60(sp)
58    stw     r15, 64(sp)
59    rdctl   r5, estatus         # Save the eStatus
60    stw     r5, 68(sp)
61    addi    r15, ea, -4         # Instruction that caused exception
62    stw     r15, 72(sp)         # Save as EA
63    stw     r16, 76(sp)         # Save the remaining registers
64    stw     r17, 80(sp)
65    stw     r18, 84(sp)
66    stw     r19, 88(sp)
67    stw     r20, 92(sp)
68    stw     r21, 96(sp)
69    stw     r22, 100(sp)
70    stw     r23, 104(sp)
71    stw     gp, 108(sp)
72    stw     fp, 112(sp)
73
74save_sp_to_pxCurrentTCB:
75    movia   et, pxCurrentTCB    # Load the address of the pxCurrentTCB pointer
76    ldw     et, (et)            # Load the value of the pxCurrentTCB pointer
77    stw     sp, (et)            # Store the stack pointer into the top of the TCB
78
79    br      irq_test_user       # skip the section .exceptions.entry
80
81    .section .exceptions.irqtest, "xa"
82irq_test_user:
83
84    .section .exceptions.exit.user, "xa"
85restore_sp_from_pxCurrentTCB:
86    movia   et, pxCurrentTCB        # Load the address of the pxCurrentTCB pointer
87    ldw     et, (et)                # Load the value of the pxCurrentTCB pointer
88    ldw     sp, (et)                # Load the stack pointer with the top value of the TCB
89
90restore_context:
91    ldw     ra, 0(sp)       # Restore the registers.
92                            # Leave a gap for muldiv 0.
93    ldw     at, 8(sp)
94    ldw     r2, 12(sp)
95    ldw     r3, 16(sp)
96    ldw     r4, 20(sp)
97    ldw     r5, 24(sp)
98    ldw     r6, 28(sp)
99    ldw     r7, 32(sp)
100    ldw     r8, 36(sp)
101    ldw     r9, 40(sp)
102    ldw     r10, 44(sp)
103    ldw     r11, 48(sp)
104    ldw     r12, 52(sp)
105    ldw     r13, 56(sp)
106    ldw     r14, 60(sp)
107    ldw     r15, 64(sp)
108    ldw     et, 68(sp)      # Load the eStatus
109    wrctl   estatus, et     # Write the eStatus
110    ldw     ea, 72(sp)      # Load the Program Counter
111    ldw     r16, 76(sp)
112    ldw     r17, 80(sp)
113    ldw     r18, 84(sp)
114    ldw     r19, 88(sp)
115    ldw     r20, 92(sp)
116    ldw     r21, 96(sp)
117    ldw     r22, 100(sp)
118    ldw     r23, 104(sp)
119    ldw     gp, 108(sp)
120    ldw     fp, 112(sp)
121    addi    sp, sp, 116     # Release stack space
122
123    eret                    # Return to address ea, loading eStatus into Status.
124
125    .section .exceptions.soft, "xa"
126soft_exceptions:
127    movhi   r3, 0x003b              /* upper half of trap opcode */
128    ori     r3, r3, 0x683a          /* lower half of trap opcode */
129    beq     r2, r3, call_scheduler
130    br      exceptions_unknown_user         # its something else
131
132call_scheduler:
133    stw     ea, 72(sp)                      # EA is PC+4 so will skip over instruction causing exception
134    movia   r15, vTaskSwitchContext         # Pick the next context - use long call version in place of "call"
135    callr   r15
136    br      restore_sp_from_pxCurrentTCB    # Switch in the task context and restore.
137
138    .section .exceptions.unknown.user
139exceptions_unknown_user:
140