diff --git a/llvm/lib/Target/AVR/AVRCallingConv.td b/llvm/lib/Target/AVR/AVRCallingConv.td --- a/llvm/lib/Target/AVR/AVRCallingConv.td +++ b/llvm/lib/Target/AVR/AVRCallingConv.td @@ -38,4 +38,4 @@ //===----------------------------------------------------------------------===// def CSR_Normal : CalleeSavedRegs<(add R29, R28, (sequence "R%u", 17, 2))>; -def CSR_Interrupts : CalleeSavedRegs<(add (sequence "R%u", 31, 0))>; +def CSR_Interrupts : CalleeSavedRegs<(add (sequence "R%u", 31, 2))>; diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp --- a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp +++ b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp @@ -45,11 +45,7 @@ const uint32_t * AVRRegisterInfo::getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const { - const AVRMachineFunctionInfo *AFI = MF.getInfo(); - - return AFI->isInterruptOrSignalHandler() - ? CSR_Interrupts_RegMask - : CSR_Normal_RegMask; + return CSR_Normal_RegMask; } BitVector AVRRegisterInfo::getReservedRegs(const MachineFunction &MF) const { diff --git a/llvm/test/CodeGen/AVR/interrupts.ll b/llvm/test/CodeGen/AVR/interrupts.ll --- a/llvm/test/CodeGen/AVR/interrupts.ll +++ b/llvm/test/CodeGen/AVR/interrupts.ll @@ -1,5 +1,7 @@ ; RUN: llc < %s -march=avr | FileCheck %s +@count = global i8 0 + define avr_intrcc void @interrupt_handler() { ; CHECK-LABEL: interrupt_handler: ; CHECK: sei @@ -104,5 +106,75 @@ ret void } +define void @signal_handler_with_increment() #1 { +; CHECK-LABEL: signal_handler_with_increment: +; CHECK: push r0 +; CHECK-NEXT: push r1 +; CHECK-NEXT: in r0, 63 +; CHECK-NEXT: push r0 +; CHECK: clr r0 +; CHECK-NEXT: clr r1 +; CHECK-NEXT: push r24 +; CHECK-NEXT: lds r24, count +; CHECK-NEXT: inc r24 +; CHECK-NEXT: sts count, r24 +; CHECK-NEXT: pop r24 +; CHECK: pop r0 +; CHECK-NEXT: out 63, r0 +; CHECK-NEXT: pop r1 +; CHECK-NEXT: pop r0 +; CHECK-NEXT: reti + %old = load volatile i8, i8* @count + %new = add i8 %old, 1 + store volatile i8 %new, i8* @count + ret void +} + +declare void @foo() + +; When a signal handler calls a function, it must push/pop all call clobbered +; registers. +define void @signal_handler_with_call() #1 { +; CHECK-LABEL: signal_handler_with_call: +; CHECK: push r0 +; CHECK-NEXT: push r1 +; CHECK-NEXT: in r0, 63 +; CHECK-NEXT: push r0 +; CHECK: clr r0 +; CHECK-NEXT: clr r1 +; CHECK: push r18 +; CHECK-NEXT: push r19 +; CHECK-NEXT: push r20 +; CHECK-NEXT: push r21 +; CHECK-NEXT: push r22 +; CHECK-NEXT: push r23 +; CHECK-NEXT: push r24 +; CHECK-NEXT: push r25 +; CHECK-NEXT: push r26 +; CHECK-NEXT: push r27 +; CHECK-NEXT: push r30 +; CHECK-NEXT: push r31 +; CHECK-NEXT: call foo +; CHECK-NEXT: pop r31 +; CHECK-NEXT: pop r30 +; CHECK-NEXT: pop r27 +; CHECK-NEXT: pop r26 +; CHECK-NEXT: pop r25 +; CHECK-NEXT: pop r24 +; CHECK-NEXT: pop r23 +; CHECK-NEXT: pop r22 +; CHECK-NEXT: pop r21 +; CHECK-NEXT: pop r20 +; CHECK-NEXT: pop r19 +; CHECK-NEXT: pop r18 +; CHECK: pop r0 +; CHECK-NEXT: out 63, r0 +; CHECK-NEXT: pop r1 +; CHECK-NEXT: pop r0 +; CHECK-NEXT: reti + call void @foo() + ret void +} + attributes #0 = { "interrupt" } attributes #1 = { "signal" }