mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[AVR] Generalize the previous interrupt bugfix to signal handlers too
This commit is contained in:
parent
7132783865
commit
dd0d79a2a1
@ -60,7 +60,7 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
|
||||
bool HasFP = hasFP(MF);
|
||||
|
||||
// Interrupt handlers re-enable interrupts in function entry.
|
||||
if (AFI->isInterruptHandler() && CallConv != CallingConv::AVR_SIGNAL) {
|
||||
if (AFI->isInterruptHandler()) {
|
||||
BuildMI(MBB, MBBI, DL, TII.get(AVR::BSETs))
|
||||
.addImm(0x07)
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
@ -75,7 +75,7 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
|
||||
|
||||
// Emit special prologue code to save R1, R0 and SREG in interrupt/signal
|
||||
// handlers before saving any other registers.
|
||||
if (AFI->isInterruptHandler()) {
|
||||
if (AFI->isInterruptOrSignalHandler()) {
|
||||
BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
|
||||
.addReg(AVR::R1R0, RegState::Kill)
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
@ -145,7 +145,7 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
|
||||
// Early exit if the frame pointer is not needed in this function except for
|
||||
// signal/interrupt handlers where special code generation is required.
|
||||
if (!hasFP(MF) && !AFI->isInterruptHandler()) {
|
||||
if (!hasFP(MF) && !AFI->isInterruptOrSignalHandler()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
|
||||
// Emit special epilogue code to restore R1, R0 and SREG in interrupt/signal
|
||||
// handlers at the very end of the function, just before reti.
|
||||
if (AFI->isInterruptHandler()) {
|
||||
if (AFI->isInterruptOrSignalHandler()) {
|
||||
BuildMI(MBB, MBBI, DL, TII.get(AVR::POPRd), AVR::R0);
|
||||
BuildMI(MBB, MBBI, DL, TII.get(AVR::OUTARr))
|
||||
.addImm(0x3f)
|
||||
|
@ -1432,7 +1432,7 @@ AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
|
||||
const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
|
||||
|
||||
unsigned RetOpc =
|
||||
AFI->isInterruptHandler()
|
||||
AFI->isInterruptOrSignalHandler()
|
||||
? AVRISD::RETI_FLAG
|
||||
: AVRISD::RET_FLAG;
|
||||
|
||||
|
@ -34,6 +34,9 @@ class AVRMachineFunctionInfo : public MachineFunctionInfo {
|
||||
/// Whether or not the function is an interrupt handler.
|
||||
bool IsInterruptHandler;
|
||||
|
||||
/// Whether or not the function is an non-blocking interrupt handler.
|
||||
bool IsSignalHandler;
|
||||
|
||||
/// Size of the callee-saved register portion of the
|
||||
/// stack frame in bytes.
|
||||
unsigned CalleeSavedFrameSize;
|
||||
@ -44,18 +47,16 @@ class AVRMachineFunctionInfo : public MachineFunctionInfo {
|
||||
public:
|
||||
AVRMachineFunctionInfo()
|
||||
: HasSpills(false), HasAllocas(false), HasStackArgs(false),
|
||||
IsInterruptHandler(false), CalleeSavedFrameSize(0),
|
||||
VarArgsFrameIndex(0) {}
|
||||
IsInterruptHandler(false), IsSignalHandler(false),
|
||||
CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {}
|
||||
|
||||
explicit AVRMachineFunctionInfo(MachineFunction &MF)
|
||||
: HasSpills(false), HasAllocas(false), HasStackArgs(false),
|
||||
CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {
|
||||
unsigned CallConv = MF.getFunction().getCallingConv();
|
||||
|
||||
this->IsInterruptHandler =
|
||||
CallConv == CallingConv::AVR_INTR ||
|
||||
CallConv == CallingConv::AVR_SIGNAL ||
|
||||
MF.getFunction().hasFnAttribute("interrupt");
|
||||
this->IsInterruptHandler = CallConv == CallingConv::AVR_INTR || MF.getFunction().hasFnAttribute("interrupt");
|
||||
this->IsSignalHandler = CallConv == CallingConv::AVR_SIGNAL || MF.getFunction().hasFnAttribute("signal");
|
||||
}
|
||||
|
||||
bool getHasSpills() const { return HasSpills; }
|
||||
@ -67,7 +68,11 @@ public:
|
||||
bool getHasStackArgs() const { return HasStackArgs; }
|
||||
void setHasStackArgs(bool B) { HasStackArgs = B; }
|
||||
|
||||
/// Checks if the function is some form of interrupt service routine.
|
||||
bool isInterruptOrSignalHandler() const { return isInterruptHandler() || isSignalHandler(); }
|
||||
|
||||
bool isInterruptHandler() const { return IsInterruptHandler; }
|
||||
bool isSignalHandler() const { return IsSignalHandler; }
|
||||
|
||||
unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
|
||||
void setCalleeSavedFrameSize(unsigned Bytes) { CalleeSavedFrameSize = Bytes; }
|
||||
|
@ -37,7 +37,7 @@ const uint16_t *
|
||||
AVRRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
const AVRMachineFunctionInfo *AFI = MF->getInfo<AVRMachineFunctionInfo>();
|
||||
|
||||
return AFI->isInterruptHandler()
|
||||
return AFI->isInterruptOrSignalHandler()
|
||||
? CSR_Interrupts_SaveList
|
||||
: CSR_Normal_SaveList;
|
||||
}
|
||||
@ -47,7 +47,7 @@ AVRRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
|
||||
CallingConv::ID CC) const {
|
||||
const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
|
||||
|
||||
return AFI->isInterruptHandler()
|
||||
return AFI->isInterruptOrSignalHandler()
|
||||
? CSR_Interrupts_RegMask
|
||||
: CSR_Normal_RegMask;
|
||||
}
|
||||
|
@ -48,5 +48,21 @@ define avr_signalcc void @signal_handler() {
|
||||
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
|
||||
}
|
||||
|
||||
attributes #0 = { "interrupt" }
|
||||
attributes #1 = { "signal" }
|
||||
|
Loading…
Reference in New Issue
Block a user