void MipsSEFrameLowering::emitInterruptEpilogueStub( MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Perform ISR handling like GCC const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; // Disable Interrupts. BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::DI), Mips::ZERO); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EHB)); // Restore EPC STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, Mips::K1, MipsFI->getISRRegFI(0), PtrRC, STI.getRegisterInfo()); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP014) .addReg(Mips::K1) .addImm(0); // Restore Status STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, Mips::K1, MipsFI->getISRRegFI(1), PtrRC, STI.getRegisterInfo()); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012) .addReg(Mips::K1) .addImm(0); }
void MipsSEFrameLowering::emitInterruptPrologueStub( MachineFunction &MF, MachineBasicBlock &MBB) const { MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Report an error the target doesn't support Mips32r2 or later. // The epilogue relies on the use of the "ehb" to clear execution // hazards. Pre R2 Mips relies on an implementation defined number // of "ssnop"s to clear the execution hazard. Support for ssnop hazard // clearing is not provided so reject that configuration. if (!STI.hasMips32r2()) report_fatal_error( "\"interrupt\" attribute is not supported on pre-MIPS32R2 or " "MIPS16 targets."); // The GP register contains the "user" value, so we cannot perform // any gp relative loads until we restore the "kernel" or "system" gp // value. Until support is written we shall only accept the static // relocation model. if ((STI.getRelocationModel() != Reloc::Static)) report_fatal_error("\"interrupt\" attribute is only supported for the " "static relocation model on MIPS at the present time."); if (!STI.isABI_O32() || STI.hasMips64()) report_fatal_error("\"interrupt\" attribute is only supported for the " "O32 ABI on MIPS32R2+ at the present time."); // Perform ISR handling like GCC StringRef IntKind = MF.getFunction()->getFnAttribute("interrupt").getValueAsString(); const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; // EIC interrupt handling needs to read the Cause register to disable // interrupts. if (IntKind == "eic") { // Coprocessor registers are always live per se. MBB.addLiveIn(Mips::COP013); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K0) .addReg(Mips::COP013) .addImm(0) .setMIFlag(MachineInstr::FrameSetup); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EXT), Mips::K0) .addReg(Mips::K0) .addImm(10) .addImm(6) .setMIFlag(MachineInstr::FrameSetup); } // Fetch and spill EPC MBB.addLiveIn(Mips::COP014); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1) .addReg(Mips::COP014) .addImm(0) .setMIFlag(MachineInstr::FrameSetup); STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false, MipsFI->getISRRegFI(0), PtrRC, STI.getRegisterInfo(), 0); // Fetch and Spill Status MBB.addLiveIn(Mips::COP012); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1) .addReg(Mips::COP012) .addImm(0) .setMIFlag(MachineInstr::FrameSetup); STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false, MipsFI->getISRRegFI(1), PtrRC, STI.getRegisterInfo(), 0); // Build the configuration for disabling lower priority interrupts. Non EIC // interrupts need to be masked off with zero, EIC from the Cause register. unsigned InsPosition = 8; unsigned InsSize = 0; unsigned SrcReg = Mips::ZERO; // If the interrupt we're tied to is the EIC, switch the source for the // masking off interrupts to the cause register. if (IntKind == "eic") { SrcReg = Mips::K0; InsPosition = 10; InsSize = 6; } else InsSize = StringSwitch<unsigned>(IntKind) .Case("sw0", 1) .Case("sw1", 2) .Case("hw0", 3) .Case("hw1", 4) .Case("hw2", 5) .Case("hw3", 6) .Case("hw4", 7) .Case("hw5", 8) .Default(0); assert(InsSize != 0 && "Unknown interrupt type!"); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1) .addReg(SrcReg) .addImm(InsPosition) .addImm(InsSize) .addReg(Mips::K1) .setMIFlag(MachineInstr::FrameSetup); // Mask off KSU, ERL, EXL BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1) .addReg(Mips::ZERO) .addImm(1) .addImm(4) .addReg(Mips::K1) .setMIFlag(MachineInstr::FrameSetup); // Disable the FPU as we are not spilling those register sets. if (!STI.useSoftFloat()) BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1) .addReg(Mips::ZERO) .addImm(29) .addImm(1) .addReg(Mips::K1) .setMIFlag(MachineInstr::FrameSetup); // Set the new status BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012) .addReg(Mips::K1) .addImm(0) .setMIFlag(MachineInstr::FrameSetup); }