@@ -150,6 +150,7 @@ class MipsAsmParser : public MCTargetAsmParser {
150150 bool IsLittleEndian;
151151 bool IsPicEnabled;
152152 bool IsCpRestoreSet;
153+ bool CurForbiddenSlotAttr;
153154 int CpRestoreOffset;
154155 unsigned GPReg;
155156 unsigned CpSaveLocation;
@@ -552,6 +553,7 @@ class MipsAsmParser : public MCTargetAsmParser {
552553
553554 CurrentFn = nullptr ;
554555
556+ CurForbiddenSlotAttr = false ;
555557 IsPicEnabled = getContext ().getObjectFileInfo ()->isPositionIndependent ();
556558
557559 IsCpRestoreSet = false ;
@@ -723,6 +725,16 @@ class MipsAsmParser : public MCTargetAsmParser {
723725 return getSTI ().hasFeature (Mips::FeatureGINV);
724726 }
725727
728+ bool hasForbiddenSlot (const MCInstrDesc &MCID) const {
729+ return !inMicroMipsMode () && (MCID.TSFlags & MipsII::HasForbiddenSlot);
730+ }
731+
732+ bool SafeInForbiddenSlot (const MCInstrDesc &MCID) const {
733+ return !(MCID.TSFlags & MipsII::IsCTI);
734+ }
735+
736+ void onEndOfFile () override ;
737+
726738 // / Warn if RegIndex is the same as the current AT.
727739 void warnIfRegIndexIsAT (unsigned RegIndex, SMLoc Loc);
728740
@@ -2307,7 +2319,42 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23072319
23082320 bool FillDelaySlot =
23092321 MCID.hasDelaySlot () && AssemblerOptions.back ()->isReorder ();
2310- if (FillDelaySlot)
2322+
2323+ // Get previous instruction`s forbidden slot attribute and
2324+ // whether set reorder.
2325+ // This 'CurForbiddenSlotAttr' is a global variable.
2326+ bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;
2327+
2328+ // Flag represents we set reorder after nop.
2329+ bool SetReorderAfterNop = false ;
2330+
2331+ // If previous instruction has forbidden slot and .set reorder
2332+ // is active and current instruction is CTI.
2333+ // Then emit a NOP after it.
2334+ if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot (MCID)) {
2335+ TOut.emitEmptyDelaySlot (false , IDLoc, STI);
2336+ // When 'FillDelaySlot' is true, the existing logic will add
2337+ // noreorder before instruction and reorder after it. So there
2338+ // need exclude this case avoiding two '.set reorder'.
2339+ // The format of the first case is:
2340+ // .set noreorder
2341+ // bnezc
2342+ // nop
2343+ // .set reorder
2344+ if (AssemblerOptions.back ()->isReorder () && !FillDelaySlot) {
2345+ SetReorderAfterNop = true ;
2346+ TOut.emitDirectiveSetReorder ();
2347+ }
2348+ }
2349+
2350+ // Save current instruction`s forbidden slot and whether set reorder.
2351+ // This is the judgment condition for whether to add nop.
2352+ // We would add a couple of '.set noreorder' and '.set reorder' to
2353+ // wrap the current instruction and the next instruction.
2354+ CurForbiddenSlotAttr =
2355+ hasForbiddenSlot (MCID) && AssemblerOptions.back ()->isReorder ();
2356+
2357+ if (FillDelaySlot || CurForbiddenSlotAttr)
23112358 TOut.emitDirectiveSetNoReorder ();
23122359
23132360 MacroExpanderResultTy ExpandResult =
@@ -2322,6 +2369,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23222369 return true ;
23232370 }
23242371
2372+ // When current instruction was not CTI, recover reorder state.
2373+ // The format of the second case is:
2374+ // .set noreoder
2375+ // bnezc
2376+ // add
2377+ // .set reorder
2378+ if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&
2379+ AssemblerOptions.back ()->isReorder ()) {
2380+ TOut.emitDirectiveSetReorder ();
2381+ }
2382+
23252383 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
23262384 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
23272385 if (inMicroMipsMode ()) {
@@ -2331,6 +2389,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23312389
23322390 // If this instruction has a delay slot and .set reorder is active,
23332391 // emit a NOP after it.
2392+ // The format of the third case is:
2393+ // .set noreorder
2394+ // bnezc
2395+ // nop
2396+ // .set noreorder
2397+ // j
2398+ // nop
2399+ // .set reorder
23342400 if (FillDelaySlot) {
23352401 TOut.emitEmptyDelaySlot (hasShortDelaySlot (Inst), IDLoc, STI);
23362402 TOut.emitDirectiveSetReorder ();
@@ -2356,6 +2422,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23562422 return false ;
23572423}
23582424
2425+ void MipsAsmParser::onEndOfFile () {
2426+ MipsTargetStreamer &TOut = getTargetStreamer ();
2427+ SMLoc IDLoc = SMLoc ();
2428+ // If has pending forbidden slot, fill nop and recover reorder.
2429+ if (CurForbiddenSlotAttr) {
2430+ TOut.emitEmptyDelaySlot (false , IDLoc, STI);
2431+ if (AssemblerOptions.back ()->isReorder ())
2432+ TOut.emitDirectiveSetReorder ();
2433+ }
2434+ }
2435+
23592436MipsAsmParser::MacroExpanderResultTy
23602437MipsAsmParser::tryExpandInstruction (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
23612438 const MCSubtargetInfo *STI) {
0 commit comments