@@ -11,13 +11,13 @@ use core::sync::atomic::{compiler_fence, Ordering};
11
11
12
12
#[ inline( always) ]
13
13
pub unsafe fn __bkpt ( ) {
14
- asm ! ( "bkpt" , options( nostack) ) ;
14
+ asm ! ( "bkpt" , options( nomem , nostack, preserves_flags ) ) ;
15
15
}
16
16
17
17
#[ inline( always) ]
18
18
pub unsafe fn __control_r ( ) -> u32 {
19
19
let r;
20
- asm ! ( "mrs {}, CONTROL" , out( reg) r) ;
20
+ asm ! ( "mrs {}, CONTROL" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
21
21
r
22
22
}
23
23
@@ -28,7 +28,8 @@ pub unsafe fn __control_w(w: u32) {
28
28
asm ! (
29
29
"msr CONTROL, {}" ,
30
30
"isb" ,
31
- in( reg) w
31
+ in( reg) w,
32
+ options( nomem, nostack, preserves_flags) ,
32
33
) ;
33
34
34
35
// Ensure memory accesses are not reordered around the CONTROL update.
@@ -37,7 +38,7 @@ pub unsafe fn __control_w(w: u32) {
37
38
38
39
#[ inline( always) ]
39
40
pub unsafe fn __cpsid ( ) {
40
- asm ! ( "cpsid i" ) ;
41
+ asm ! ( "cpsid i" , options ( nomem , nostack , preserves_flags ) ) ;
41
42
42
43
// Ensure no subsequent memory accesses are reordered to before interrupts are disabled.
43
44
compiler_fence ( Ordering :: SeqCst ) ;
@@ -48,7 +49,7 @@ pub unsafe fn __cpsie() {
48
49
// Ensure no preceeding memory accesses are reordered to after interrupts are enabled.
49
50
compiler_fence ( Ordering :: SeqCst ) ;
50
51
51
- asm ! ( "cpsie i" ) ;
52
+ asm ! ( "cpsie i" , options ( nomem , nostack , preserves_flags ) ) ;
52
53
}
53
54
54
55
#[ inline( always) ]
@@ -63,48 +64,53 @@ pub unsafe fn __delay(cyc: u32) {
63
64
"1:" ,
64
65
"subs {}, #1" ,
65
66
"bne 1b" ,
66
- inout( reg) real_cyc => _
67
+ inout( reg) real_cyc => _,
68
+ options( nomem, nostack) ,
67
69
) ;
68
70
}
69
71
70
72
#[ inline( always) ]
71
73
pub unsafe fn __dmb ( ) {
72
74
compiler_fence ( Ordering :: SeqCst ) ;
73
- asm ! ( "dmb" ) ;
75
+ asm ! ( "dmb" , options ( nomem , nostack , preserves_flags ) ) ;
74
76
compiler_fence ( Ordering :: SeqCst ) ;
75
77
}
76
78
77
79
#[ inline( always) ]
78
80
pub unsafe fn __dsb ( ) {
79
81
compiler_fence ( Ordering :: SeqCst ) ;
80
- asm ! ( "dsb" ) ;
82
+ asm ! ( "dsb" , options ( nomem , nostack , preserves_flags ) ) ;
81
83
compiler_fence ( Ordering :: SeqCst ) ;
82
84
}
83
85
84
86
#[ inline( always) ]
85
87
pub unsafe fn __isb ( ) {
86
88
compiler_fence ( Ordering :: SeqCst ) ;
87
- asm ! ( "isb" ) ;
89
+ asm ! ( "isb" , options ( nomem , nostack , preserves_flags ) ) ;
88
90
compiler_fence ( Ordering :: SeqCst ) ;
89
91
}
90
92
91
93
#[ inline( always) ]
92
94
pub unsafe fn __msp_r ( ) -> u32 {
93
95
let r;
94
- asm ! ( "mrs {}, MSP" , out( reg) r) ;
96
+ asm ! ( "mrs {}, MSP" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
95
97
r
96
98
}
97
99
98
100
#[ inline( always) ]
99
101
pub unsafe fn __msp_w ( val : u32 ) {
100
- asm ! ( "msr MSP, {}" , in( reg) val) ;
102
+ // Technically is writing to the stack pointer "not pushing any data to the stack"?
103
+ // In any event, if we don't set `nostack` here, this method is useless as the new
104
+ // stack value is immediately mutated by returning. Really this is just not a good
105
+ // method and its higher-level use is marked as deprecated in cortex-m.
106
+ asm ! ( "msr MSP, {}" , in( reg) val, options( nomem, nostack, preserves_flags) ) ;
101
107
}
102
108
103
109
// NOTE: No FFI shim, this requires inline asm.
104
110
#[ inline( always) ]
105
111
pub unsafe fn __apsr_r ( ) -> u32 {
106
112
let r;
107
- asm ! ( "mrs {}, APSR" , out( reg) r) ;
113
+ asm ! ( "mrs {}, APSR" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
108
114
r
109
115
}
110
116
@@ -113,80 +119,82 @@ pub unsafe fn __nop() {
113
119
// NOTE: This is a `pure` asm block, but applying that option allows the compiler to eliminate
114
120
// the nop entirely (or to collapse multiple subsequent ones). Since the user probably wants N
115
121
// nops when they call `nop` N times, let's not add that option.
116
- asm ! ( "nop" ) ;
122
+ asm ! ( "nop" , options ( nomem , nostack , preserves_flags ) ) ;
117
123
}
118
124
119
125
// NOTE: No FFI shim, this requires inline asm.
120
126
#[ inline( always) ]
121
127
pub unsafe fn __pc_r ( ) -> u32 {
122
128
let r;
123
- asm ! ( "mov {}, pc" , out( reg) r) ;
129
+ asm ! ( "mov {}, pc" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
124
130
r
125
131
}
126
132
127
133
// NOTE: No FFI shim, this requires inline asm.
128
134
#[ inline( always) ]
129
135
pub unsafe fn __pc_w ( val : u32 ) {
130
- asm ! ( "mov pc, {}" , in( reg) val) ;
136
+ asm ! ( "mov pc, {}" , in( reg) val, options ( nomem , nostack , preserves_flags ) ) ;
131
137
}
132
138
133
139
// NOTE: No FFI shim, this requires inline asm.
134
140
#[ inline( always) ]
135
141
pub unsafe fn __lr_r ( ) -> u32 {
136
142
let r;
137
- asm ! ( "mov {}, lr" , out( reg) r) ;
143
+ asm ! ( "mov {}, lr" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
138
144
r
139
145
}
140
146
141
147
// NOTE: No FFI shim, this requires inline asm.
142
148
#[ inline( always) ]
143
149
pub unsafe fn __lr_w ( val : u32 ) {
144
- asm ! ( "mov lr, {}" , in( reg) val) ;
150
+ asm ! ( "mov lr, {}" , in( reg) val, options ( nomem , nostack , preserves_flags ) ) ;
145
151
}
146
152
147
153
#[ inline( always) ]
148
154
pub unsafe fn __primask_r ( ) -> u32 {
149
155
let r;
150
- asm ! ( "mrs {}, PRIMASK" , out( reg) r) ;
156
+ asm ! ( "mrs {}, PRIMASK" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
151
157
r
152
158
}
153
159
154
160
#[ inline( always) ]
155
161
pub unsafe fn __psp_r ( ) -> u32 {
156
162
let r;
157
- asm ! ( "mrs {}, PSP" , out( reg) r) ;
163
+ asm ! ( "mrs {}, PSP" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
158
164
r
159
165
}
160
166
161
167
#[ inline( always) ]
162
168
pub unsafe fn __psp_w ( val : u32 ) {
163
- asm ! ( "msr PSP, {}" , in( reg) val) ;
169
+ // See comment on __msp_w. Unlike MSP, there are legitimate use-cases for modifying PSP
170
+ // if MSP is currently being used as the stack pointer.
171
+ asm ! ( "msr PSP, {}" , in( reg) val, options( nomem, nostack, preserves_flags) ) ;
164
172
}
165
173
166
174
#[ inline( always) ]
167
175
pub unsafe fn __sev ( ) {
168
- asm ! ( "sev" ) ;
176
+ asm ! ( "sev" , options ( nomem , nostack , preserves_flags ) ) ;
169
177
}
170
178
171
179
#[ inline( always) ]
172
180
pub unsafe fn __udf ( ) -> ! {
173
- asm ! ( "udf #0" , options( noreturn) ) ;
181
+ asm ! ( "udf #0" , options( noreturn, nomem , nostack , preserves_flags ) ) ;
174
182
}
175
183
176
184
#[ inline( always) ]
177
185
pub unsafe fn __wfe ( ) {
178
- asm ! ( "wfe" ) ;
186
+ asm ! ( "wfe" , options ( nomem , nostack , preserves_flags ) ) ;
179
187
}
180
188
181
189
#[ inline( always) ]
182
190
pub unsafe fn __wfi ( ) {
183
- asm ! ( "wfi" ) ;
191
+ asm ! ( "wfi" , options ( nomem , nostack , preserves_flags ) ) ;
184
192
}
185
193
186
194
/// Semihosting syscall.
187
195
#[ inline( always) ]
188
196
pub unsafe fn __sh_syscall ( mut nr : u32 , arg : u32 ) -> u32 {
189
- asm ! ( "bkpt #0xab" , inout( "r0" ) nr, in( "r1" ) arg) ;
197
+ asm ! ( "bkpt #0xab" , inout( "r0" ) nr, in( "r1" ) arg, options ( nomem , nostack , preserves_flags ) ) ;
190
198
nr
191
199
}
192
200
@@ -206,7 +214,7 @@ pub unsafe fn __bootstrap(msp: u32, rv: u32) -> ! {
206
214
spsel = in( reg) 2 ,
207
215
msp = in( reg) msp,
208
216
rv = in( reg) rv,
209
- options( noreturn) ,
217
+ options( noreturn, nomem , nostack ) ,
210
218
) ;
211
219
}
212
220
@@ -220,25 +228,25 @@ mod v7m {
220
228
221
229
#[ inline( always) ]
222
230
pub unsafe fn __basepri_max ( val : u8 ) {
223
- asm ! ( "msr BASEPRI_MAX, {}" , in( reg) val) ;
231
+ asm ! ( "msr BASEPRI_MAX, {}" , in( reg) val, options ( nomem , nostack , preserves_flags ) ) ;
224
232
}
225
233
226
234
#[ inline( always) ]
227
235
pub unsafe fn __basepri_r ( ) -> u8 {
228
236
let r;
229
- asm ! ( "mrs {}, BASEPRI" , out( reg) r) ;
237
+ asm ! ( "mrs {}, BASEPRI" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
230
238
r
231
239
}
232
240
233
241
#[ inline( always) ]
234
242
pub unsafe fn __basepri_w ( val : u8 ) {
235
- asm ! ( "msr BASEPRI, {}" , in( reg) val) ;
243
+ asm ! ( "msr BASEPRI, {}" , in( reg) val, options ( nomem , nostack , preserves_flags ) ) ;
236
244
}
237
245
238
246
#[ inline( always) ]
239
247
pub unsafe fn __faultmask_r ( ) -> u32 {
240
248
let r;
241
- asm ! ( "mrs {}, FAULTMASK" , out( reg) r) ;
249
+ asm ! ( "mrs {}, FAULTMASK" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
242
250
r
243
251
}
244
252
@@ -257,6 +265,7 @@ mod v7m {
257
265
out( reg) _,
258
266
out( reg) _,
259
267
out( reg) _,
268
+ options( nostack) ,
260
269
) ;
261
270
compiler_fence ( Ordering :: SeqCst ) ;
262
271
}
@@ -276,6 +285,7 @@ mod v7m {
276
285
out( reg) _,
277
286
out( reg) _,
278
287
out( reg) _,
288
+ options( nostack) ,
279
289
) ;
280
290
compiler_fence ( Ordering :: SeqCst ) ;
281
291
}
@@ -299,6 +309,7 @@ mod v7em {
299
309
"cpsie i" ,
300
310
in( reg) val,
301
311
out( reg) _,
312
+ options( nomem, nostack, preserves_flags) ,
302
313
) ;
303
314
}
304
315
@@ -314,6 +325,7 @@ mod v7em {
314
325
"cpsie i" ,
315
326
in( reg) val,
316
327
out( reg) _,
328
+ options( nomem, nostack, preserves_flags) ,
317
329
) ;
318
330
}
319
331
}
@@ -327,43 +339,59 @@ mod v8m {
327
339
328
340
#[ inline( always) ]
329
341
pub unsafe fn __tt ( mut target : u32 ) -> u32 {
330
- asm ! ( "tt {target}, {target}" , target = inout( reg) target) ;
342
+ asm ! (
343
+ "tt {target}, {target}" ,
344
+ target = inout( reg) target,
345
+ options( nomem, nostack, preserves_flags) ,
346
+ ) ;
331
347
target
332
348
}
333
349
334
350
#[ inline( always) ]
335
351
pub unsafe fn __ttt ( mut target : u32 ) -> u32 {
336
- asm ! ( "ttt {target}, {target}" , target = inout( reg) target) ;
352
+ asm ! (
353
+ "ttt {target}, {target}" ,
354
+ target = inout( reg) target,
355
+ options( nomem, nostack, preserves_flags) ,
356
+ ) ;
337
357
target
338
358
}
339
359
340
360
#[ inline( always) ]
341
361
pub unsafe fn __tta ( mut target : u32 ) -> u32 {
342
- asm ! ( "tta {target}, {target}" , target = inout( reg) target) ;
362
+ asm ! (
363
+ "tta {target}, {target}" ,
364
+ target = inout( reg) target,
365
+ options( nomem, nostack, preserves_flags) ,
366
+ ) ;
343
367
target
344
368
}
345
369
346
370
#[ inline( always) ]
347
371
pub unsafe fn __ttat ( mut target : u32 ) -> u32 {
348
- asm ! ( "ttat {target}, {target}" , target = inout( reg) target) ;
372
+ asm ! (
373
+ "ttat {target}, {target}" ,
374
+ target = inout( reg) target,
375
+ options( nomem, nostack, preserves_flags) ,
376
+ ) ;
349
377
target
350
378
}
351
379
352
380
#[ inline( always) ]
353
381
pub unsafe fn __msp_ns_r ( ) -> u32 {
354
382
let r;
355
- asm ! ( "mrs {}, MSP_NS" , out( reg) r) ;
383
+ asm ! ( "mrs {}, MSP_NS" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
356
384
r
357
385
}
358
386
359
387
#[ inline( always) ]
360
388
pub unsafe fn __msp_ns_w ( val : u32 ) {
361
- asm ! ( "msr MSP_NS, {}" , in( reg) val) ;
389
+ asm ! ( "msr MSP_NS, {}" , in( reg) val, options ( nomem , nostack , preserves_flags ) ) ;
362
390
}
363
391
364
392
#[ inline( always) ]
365
393
pub unsafe fn __bxns ( val : u32 ) {
366
- asm ! ( "BXNS {}" , in( reg) val) ;
394
+ asm ! ( "BXNS {}" , in( reg) val, options ( nomem , nostack , preserves_flags ) ) ;
367
395
}
368
396
}
369
397
@@ -377,25 +405,25 @@ mod v8m_main {
377
405
#[ inline( always) ]
378
406
pub unsafe fn __msplim_r ( ) -> u32 {
379
407
let r;
380
- asm ! ( "mrs {}, MSPLIM" , out( reg) r) ;
408
+ asm ! ( "mrs {}, MSPLIM" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
381
409
r
382
410
}
383
411
384
412
#[ inline( always) ]
385
413
pub unsafe fn __msplim_w ( val : u32 ) {
386
- asm ! ( "msr MSPLIM, {}" , in( reg) val) ;
414
+ asm ! ( "msr MSPLIM, {}" , in( reg) val, options ( nomem , nostack , preserves_flags ) ) ;
387
415
}
388
416
389
417
#[ inline( always) ]
390
418
pub unsafe fn __psplim_r ( ) -> u32 {
391
419
let r;
392
- asm ! ( "mrs {}, PSPLIM" , out( reg) r) ;
420
+ asm ! ( "mrs {}, PSPLIM" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
393
421
r
394
422
}
395
423
396
424
#[ inline( always) ]
397
425
pub unsafe fn __psplim_w ( val : u32 ) {
398
- asm ! ( "msr PSPLIM, {}" , in( reg) val) ;
426
+ asm ! ( "msr PSPLIM, {}" , in( reg) val, options ( nomem , nostack , preserves_flags ) ) ;
399
427
}
400
428
}
401
429
@@ -409,12 +437,12 @@ mod fpu {
409
437
#[ inline( always) ]
410
438
pub unsafe fn __fpscr_r ( ) -> u32 {
411
439
let r;
412
- asm ! ( "vmrs {}, fpscr" , out( reg) r) ;
440
+ asm ! ( "vmrs {}, fpscr" , out( reg) r, options ( nomem , nostack , preserves_flags ) ) ;
413
441
r
414
442
}
415
443
416
444
#[ inline( always) ]
417
445
pub unsafe fn __fpscr_w ( val : u32 ) {
418
- asm ! ( "vmsr fpscr, {}" , in( reg) val) ;
446
+ asm ! ( "vmsr fpscr, {}" , in( reg) val, options ( nomem , nostack ) ) ;
419
447
}
420
448
}
0 commit comments