@@ -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,41 @@ 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+ bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;
2326+
2327+ // Flag represents we set reorder after nop.
2328+ bool SetReorderAfterNop = false ;
2329+
2330+ // If previous instruction has forbidden slot and .set reorder
2331+ // is active and current instruction is CTI.
2332+ // Then emit a NOP after it.
2333+ if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot (MCID)) {
2334+ TOut.emitEmptyDelaySlot (false , IDLoc, STI);
2335+ // When 'FillDelaySlot' is true, the existing logic will add
2336+ // noreorder before instruction and reorder after it. So there
2337+ // need exclude this case avoiding two '.set reorder'.
2338+ // The format of the first case is:
2339+ // .set noreorder
2340+ // bnezc
2341+ // nop
2342+ // .set reorder
2343+ if (AssemblerOptions.back ()->isReorder () && !FillDelaySlot) {
2344+ SetReorderAfterNop = true ;
2345+ TOut.emitDirectiveSetReorder ();
2346+ }
2347+ }
2348+
2349+ // Save current instruction`s forbidden slot and whether set reorder.
2350+ // This is the judgment condition for whether to add nop.
2351+ // We would add a couple of '.set noreorder' and '.set reorder' to
2352+ // wrap the current instruction and the next instruction.
2353+ CurForbiddenSlotAttr =
2354+ hasForbiddenSlot (MCID) && AssemblerOptions.back ()->isReorder ();
2355+
2356+ if (FillDelaySlot || CurForbiddenSlotAttr)
23112357 TOut.emitDirectiveSetNoReorder ();
23122358
23132359 MacroExpanderResultTy ExpandResult =
@@ -2322,6 +2368,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23222368 return true ;
23232369 }
23242370
2371+ // When current instruction was not CTI, recover reorder state.
2372+ // The format of the second case is:
2373+ // .set noreoder
2374+ // bnezc
2375+ // add
2376+ // .set reorder
2377+ if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&
2378+ AssemblerOptions.back ()->isReorder ()) {
2379+ TOut.emitDirectiveSetReorder ();
2380+ }
2381+
23252382 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
23262383 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
23272384 if (inMicroMipsMode ()) {
@@ -2331,6 +2388,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23312388
23322389 // If this instruction has a delay slot and .set reorder is active,
23332390 // emit a NOP after it.
2391+ // The format of the third case is:
2392+ // .set noreorder
2393+ // bnezc
2394+ // nop
2395+ // .set noreorder
2396+ // j
2397+ // nop
2398+ // .set reorder
23342399 if (FillDelaySlot) {
23352400 TOut.emitEmptyDelaySlot (hasShortDelaySlot (Inst), IDLoc, STI);
23362401 TOut.emitDirectiveSetReorder ();
@@ -2356,6 +2421,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23562421 return false ;
23572422}
23582423
2424+ void MipsAsmParser::onEndOfFile () {
2425+ MipsTargetStreamer &TOut = getTargetStreamer ();
2426+ SMLoc IDLoc = SMLoc ();
2427+ // If has pending forbidden slot, fill nop and recover reorder.
2428+ if (CurForbiddenSlotAttr) {
2429+ TOut.emitEmptyDelaySlot (false , IDLoc, STI);
2430+ if (AssemblerOptions.back ()->isReorder ())
2431+ TOut.emitDirectiveSetReorder ();
2432+ }
2433+ }
2434+
23592435MipsAsmParser::MacroExpanderResultTy
23602436MipsAsmParser::tryExpandInstruction (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
23612437 const MCSubtargetInfo *STI) {
0 commit comments