74
74
//!
75
75
//! ```rust
76
76
//! #[unsafe(no_mangle)]
77
- //! extern "C" fn _undefined_handler(faulting_instruction: u32 );
77
+ //! extern "C" fn _undefined_handler(addr: usize );
78
78
//! ```
79
79
//!
80
80
//! * `_abort_handler` - an `extern "C"` function to call when a Data Abort Exception
86
86
//!
87
87
//! ```rust
88
88
//! #[unsafe(no_mangle)]
89
- //! extern "C" fn _abort_handler(faulting_instruction: u32 );
89
+ //! extern "C" fn _abort_handler(addr: usize );
90
90
//! ```
91
91
//!
92
92
//! * `_prefetch_handler` - an `extern "C"` function to call when a Prefetch Abort Exception
98
98
//!
99
99
//! ```rust
100
100
//! #[unsafe(no_mangle)]
101
- //! extern "C" fn _prefetch_handler(faulting_instruction: u32 );
101
+ //! extern "C" fn _prefetch_handler(addr: usize );
102
102
//! ```
103
103
//!
104
104
//! ### ASM functions
113
113
//! * `_asm_undefined_handler` - a naked function to call when an Undefined
114
114
//! Exception occurs. Our linker script PROVIDEs a default function at
115
115
//! `_asm_default_undefined_handler` but you can override it.
116
- //! * `_asm_prefetch_handler` - a naked function to call when an Prefetch
116
+ //! * `_asm_prefetch_handler` - a naked function to call when a Prefetch
117
117
//! Exception occurs. Our linker script PROVIDEs a default function at
118
118
//! `_asm_default_prefetch_handler` but you can override it. The provided default
119
119
//! handler will perform an exception return to the faulting address.
@@ -313,7 +313,7 @@ core::arch::global_asm!(
313
313
314
314
// Called from the vector table when we have an software interrupt.
315
315
// Saves state and calls a C-compatible handler like
316
- // `extern "C" fn svc_handler(svc: u32, context: *const u32 );`
316
+ // `extern "C" fn svc_handler(svc: u32);`
317
317
.global _asm_svc_handler
318
318
.type _asm_svc_handler, %function
319
319
_asm_svc_handler:
@@ -335,6 +335,7 @@ core::arch::global_asm!(
335
335
rfefd sp!
336
336
.size _asm_svc_handler, . - _asm_svc_handler
337
337
338
+
338
339
// Called from the vector table when we have an interrupt.
339
340
// Saves state and calls a C-compatible handler like
340
341
// `extern "C" fn irq_handler();`
@@ -357,56 +358,64 @@ core::arch::global_asm!(
357
358
358
359
// Called from the vector table when we have an undefined exception.
359
360
// Saves state and calls a C-compatible handler like
360
- // `extern "C" fn _undefined_handler();`
361
+ // `extern "C" fn _undefined_handler(addr: usize );`
361
362
.global _asm_default_undefined_handler
362
363
.type _asm_default_undefined_handler, %function
363
364
_asm_default_undefined_handler:
364
- // First adjust LR for two purposes: Passing the faulting instruction to the C handler,
365
- // and to return to the failing instruction after the C handler returns.
366
- // Load processor status
367
- mrs r4, cpsr
368
- // Occurred in Thumb state?
369
- tst r4, {t_bit}
370
- // If not in Thumb mode, branch to not_thumb
371
- beq not_thumb
372
- subs lr, lr, #2
373
- b done
374
- not_thumb:
375
- // Subtract 4 from LR (ARM mode)
376
- subs lr, lr, #4
377
- done:
378
365
// state save from compiled code
379
366
srsfd sp!, {und_mode}
367
+ // to work out what mode we're in, we need R0
368
+ push {{r0}}
369
+ // First adjust LR for two purposes: Passing the faulting instruction to the C handler,
370
+ // and to return to the failing instruction after the C handler returns.
371
+ // Load processor status for the calling code
372
+ mrs r0, spsr
373
+ // Was the code that triggered the exception in Thumb state?
374
+ tst r0, {t_bit}
375
+ // Subtract 2 in Thumb Mode, 4 in Arm Mode - see p.1206 of the ARMv7-A architecture manual.
376
+ ite eq
377
+ subeq lr, lr, #4
378
+ subne lr, lr, #2
379
+ // save the newly computed LR
380
+ push {{lr}}
381
+ // now do our standard exception save
380
382
"# ,
381
383
save_context!( ) ,
382
384
r#"
383
385
// Pass the faulting instruction address to the handler.
384
386
mov r0, lr
385
387
// call C handler
386
388
bl _undefined_handler
389
+ // do our standard restore
387
390
"# ,
388
391
restore_context!( ) ,
389
392
r#"
393
+ // get our saved LR
394
+ pop {{lr}}
395
+ // get our real saved R0
396
+ pop {{r0}}
397
+ // overwrite the saved LR with the adjusted one
398
+ str lr, [sp]
390
399
// Return to the failing instruction which is the recommended approach by ARM.
391
400
rfefd sp!
392
401
.size _asm_default_undefined_handler, . - _asm_default_undefined_handler
393
402
394
403
395
- // Called from the vector table when we have an undefined exception.
404
+ // Called from the vector table when we have a prefetch exception.
396
405
// Saves state and calls a C-compatible handler like
397
- // `extern "C" fn _prefetch_handler();`
406
+ // `extern "C" fn _prefetch_handler(addr: usize );`
398
407
.global _asm_default_prefetch_handler
399
408
.type _asm_default_prefetch_handler, %function
400
409
_asm_default_prefetch_handler:
401
410
// Subtract 4 from the stored LR, see p.1212 of the ARMv7-A architecture manual.
402
- subs lr, lr, #4
411
+ subs lr, lr, #4
403
412
// state save from compiled code
404
413
srsfd sp!, {abt_mode}
405
414
"# ,
406
415
save_context!( ) ,
407
416
r#"
408
417
// Pass the faulting instruction address to the handler.
409
- mov r0, lr
418
+ mov r0, lr
410
419
// call C handler
411
420
bl _prefetch_handler
412
421
"# ,
@@ -419,12 +428,12 @@ done:
419
428
420
429
// Called from the vector table when we have an undefined exception.
421
430
// Saves state and calls a C-compatible handler like
422
- // `extern "C" fn _abort_handler();`
431
+ // `extern "C" fn _abort_handler(addr: usize );`
423
432
.global _asm_default_abort_handler
424
433
.type _asm_default_abort_handler, %function
425
434
_asm_default_abort_handler:
426
435
// Subtract 8 from the stored LR, see p.1214 of the ARMv7-A architecture manual.
427
- subs lr, lr, #8
436
+ subs lr, lr, #8
428
437
// state save from compiled code
429
438
srsfd sp!, {abt_mode}
430
439
"# ,
0 commit comments