Skip to content

Commit a05fdd2

Browse files
Add -mfix-nmips-hw110880 option
1 parent a82a35d commit a05fdd2

File tree

9 files changed

+140
-17
lines changed

9 files changed

+140
-17
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3487,6 +3487,8 @@ def mxgot : Flag<["-"], "mxgot">, Group<m_mips_Features_Group>;
34873487
def mno_xgot : Flag<["-"], "mno-xgot">, Group<m_mips_Features_Group>;
34883488
def mjump_table_opt : Flag<["-"], "mjump-table-opt">, Group<m_mips_Features_Group>;
34893489
def mno_jump_table_opt : Flag<["-"], "mno-jump-table-opt">, Group<m_mips_Features_Group>;
3490+
def mfix_nmips_hw110880 : Flag<["-"], "mfix-nmips-hw110880">, Group<m_mips_Features_Group>;
3491+
def mno_fix_nmips_hw110880 : Flag<["-"], "mno-fix-nmips-hw110880">, Group<m_mips_Features_Group>;
34903492
def mldc1_sdc1 : Flag<["-"], "mldc1-sdc1">, Group<m_mips_Features_Group>;
34913493
def mno_ldc1_sdc1 : Flag<["-"], "mno-ldc1-sdc1">, Group<m_mips_Features_Group>;
34923494
def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">,

clang/lib/Driver/ToolChains/Arch/Mips.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,14 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
300300
Features.push_back("-disable-jump-table-opt");
301301
}
302302

