@@ -72,6 +72,11 @@ using namespace llvm;
7272
7373extern cl::opt<bool > EmitJalrReloc;
7474
75+ cl::opt<bool >
76+ FixHw110880 (" nmips-fix-hw110880" , cl::Hidden,
77+ cl::desc (" nanoMIPS: Fix problematic instructions to avoid hw110880 issue" ),
78+ cl::init(true ));
79+
7580void MipsAsmPrinter::emitJumpTableInfo () {
7681 if (!Subtarget->hasNanoMips () || Subtarget->useAbsoluteJumpTables () ) {
7782 AsmPrinter::emitJumpTableInfo ();
@@ -249,6 +254,56 @@ void MipsAsmPrinter::emitJumpTableDest(MCStreamer &OutStreamer,
249254 EmitToStreamer (OutStreamer, LoadI);
250255}
251256
257+ bool MipsAsmPrinter::tryEmitHw110880Fix (MCStreamer &OutStreamer,
258+ const MachineInstr *MI) {
259+ if (!FixHw110880)
260+ return false ;
261+
262+ if (!Subtarget->hasFixHw110880 ())
263+ return false ;
264+
265+ if (MI->getOpcode () != Mips::Li_NM &&
266+ MI->getOpcode () != Mips::ADDIU48_NM)
267+ return false ;
268+
269+ int LastOp = MI->getNumOperands () - 1 ;
270+ auto Last = MI->getOperand (LastOp);
271+
272+ if (!Last.isImm ())
273+ return false ;
274+
275+ int64_t Value = Last.getImm ();
276+
277+ auto ImmValueNeedsHw110880Fix = [MI](int64_t Value) -> bool {
278+ // Check if we are dealing with 48-bit LI
279+ if ((MI->getOpcode () == Mips::Li_NM) &&
280+ (isUInt<16 >(Value) || isInt<9 >(Value) || ((Value & 0xfffu ) == 0u )))
281+ return false ;
282+
283+ return (((Value & 0x50016400 ) == 0x50012400 ) &&
284+ (((Value >> 24 ) & 0x7 ) == 0x1 || ((Value >> 24 ) & 0x2 ) == 0x2 ));
285+ };
286+
287+ if (!ImmValueNeedsHw110880Fix (Value))
288+ return false ;
289+
290+ MCSymbol *AbsZero = OutContext.getOrCreateSymbol (
291+ Twine (getDataLayout ().getPrivateGlobalPrefix ()) +
292+ Twine (" zero" ));
293+
294+ const MCExpr *ZeroRef = MCSymbolRefExpr::create (AbsZero, OutContext);
295+ const MCExpr *ValueExpr = MCBinaryExpr::createAdd (
296+ ZeroRef, MCConstantExpr::create (Value, OutContext, true , 4u ), OutContext);
297+
298+ MCInst Load;
299+ Load.setOpcode (MI->getOpcode ());
300+ for (int i = 0 ; i < LastOp; i++)
301+ Load.addOperand (MCOperand::createReg (MI->getOperand (i).getReg ()));
302+ Load.addOperand (MCOperand::createExpr (ValueExpr));
303+ EmitToStreamer (OutStreamer, Load);
304+ return true ;
305+ }
306+
252307// Each table starts with the following directive:
253308//
254309// .jumptable esize, nsize [, unsigned]
@@ -417,6 +472,12 @@ void MipsAsmPrinter::emitInstruction(const MachineInstr *MI) {
417472 continue ;
418473 }
419474
475+ if (Subtarget->hasNanoMips () &&
476+ tryEmitHw110880Fix (*OutStreamer, &*I)) {
477+ continue ;
478+ }
479+
480+
420481 if (Subtarget->hasNanoMips () &&
421482 (I->getOpcode () == Mips::LoadJumpTableOffset)) {
422483 emitJumpTableDest (*OutStreamer, &*I);
@@ -1294,6 +1355,20 @@ void MipsAsmPrinter::EmitFPCallStub(
12941355}
12951356
12961357void MipsAsmPrinter::emitEndOfAsmFile (Module &M) {
1358+ if (Subtarget->hasNanoMips () && FixHw110880) {
1359+ SmallString<8 > Name;
1360+ auto Symbols = OutContext.getSymbols ();
1361+ MCSymbol *AbsZero = Symbols.lookup (
1362+ (Twine (getDataLayout ().getPrivateGlobalPrefix ()) + Twine (" zero" ))
1363+ .toStringRef (Name));
1364+
1365+ if (AbsZero) {
1366+ assert (!AbsZero->isDefined ());
1367+ // Force assembler to use relocations via weak symbol
1368+ OutStreamer->emitSymbolAttribute (AbsZero, MCSymbolAttr::MCSA_Weak);
1369+ OutStreamer->emitAssignment (AbsZero, MCConstantExpr::create (0u , OutContext));
1370+ }
1371+ }
12971372 // Emit needed stubs
12981373 //
12991374 for (std::map<
0 commit comments