f83f0a1fbf42bc791af14a69666eb5f1827cbf50
[openocd.git] / src / rtos / rtos_standard_stackings.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2011 by Broadcom Corporation *
5 * Evan Hunter - ehunter@broadcom.com *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "rtos.h"
13 #include "target/armv7m.h"
14
15 static const struct stack_register_offset rtos_standard_cortex_m3_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
16 { ARMV7M_R0, 0x20, 32 }, /* r0 */
17 { ARMV7M_R1, 0x24, 32 }, /* r1 */
18 { ARMV7M_R2, 0x28, 32 }, /* r2 */
19 { ARMV7M_R3, 0x2c, 32 }, /* r3 */
20 { ARMV7M_R4, 0x00, 32 }, /* r4 */
21 { ARMV7M_R5, 0x04, 32 }, /* r5 */
22 { ARMV7M_R6, 0x08, 32 }, /* r6 */
23 { ARMV7M_R7, 0x0c, 32 }, /* r7 */
24 { ARMV7M_R8, 0x10, 32 }, /* r8 */
25 { ARMV7M_R9, 0x14, 32 }, /* r9 */
26 { ARMV7M_R10, 0x18, 32 }, /* r10 */
27 { ARMV7M_R11, 0x1c, 32 }, /* r11 */
28 { ARMV7M_R12, 0x30, 32 }, /* r12 */
29 { ARMV7M_R13, -2, 32 }, /* sp */
30 { ARMV7M_R14, 0x34, 32 }, /* lr */
31 { ARMV7M_PC, 0x38, 32 }, /* pc */
32 { ARMV7M_XPSR, 0x3c, 32 }, /* xPSR */
33 };
34
35 static const struct stack_register_offset rtos_standard_cortex_m4f_stack_offsets[] = {
36 { ARMV7M_R0, 0x24, 32 }, /* r0 */
37 { ARMV7M_R1, 0x28, 32 }, /* r1 */
38 { ARMV7M_R2, 0x2c, 32 }, /* r2 */
39 { ARMV7M_R3, 0x30, 32 }, /* r3 */
40 { ARMV7M_R4, 0x00, 32 }, /* r4 */
41 { ARMV7M_R5, 0x04, 32 }, /* r5 */
42 { ARMV7M_R6, 0x08, 32 }, /* r6 */
43 { ARMV7M_R7, 0x0c, 32 }, /* r7 */
44 { ARMV7M_R8, 0x10, 32 }, /* r8 */
45 { ARMV7M_R9, 0x14, 32 }, /* r9 */
46 { ARMV7M_R10, 0x18, 32 }, /* r10 */
47 { ARMV7M_R11, 0x1c, 32 }, /* r11 */
48 { ARMV7M_R12, 0x34, 32 }, /* r12 */
49 { ARMV7M_R13, -2, 32 }, /* sp */
50 { ARMV7M_R14, 0x38, 32 }, /* lr */
51 { ARMV7M_PC, 0x3c, 32 }, /* pc */
52 { ARMV7M_XPSR, 0x40, 32 }, /* xPSR */
53 };
54
55 static const struct stack_register_offset rtos_standard_cortex_m4f_fpu_stack_offsets[] = {
56 { ARMV7M_R0, 0x64, 32 }, /* r0 */
57 { ARMV7M_R1, 0x68, 32 }, /* r1 */
58 { ARMV7M_R2, 0x6c, 32 }, /* r2 */
59 { ARMV7M_R3, 0x70, 32 }, /* r3 */
60 { ARMV7M_R4, 0x00, 32 }, /* r4 */
61 { ARMV7M_R5, 0x04, 32 }, /* r5 */
62 { ARMV7M_R6, 0x08, 32 }, /* r6 */
63 { ARMV7M_R7, 0x0c, 32 }, /* r7 */
64 { ARMV7M_R8, 0x10, 32 }, /* r8 */
65 { ARMV7M_R9, 0x14, 32 }, /* r9 */
66 { ARMV7M_R10, 0x18, 32 }, /* r10 */
67 { ARMV7M_R11, 0x1c, 32 }, /* r11 */
68 { ARMV7M_R12, 0x74, 32 }, /* r12 */
69 { ARMV7M_R13, -2, 32 }, /* sp */
70 { ARMV7M_R14, 0x78, 32 }, /* lr */
71 { ARMV7M_PC, 0x7c, 32 }, /* pc */
72 { ARMV7M_XPSR, 0x80, 32 }, /* xPSR */
73 };
74
75
76 static const struct stack_register_offset rtos_standard_cortex_r4_stack_offsets[] = {
77 { 0, 0x08, 32 }, /* r0 (a1) */
78 { 1, 0x0c, 32 }, /* r1 (a2) */
79 { 2, 0x10, 32 }, /* r2 (a3) */
80 { 3, 0x14, 32 }, /* r3 (a4) */
81 { 4, 0x18, 32 }, /* r4 (v1) */
82 { 5, 0x1c, 32 }, /* r5 (v2) */
83 { 6, 0x20, 32 }, /* r6 (v3) */
84 { 7, 0x24, 32 }, /* r7 (v4) */
85 { 8, 0x28, 32 }, /* r8 (a1) */
86 { 10, 0x2c, 32 }, /* r9 (sb) */
87 { 11, 0x30, 32 }, /* r10 (sl) */
88 { 12, 0x34, 32 }, /* r11 (fp) */
89 { 13, 0x38, 32 }, /* r12 (ip) */
90 { 14, -2, 32 }, /* sp */
91 { 15, 0x3c, 32 }, /* lr */
92 { 16, 0x40, 32 }, /* pc */
93 { 17, -1, 96 }, /* FPA1 */
94 { 18, -1, 96 }, /* FPA2 */
95 { 19, -1, 96 }, /* FPA3 */
96 { 20, -1, 96 }, /* FPA4 */
97 { 21, -1, 96 }, /* FPA5 */
98 { 22, -1, 96 }, /* FPA6 */
99 { 23, -1, 96 }, /* FPA7 */
100 { 24, -1, 96 }, /* FPA8 */
101 { 25, -1, 32 }, /* FPS */
102 { 26, 0x04, 32 }, /* CSPR */
103 };
104
105 static target_addr_t rtos_generic_stack_align(struct target *target,
106 const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
107 target_addr_t stack_ptr, int align)
108 {
109 target_addr_t new_stack_ptr;
110 target_addr_t aligned_stack_ptr;
111 new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
112 stacking->stack_registers_size;
113 aligned_stack_ptr = new_stack_ptr & ~((target_addr_t)align - 1);
114 if (aligned_stack_ptr != new_stack_ptr &&
115 stacking->stack_growth_direction == -1) {
116 /* If we have a downward growing stack, the simple alignment code
117 * above results in a wrong result (since it rounds down to nearest
118 * alignment). We want to round up so add an extra align.
119 */
120 aligned_stack_ptr += (target_addr_t)align;
121 }
122 return aligned_stack_ptr;
123 }
124
125 target_addr_t rtos_generic_stack_align8(struct target *target,
126 const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
127 target_addr_t stack_ptr)
128 {
129 return rtos_generic_stack_align(target, stack_data,
130 stacking, stack_ptr, 8);
131 }
132
133 /* The Cortex-M3 will indicate that an alignment adjustment
134 * has been done on the stack by setting bit 9 of the stacked xPSR
135 * register. In this case, we can just add an extra 4 bytes to get
136 * to the program stack. Note that some places in the ARM documentation
137 * make this a little unclear but the padding takes place before the
138 * normal exception stacking - so xPSR is always available at a fixed
139 * location.
140 *
141 * Relevant documentation:
142 * Cortex-M series processors -> Cortex-M3 -> Revision: xxx ->
143 * Cortex-M3 Devices Generic User Guide -> The Cortex-M3 Processor ->
144 * Exception Model -> Exception entry and return -> Exception entry
145 * Cortex-M series processors -> Cortex-M3 -> Revision: xxx ->
146 * Cortex-M3 Devices Generic User Guide -> Cortex-M3 Peripherals ->
147 * System control block -> Configuration and Control Register (STKALIGN)
148 *
149 * This is just a helper function for use in the calculate_process_stack
150 * function for a given architecture/rtos.
151 */
152 target_addr_t rtos_cortex_m_stack_align(struct target *target,
153 const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
154 target_addr_t stack_ptr, size_t xpsr_offset)
155 {
156 const uint32_t ALIGN_NEEDED = (1 << 9);
157 uint32_t xpsr;
158 target_addr_t new_stack_ptr;
159
160 new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
161 stacking->stack_registers_size;
162 xpsr = (target->endianness == TARGET_LITTLE_ENDIAN) ?
163 le_to_h_u32(&stack_data[xpsr_offset]) :
164 be_to_h_u32(&stack_data[xpsr_offset]);
165 if ((xpsr & ALIGN_NEEDED) != 0) {
166 LOG_DEBUG("XPSR(0x%08" PRIx32 ") indicated stack alignment was necessary\r\n",
167 xpsr);
168 new_stack_ptr -= (stacking->stack_growth_direction * 4);
169 }
170 return new_stack_ptr;
171 }
172
173 static target_addr_t rtos_standard_cortex_m3_stack_align(struct target *target,
174 const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
175 target_addr_t stack_ptr)
176 {
177 const int XPSR_OFFSET = 0x3c;
178 return rtos_cortex_m_stack_align(target, stack_data, stacking,
179 stack_ptr, XPSR_OFFSET);
180 }
181
182 static target_addr_t rtos_standard_cortex_m4f_stack_align(struct target *target,
183 const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
184 target_addr_t stack_ptr)
185 {
186 const int XPSR_OFFSET = 0x40;
187 return rtos_cortex_m_stack_align(target, stack_data, stacking,
188 stack_ptr, XPSR_OFFSET);
189 }
190
191 static target_addr_t rtos_standard_cortex_m4f_fpu_stack_align(struct target *target,
192 const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
193 target_addr_t stack_ptr)
194 {
195 const int XPSR_OFFSET = 0x80;
196 return rtos_cortex_m_stack_align(target, stack_data, stacking,
197 stack_ptr, XPSR_OFFSET);
198 }
199
200
201 const struct rtos_register_stacking rtos_standard_cortex_m3_stacking = {
202 .stack_registers_size = 0x40,
203 .stack_growth_direction = -1,
204 .num_output_registers = ARMV7M_NUM_CORE_REGS,
205 .calculate_process_stack = rtos_standard_cortex_m3_stack_align,
206 .register_offsets = rtos_standard_cortex_m3_stack_offsets
207 };
208
209 const struct rtos_register_stacking rtos_standard_cortex_m4f_stacking = {
210 .stack_registers_size = 0x44,
211 .stack_growth_direction = -1,
212 .num_output_registers = ARMV7M_NUM_CORE_REGS,
213 .calculate_process_stack = rtos_standard_cortex_m4f_stack_align,
214 .register_offsets = rtos_standard_cortex_m4f_stack_offsets
215 };
216
217 const struct rtos_register_stacking rtos_standard_cortex_m4f_fpu_stacking = {
218 .stack_registers_size = 0xcc,
219 .stack_growth_direction = -1,
220 .num_output_registers = ARMV7M_NUM_CORE_REGS,
221 .calculate_process_stack = rtos_standard_cortex_m4f_fpu_stack_align,
222 .register_offsets = rtos_standard_cortex_m4f_fpu_stack_offsets
223 };
224
225 const struct rtos_register_stacking rtos_standard_cortex_r4_stacking = {
226 .stack_registers_size = 0x48,
227 .stack_growth_direction = -1,
228 .num_output_registers = 26,
229 .calculate_process_stack = rtos_generic_stack_align8,
230 .register_offsets = rtos_standard_cortex_r4_stack_offsets
231 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)