303+
if (Arg *A = Args.getLastArg(options::OPT_mfix_nmips_hw110880,
304+
options::OPT_mno_fix_nmips_hw110880)) {
305+
if (A->getOption().matches(options::OPT_mfix_nmips_hw110880))
306+
Features.push_back("+fix-hw110880");
307+
else
308+
Features.push_back("-fix-hw110880");
309+
}
310+
303311
mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple);
304312
if (FloatABI == mips::FloatABI::Soft) {
305313
// FIXME: Note, this is a hack. We need to pass the selected float

clang/lib/Driver/ToolChains/NanoMips.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ void NanoMipsLinker::ConstructJob(Compilation &C, const JobAction &JA,
128128
CmdArgs.push_back("--relax");
129129
}
130130

131+
if (Args.hasFlag(options::OPT_mfix_nmips_hw110880,
132+
options::OPT_mno_fix_nmips_hw110880, false)) {
133+
CmdArgs.push_back("--fix-nmips-hw110880");
134+
}
135+
131136
Args.AddAllArgs(CmdArgs, options::OPT_L);
132137
Args.AddAllArgs(CmdArgs, options::OPT_u);
133138

llvm/lib/Target/Mips/Mips.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ def FeatureUseIndirectJumpsHazard : SubtargetFeature<"use-indirect-jump-hazard",
226226
"true", "Use indirect jump"
227227
" guards to prevent certain speculation based attacks">;
228228

229+
def FeatureFixImm48 : SubtargetFeature<"fix-hw110880", "HasFixHw110880", "true", "Avoid problematic instructions for hw110880 issue">;
230+
229231
//===----------------------------------------------------------------------===//
230232
// Register File, Calling Conv, Instruction Descriptions
231233
//===----------------------------------------------------------------------===//

llvm/lib/Target/Mips/MipsAsmPrinter.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ using namespace llvm;
7272

7373
extern 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+
7580
void 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

12961357
void 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<

llvm/lib/Target/Mips/MipsAsmPrinter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter {
8080

8181
void emitJumpTableDest(MCStreamer &OutStreamer, const MachineInstr *MI);
8282

83+
bool tryEmitHw110880Fix(MCStreamer &OutStreamer, const MachineInstr *MI);
84+
8385
// Emit brsc instruction followed by a label that will be used while creating
8486
// offset expressions in jump table entries.
8587
void emitBrsc(MCStreamer &OutStreamer, const MachineInstr *MI);

llvm/lib/Target/Mips/MipsSubtarget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
207207
// Use linker relaxation
208208
bool UseLinkerRelax = true;
209209

210+
bool HasFixHw110880 = false;
211+
210212
/// The minimum alignment known to hold of the stack frame on
211213
/// entry to the function and which must be maintained by every function.
212214
Align stackAlignment;
@@ -355,6 +357,8 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
355357

356358
bool useLinkerRelax() const { return UseLinkerRelax; }
357359

360+
bool hasFixHw110880() const { return HasFixHw110880; }
361+
358362
bool enableLongBranchPass() const {
359363
return hasStandardEncoding() || inMicroMipsMode() || allowMixed16_32();
360364
}
Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
; RUN: llc -mtriple=nanomips -asm-show-inst -verify-machineinstrs < %s | FileCheck %s
2-
1+
; RUN: llc -mtriple=nanomips -asm-show-inst -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-ALL --check-prefix=CHECK %s
2+
; RUN: llc -mtriple=nanomips -asm-show-inst -mattr=+fix-hw110880 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-ALL --check-prefix=CHECK-FIX %s
33
define i32 @test_addiu0(i32 %a) {
4-
; CHECK: addiu $a0, $a0, 1
4+
; CHECK-ALL: addiu $a0, $a0, 1
55
%added = add i32 %a, 1
66
ret i32 %added
77
}
88

99
define i32 @test_addiu1(i32 %a) {
10-
; CHECK: addiu $a0, $a0, 65535
10+
; CHECK-ALL: addiu $a0, $a0, 65535
1111
%added = add i32 %a, 65535
1212
ret i32 %added
1313
}
@@ -19,7 +19,7 @@ define i32 @test_addiu2(i32 %a) {
1919
}
2020

2121
define i32 @test_addiu3(i32 %a) {
22-
; CHECK: addiu $a0, $a0, -2048
22+
; CHECK-ALL: addiu $a0, $a0, -2048
2323
%added = add i32 %a, -2048
2424
ret i32 %added
2525
}
@@ -31,26 +31,33 @@ define i32 @test_addiu4(i32 %a) {
3131
}
3232

3333
define i32 @test_addiu5(i32 %a) {
34-
; CHECK: addiu[48] $a0, $a0, 2147483647
34+
; CHECK-ALL: addiu[48] $a0, $a0, 2147483647
3535
%added = add i32 %a, 2147483647
3636
ret i32 %added
3737
}
3838

3939
define i32 @test_addiu6(i32 %a) {
40-
; CHECK: addiu[48] $a0, $a0, -2147483648
40+
; CHECK-ALL: addiu[48] $a0, $a0, -2147483648
4141
%added = add i32 %a, -2147483648
4242
ret i32 %added
4343
}
4444

4545
define i32 @test_addiu7(i32 %a, i32 %b) {
46-
; CHECK: move $a0, $a1
47-
; CHECK: addiu[48] $a0, $a0, -2049
46+
; CHECK-ALL: move $a0, $a1
47+
; CHECK-ALL: addiu[48] $a0, $a0, -2049
4848
%added = add i32 %b, -2049
4949
ret i32 %added
5050
}
5151

5252
define i32 @test_addiu8(i32 %a) {
53-
; CHECK: addiu[48] $a0, $a0, -2147483648
53+
; CHECK-ALL: addiu[48] $a0, $a0, -2147483648
5454
%added = add i32 %a, 2147483648
5555
ret i32 %added
5656
}
57+
58+
define i32 @test_addiu9(i32 %a) {
59+
; CHECK: addiu[48] $a0, $a0, 1375806708
60+
; CHECK-FIX: addiu[48] $a0, $a0, .Lzero+0x520124f4
61+
%added = add i32 %a, 1375806708
62+
ret i32 %added
63+
}
Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,43 @@
1-
; RUN: llc -mtriple=nanomips -asm-show-inst -verify-machineinstrs < %s | FileCheck %s
1+
; RUN: llc -mtriple=nanomips -asm-show-inst -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-ALL --check-prefix=CHECK %s
2+
; RUN: llc -mtriple=nanomips -asm-show-inst -mattr=+fix-hw110880 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-ALL --check-prefix=CHECK-FIX %s
23

34
define i32 @foo0() nounwind readnone {
45
; CHECK-LABEL: foo0
56
entry:
6-
; CHECK: li $a0, 12345
7-
; CHECK: Li_NM
7+
; CHECK-ALL: li $a0, 12345
8+
; CHECK-ALL: Li_NM
89
ret i32 12345
910
}
1011

1112
define i32 @foo1() nounwind readnone {
1213
; CHECK-LABEL: foo1
1314
entry:
14-
; CHECK: li $a0, -2147483648
15-
; CHECK: Li_NM
15+
; CHECK-ALL: li $a0, -2147483648
16+
; CHECK-ALL: Li_NM
1617
ret i32 -2147483648
1718
}
1819

1920
define i32 @foo2() nounwind readnone {
2021
; CHECK-LABEL: foo2
2122
entry:
22-
; CHECK: li $a0, 2147483647
23-
; CHECK: Li_NM
23+
; CHECK-ALL: li $a0, 2147483647
24+
; CHECK-ALL: Li_NM
2425
ret i32 2147483647
2526
}
27+
28+
define i32 @foo3() nounwind readnone {
29+
; CHECK-LABEL: foo3
30+
entry:
31+
; CHECK-ALL: li $a0, 2147479552
32+
; CHECK-ALL: Li_NM
33+
ret i32 2147479552
34+
}
35+
36+
define i32 @foo4() nounwind readnone {
37+
; CHECK-LABEL: foo4
38+
entry:
39+
; CHECK: li $a0, 1375806708
40+
; CHECK-FIX: li $a0, .Lzero+0x520124f4
41+
; CHECK-ALL: Li_NM
42+
ret i32 1375806708
43+
}

0 commit comments

Comments
 (0)