mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
fb68d2c9e8
This patch fixes a corruption of the stack pointer and several registers in any AVR interrupt with non-empty stack frame. Previously, the callee-saved registers were popped before restoring the stack pointer, causing the pointer math to use the wrong base value while also corrupting the caller's register. This change fixes the code to restore the stack pointer last before exiting the interrupt service routine. https://bugs.llvm.org/show_bug.cgi?id=47253 Reviewed By: dylanmckay Differential Revision: https://reviews.llvm.org/D87735 Patch by Andrew Dona-Couch.
104 lines
2.1 KiB
LLVM
104 lines
2.1 KiB
LLVM
; RUN: llc < %s -march=avr | FileCheck %s
|
|
|
|
define avr_intrcc void @interrupt_handler() {
|
|
; CHECK-LABEL: interrupt_handler:
|
|
; CHECK: sei
|
|
; CHECK-NEXT: push r0
|
|
; CHECK-NEXT: push r1
|
|
; CHECK-NEXT: in r0, 63
|
|
; CHECK-NEXT: push r0
|
|
; CHECK: clr r0
|
|
; CHECK: pop r0
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: pop r1
|
|
; CHECK-NEXT: pop r0
|
|
; CHECK-NEXT: reti
|
|
ret void
|
|
}
|
|
|
|
define void @interrupt_handler_via_ir_attribute() #0 {
|
|
; CHECK-LABEL: interrupt_handler_via_ir_attribute:
|
|
; CHECK: sei
|
|
; CHECK-NEXT: push r0
|
|
; CHECK-NEXT: push r1
|
|
; CHECK-NEXT: in r0, 63
|
|
; CHECK-NEXT: push r0
|
|
; CHECK: clr r0
|
|
; CHECK: pop r0
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: pop r1
|
|
; CHECK-NEXT: pop r0
|
|
; CHECK-NEXT: reti
|
|
ret void
|
|
}
|
|
|
|
define avr_signalcc void @signal_handler() {
|
|
; CHECK-LABEL: signal_handler:
|
|
; CHECK-NOT: sei
|
|
; CHECK: push r0
|
|
; CHECK-NEXT: push r1
|
|
; CHECK-NEXT: in r0, 63
|
|
; CHECK-NEXT: push r0
|
|
; CHECK: clr r0
|
|
; CHECK: pop r0
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: pop r1
|
|
; CHECK-NEXT: pop r0
|
|
; CHECK-NEXT: reti
|
|
ret void
|
|
}
|
|
|
|
define void @signal_handler_via_attribute() #1 {
|
|
; CHECK-LABEL: signal_handler_via_attribute:
|
|
; CHECK-NOT: sei
|
|
; CHECK: push r0
|
|
; CHECK-NEXT: push r1
|
|
; CHECK-NEXT: in r0, 63
|
|
; CHECK-NEXT: push r0
|
|
; CHECK: clr r0
|
|
; CHECK: pop r0
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: pop r1
|
|
; CHECK-NEXT: pop r0
|
|
; CHECK-NEXT: reti
|
|
ret void
|
|
}
|
|
|
|
define avr_intrcc void @interrupt_alloca() {
|
|
; CHECK-LABEL: interrupt_alloca:
|
|
; CHECK: sei
|
|
; CHECK-NEXT: push r0
|
|
; CHECK-NEXT: push r1
|
|
; CHECK-NEXT: in r0, 63
|
|
; CHECK-NEXT: push r0
|
|
; CHECK: clr r0
|
|
; CHECK: push r28
|
|
; CHECK-NEXT: push r29
|
|
; CHECK-NEXT: in r28, 61
|
|
; CHECK-NEXT: in r29, 62
|
|
; CHECK-NEXT: sbiw r28, 1
|
|
; CHECK-NEXT: in r0, 63
|
|
; CHECK-NEXT: cli
|
|
; CHECK-NEXT: out 62, r29
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: out 61, r28
|
|
; CHECK: adiw r28, 1
|
|
; CHECK-NEXT: in r0, 63
|
|
; CHECK-NEXT: cli
|
|
; CHECK-NEXT: out 62, r29
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: out 61, r28
|
|
; CHECK-NEXT: pop r29
|
|
; CHECK-NEXT: pop r28
|
|
; CHECK: pop r0
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: pop r1
|
|
; CHECK-NEXT: pop r0
|
|
; CHECK-NEXT: reti
|
|
alloca i8
|
|
ret void
|
|
}
|
|
|
|
attributes #0 = { "interrupt" }
|
|
attributes #1 = { "signal" }
|