]> begriffs open source - freertos/blob - portable/GCC/IA32_flat/portASM.S
FreeRTOS MPU: Remove MPU region number check (#1261)
[freertos] / portable / GCC / IA32_flat / portASM.S
1 /*
2  * FreeRTOS Kernel <DEVELOPMENT BRANCH>
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 .file "portASM.S"
30 #include "FreeRTOSConfig.h"
31 #include "ISR_Support.h"
32
33     .extern pxCurrentTCB
34     .extern vTaskSwitchContext
35     .extern vPortCentralInterruptHandler
36     .extern xTaskIncrementTick
37     .extern vPortAPICErrorHandler
38     .extern pucPortTaskFPUContextBuffer
39     .extern ulPortYieldPending
40
41     .global vPortStartFirstTask
42     .global vPortCentralInterruptWrapper
43     .global vPortAPICErrorHandlerWrapper
44     .global vPortTimerHandler
45     .global vPortYieldCall
46     .global vPortAPICSpuriousHandler
47
48     .text
49
50 /*-----------------------------------------------------------*/
51
52 .align 4
53 .func vPortYieldCall
54 vPortYieldCall:
55     /* Save general purpose registers. */
56     pusha
57
58     .if configSUPPORT_FPU == 1
59
60         /* If the task has a buffer allocated to save the FPU context then save
61         the FPU context now. */
62         movl    pucPortTaskFPUContextBuffer, %eax
63         test    %eax, %eax
64         je      1f
65         fnsave  ( %eax )
66         fwait
67
68         1:
69
70         /* Save the address of the FPU context, if any. */
71         push    pucPortTaskFPUContextBuffer
72
73     .endif /* configSUPPORT_FPU */
74
75     /* Find the TCB. */
76     movl    pxCurrentTCB, %eax
77
78     /* Stack location is first item in the TCB. */
79     movl    %esp, (%eax)
80
81     call vTaskSwitchContext
82
83     /* Find the location of pxCurrentTCB again - a callee saved register could
84     be used in place of eax to prevent this second load, but that then relies
85     on the compiler and other asm code. */
86     movl    pxCurrentTCB, %eax
87     movl    (%eax), %esp
88
89     .if configSUPPORT_FPU == 1
90
91         /* Restore address of task's FPU context buffer. */
92         pop     pucPortTaskFPUContextBuffer
93
94         /* If the task has a buffer allocated in which its FPU context is saved,
95         then restore it now. */
96         movl    pucPortTaskFPUContextBuffer, %eax
97         test    %eax, %eax
98         je      1f
99         frstor  ( %eax )
100         1:
101     .endif
102
103     popa
104     iret
105
106 .endfunc
107 /*-----------------------------------------------------------*/
108
109 .align 4
110 .func vPortStartFirstTask
111 vPortStartFirstTask:
112
113     /* Find the TCB. */
114     movl    pxCurrentTCB, %eax
115
116     /* Stack location is first item in the TCB. */
117     movl    (%eax), %esp
118
119     /* Restore FPU context flag. */
120     .if configSUPPORT_FPU == 1
121
122         pop     pucPortTaskFPUContextBuffer
123
124     .endif /* configSUPPORT_FPU */
125
126     /* Restore general purpose registers. */
127     popa
128     iret
129 .endfunc
130 /*-----------------------------------------------------------*/
131
132 .align 4
133 .func vPortAPICErrorHandlerWrapper
134 vPortAPICErrorHandlerWrapper:
135     pusha
136     call    vPortAPICErrorHandler
137     popa
138     /* EOI. */
139     movl    $0x00, (0xFEE000B0)
140     iret
141 .endfunc
142 /*-----------------------------------------------------------*/
143
144 .align 4
145 .func vPortTimerHandler
146 vPortTimerHandler:
147
148     /* Save general purpose registers. */
149     pusha
150
151     /* Interrupts are not nested, so save the rest of the task context. */
152     .if configSUPPORT_FPU == 1
153
154         /* If the task has a buffer allocated to save the FPU context then save the
155         FPU context now. */
156         movl    pucPortTaskFPUContextBuffer, %eax
157         test    %eax, %eax
158         je      1f
159         fnsave  ( %eax ) /* Save FLOP context into ucTempFPUBuffer array. */
160         fwait
161
162         1:
163         /* Save the address of the FPU context, if any. */
164         push    pucPortTaskFPUContextBuffer
165
166     .endif /* configSUPPORT_FPU */
167
168     /* Find the TCB. */
169     movl    pxCurrentTCB, %eax
170
171     /* Stack location is first item in the TCB. */
172     movl    %esp, (%eax)
173
174     /* Switch stacks. */
175     movl    ulTopOfSystemStack, %esp
176     movl    %esp, %ebp
177
178     /* Increment nesting count. */
179     add     $1, ulInterruptNesting
180
181     call    xTaskIncrementTick
182
183     sti
184
185     /* Is a switch to another task required? */
186     test    %eax, %eax
187     je      _skip_context_switch
188     cli
189     call    vTaskSwitchContext
190
191 _skip_context_switch:
192     cli
193
194     /* Decrement the variable used to determine if a switch to a system
195     stack is necessary. */
196     sub     $1, ulInterruptNesting
197
198     /* Stack location is first item in the TCB. */
199     movl    pxCurrentTCB, %eax
200     movl    (%eax), %esp
201
202     .if configSUPPORT_FPU == 1
203
204         /* Restore address of task's FPU context buffer. */
205         pop     pucPortTaskFPUContextBuffer
206
207         /* If the task has a buffer allocated in which its FPU context is saved,
208         then restore it now. */
209         movl    pucPortTaskFPUContextBuffer, %eax
210         test    %eax, %eax
211         je      1f
212         frstor  ( %eax )
213         1:
214     .endif
215
216     popa
217
218     /* EOI. */
219     movl    $0x00, (0xFEE000B0)
220     iret
221
222 .endfunc
223 /*-----------------------------------------------------------*/
224
225 .if configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1
226
227     .align 4
228     .func vPortCentralInterruptWrapper
229     vPortCentralInterruptWrapper:
230
231         portFREERTOS_INTERRUPT_ENTRY
232
233         movl $0xFEE00170, %eax          /* Highest In Service Register (ISR) long word. */
234         movl $8, %ecx                   /* Loop counter. */
235
236     next_isr_long_word:
237         test %ecx, %ecx                 /* Loop counter reached 0? */
238         je wrapper_epilogue             /* Looked at all ISR registers without finding a bit set. */
239         sub $1, %ecx                    /* Sub 1 from loop counter. */
240         movl (%eax), %ebx               /* Load next ISR long word. */
241         sub $0x10, %eax                 /* Point to next ISR long word in case no bits are set in the current long word. */
242         test %ebx, %ebx                 /* Are there any bits set? */
243         je next_isr_long_word           /* Look at next ISR long word if no bits were set. */
244         sti
245         bsr %ebx, %ebx                  /* A bit was set, which one? */
246         movl $32, %eax                  /* Destination operand for following multiplication. */
247         mul %ecx                        /* Calculate base vector for current register, 32 vectors per register. */
248         add %ebx, %eax                  /* Add bit offset into register to get final vector number. */
249         push %eax                       /* Vector number is function parameter. */
250         call vPortCentralInterruptHandler
251         pop %eax                        /* Remove parameter. */
252
253     wrapper_epilogue:
254         portFREERTOS_INTERRUPT_EXIT
255
256     .endfunc
257
258 .endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
259 /*-----------------------------------------------------------*/
260
261 .align 4
262 .func vPortAPISpuriousHandler
263 vPortAPICSpuriousHandler:
264     iret
265
266 .endfunc
267
268 .end