https://github.com/rickgaiser updated https://github.com/llvm/llvm-project/pull/176666
>From 71b10943ce67885375dfa9bdd4ed767cb59b3943 Mon Sep 17 00:00:00 2001 From: Rick Gaiser <[email protected]> Date: Sun, 18 Jan 2026 15:53:30 +0100 Subject: [PATCH 1/6] [Mips] Add r5900 CPU definition and feature flag --- llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 2 ++ llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp | 2 ++ llvm/lib/Target/Mips/Mips.td | 5 +++++ llvm/lib/Target/Mips/MipsSubtarget.cpp | 8 ++++---- llvm/lib/Target/Mips/MipsSubtarget.h | 4 ++++ llvm/test/CodeGen/Mips/cpus.ll | 4 ++++ 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 6675db755d1a1..f91c378ad0afa 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -693,6 +693,8 @@ class MipsAsmParser : public MCTargetAsmParser { return (getSTI().hasFeature(Mips::FeatureCnMipsP)); } + bool isR5900() const { return (getSTI().hasFeature(Mips::FeatureR5900)); } + bool inPicMode() { return IsPicEnabled; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 01f18acf050d7..12a5b20cfb9ff 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -921,6 +921,8 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, // Machine if (Features[Mips::FeatureCnMips]) EFlags |= ELF::EF_MIPS_MACH_OCTEON; + else if (Features[Mips::FeatureR5900]) + EFlags |= ELF::EF_MIPS_MACH_5900; // Other options. if (Features[Mips::FeatureNaN2008]) diff --git a/llvm/lib/Target/Mips/Mips.td b/llvm/lib/Target/Mips/Mips.td index 8b0d87b5c5376..7cfa0800454c6 100644 --- a/llvm/lib/Target/Mips/Mips.td +++ b/llvm/lib/Target/Mips/Mips.td @@ -186,6 +186,10 @@ def FeatureCnMipsP : SubtargetFeature<"cnmipsp", "HasCnMipsP", "true", "Octeon+ cnMIPS Support", [FeatureCnMips]>; +def FeatureR5900 : SubtargetFeature<"r5900", "IsR5900", "true", + "R5900 (PS2 Emotion Engine) Support", + [FeatureMips3, FeatureSoftFloat]>; + def FeatureUseTCCInDIV : SubtargetFeature< "use-tcc-in-div", "UseTCCInDIV", "false", @@ -296,6 +300,7 @@ def : Proc<"mips64r6", [FeatureMips64r6]>; def : Proc<"octeon", [FeatureMips64r2, FeatureCnMips]>; def : Proc<"octeon+", [FeatureMips64r2, FeatureCnMips, FeatureCnMipsP]>; def : ProcessorModel<"p5600", MipsP5600Model, [ImplP5600]>; +def : Proc<"r5900", [FeatureR5900]>; def : ProcessorModel<"i6400", MipsI6400Model, [ImplI6400]>; def : ProcessorModel<"i6500", MipsI6400Model, [ImplI6500]>; diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index aef9382d3c1dc..5134e16a8d78b 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -86,10 +86,10 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, IsSingleFloat(false), IsFPXX(false), NoABICalls(false), Abs2008(false), IsFP64bit(false), UseOddSPReg(true), IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false), HasCnMips(false), HasCnMipsP(false), - HasMips3_32(false), HasMips3_32r2(false), HasMips4_32(false), - HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false), - InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false), - HasDSPR2(false), HasDSPR3(false), + IsR5900(false), HasMips3_32(false), HasMips3_32r2(false), + HasMips4_32(false), HasMips4_32r2(false), HasMips5_32r2(false), + InMips16Mode(false), InMips16HardFloat(Mips16HardFloat), + InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 || Mips_Os16), Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false), HasEVA(false), DisableMadd4(false), HasMT(false), HasCRC(false), HasVirt(false), HasGINV(false), diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index b09cfb3ac4a09..3c8b088421208 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -124,6 +124,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // CPU supports cnMIPSP (Cavium Networks Octeon+ CPU). bool HasCnMipsP; + // IsR5900 - CPU is R5900 (PlayStation 2 Emotion Engine). + bool IsR5900; + // isLinux - Target system is Linux. Is false we consider ELFOS for now. bool IsLinux; @@ -297,6 +300,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo { bool hasCnMips() const { return HasCnMips; } bool hasCnMipsP() const { return HasCnMipsP; } + bool isR5900() const { return IsR5900; } bool isLittle() const { return IsLittle; } bool isABICalls() const { return !NoABICalls; } diff --git a/llvm/test/CodeGen/Mips/cpus.ll b/llvm/test/CodeGen/Mips/cpus.ll index 077f8fb48bae0..14e7476d8f9ef 100644 --- a/llvm/test/CodeGen/Mips/cpus.ll +++ b/llvm/test/CodeGen/Mips/cpus.ll @@ -58,6 +58,10 @@ ; OCTEONP: ISA: MIPS64r2 ; OCTEONP: ISA Extension: Cavium Networks OcteonP +; RUN: llc -mtriple=mips64el -mcpu=r5900 -filetype=obj < %s \ +; RUN: | llvm-readelf -A - | FileCheck %s --check-prefix=R5900 +; R5900: ISA: MIPS3 + ; Check that we reject CPUs that are not implemented. ; RUN: not llc < %s -o /dev/null -mtriple=mips64 -mcpu=mips5 2>&1 \ >From c6a8b4ebde607615880fbb1d912f96f5e11e6054 Mon Sep 17 00:00:00 2001 From: Rick Gaiser <[email protected]> Date: Sun, 18 Jan 2026 13:24:24 +0100 Subject: [PATCH 2/6] [Mips] Disable unsupported instructions for r5900 The R5900 is based on MIPS-III but lacks several instructions that were also removed or relocated in MIPS32R6/MIPS64R6: - LL/SC atomic instructions - COP3 instructions (LWC3, SWC3, LDC3, SDC3) - 64-bit multiply/divide (DMULT, DMULTU, DDIV, DDIVU) Implementation uses combined ISA classes (e.g., ISA_MIPS2_NOT_32R6_64R6_R5900) with InsnPredicates to properly combine the NotR5900 predicate with existing ISA and ASE predicates. - Add NotR5900 predicate - Add ISA_MIPS*_NOT_*_R5900 combined classes - Set MaxAtomicSizeInBitsSupported to 0 for R5900 - Expand 64-bit multiply/divide operations to 32-bit equivalents - Add assembly tests for invalid instructions --- llvm/lib/Target/Mips/Mips64InstrInfo.td | 175 +++++++++++--------- llvm/lib/Target/Mips/MipsISelLowering.cpp | 5 +- llvm/lib/Target/Mips/MipsInstrInfo.td | 68 ++++++-- llvm/lib/Target/Mips/MipsSEISelLowering.cpp | 13 +- llvm/test/MC/Mips/r5900-invalid.s | 59 +++++++ 5 files changed, 224 insertions(+), 96 deletions(-) create mode 100644 llvm/test/MC/Mips/r5900-invalid.s diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td index ef4eea8c50dc6..b22b0acf49507 100644 --- a/llvm/lib/Target/Mips/Mips64InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td @@ -245,18 +245,23 @@ def SDR : StoreLeftRight<"sdr", MipsSDR, GPR64Opnd, II_SDR>, LW_FM<0x2d>, /// Load-linked, Store-conditional let AdditionalPredicates = [NotInMicroMips] in { - def LLD : LLBase<"lld", GPR64Opnd, mem_simmptr>, LW_FM<0x34>, - ISA_MIPS3_NOT_32R6_64R6; + def LLD : LLBase<"lld", GPR64Opnd, mem_simmptr>, + LW_FM<0x34>, + ISA_MIPS3_NOT_32R6_64R6_R5900; } -def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3_NOT_32R6_64R6; +def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3_NOT_32R6_64R6_R5900; let AdditionalPredicates = [NotInMicroMips], DecoderNamespace = "Mips32_64_PTR64" in { -def LL64 : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_64, - ISA_MIPS2_NOT_32R6_64R6; -def SC64 : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_64, - ISA_MIPS2_NOT_32R6_64R6; -def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>, PTR_64; + def LL64 : LLBase<"ll", GPR32Opnd>, + LW_FM<0x30>, + PTR_64, + ISA_MIPS2_NOT_32R6_64R6_R5900; + def SC64 : SCBase<"sc", GPR32Opnd>, + LW_FM<0x38>, + PTR_64, + ISA_MIPS2_NOT_32R6_64R6_R5900; + def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>, PTR_64; } def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM, PTR_64; @@ -305,25 +310,32 @@ let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, /// Multiply and Divide Instructions. let AdditionalPredicates = [NotInMicroMips] in { - def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1c>, ISA_MIPS3_NOT_32R6_64R6; + def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>, + MULT_FM<0, 0x1c>, + ISA_MIPS3_NOT_32R6_64R6_R5900; def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1d>, ISA_MIPS3_NOT_32R6_64R6; + MULT_FM<0, 0x1d>, + ISA_MIPS3_NOT_32R6_64R6_R5900; } -def PseudoDMULT : MultDivPseudo<DMULT, ACC128, GPR64Opnd, MipsMult, - II_DMULT>, ISA_MIPS3_NOT_32R6_64R6; -def PseudoDMULTu : MultDivPseudo<DMULTu, ACC128, GPR64Opnd, MipsMultu, - II_DMULTU>, ISA_MIPS3_NOT_32R6_64R6; +def PseudoDMULT : MultDivPseudo<DMULT, ACC128, GPR64Opnd, MipsMult, II_DMULT>, + ISA_MIPS3_NOT_32R6_64R6_R5900; +def PseudoDMULTu + : MultDivPseudo<DMULTu, ACC128, GPR64Opnd, MipsMultu, II_DMULTU>, + ISA_MIPS3_NOT_32R6_64R6_R5900; let AdditionalPredicates = [NotInMicroMips] in { def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1e>, ISA_MIPS3_NOT_32R6_64R6; + MULT_FM<0, 0x1e>, + ISA_MIPS3_NOT_32R6_64R6_R5900; def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1f>, ISA_MIPS3_NOT_32R6_64R6; + MULT_FM<0, 0x1f>, + ISA_MIPS3_NOT_32R6_64R6_R5900; } -def PseudoDSDIV : MultDivPseudo<DSDIV, ACC128, GPR64Opnd, MipsDivRem, - II_DDIV, 0, 1, 1>, ISA_MIPS3_NOT_32R6_64R6; -def PseudoDUDIV : MultDivPseudo<DUDIV, ACC128, GPR64Opnd, MipsDivRemU, - II_DDIVU, 0, 1, 1>, ISA_MIPS3_NOT_32R6_64R6; +def PseudoDSDIV + : MultDivPseudo<DSDIV, ACC128, GPR64Opnd, MipsDivRem, II_DDIV, 0, 1, 1>, + ISA_MIPS3_NOT_32R6_64R6_R5900; +def PseudoDUDIV + : MultDivPseudo<DUDIV, ACC128, GPR64Opnd, MipsDivRemU, II_DDIVU, 0, 1, 1>, + ISA_MIPS3_NOT_32R6_64R6_R5900; let isCodeGenOnly = 1 in { def MTHI64 : MoveToLOHI<"mthi", GPR64Opnd, [HI0_64]>, MTLO_FM<0x11>, @@ -1119,100 +1131,103 @@ def LoadAddrReg64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins mem:$addr), def LoadAddrImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins imm64:$imm64), "dla\t$rt, $imm64">; -def DMULImmMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, - simm32_relaxed:$imm), - "dmul\t$rs, $rt, $imm">, - ISA_MIPS3_NOT_32R6_64R6; -def DMULOMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, - GPR64Opnd:$rd), - "dmulo\t$rs, $rt, $rd">, - ISA_MIPS3_NOT_32R6_64R6; -def DMULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, - GPR64Opnd:$rd), - "dmulou\t$rs, $rt, $rd">, - ISA_MIPS3_NOT_32R6_64R6; +def DMULImmMacro + : MipsAsmPseudoInst<(outs), + (ins GPR64Opnd:$rs, GPR64Opnd:$rt, simm32_relaxed:$imm), + "dmul\t$rs, $rt, $imm">, + ISA_MIPS3_NOT_32R6_64R6_R5900; +def DMULOMacro + : MipsAsmPseudoInst<(outs), + (ins GPR64Opnd:$rs, GPR64Opnd:$rt, GPR64Opnd:$rd), + "dmulo\t$rs, $rt, $rd">, + ISA_MIPS3_NOT_32R6_64R6_R5900; +def DMULOUMacro + : MipsAsmPseudoInst<(outs), + (ins GPR64Opnd:$rs, GPR64Opnd:$rt, GPR64Opnd:$rd), + "dmulou\t$rs, $rt, $rd">, + ISA_MIPS3_NOT_32R6_64R6_R5900; def DMULMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, GPR64Opnd:$rd), "dmul\t$rs, $rt, $rd"> { - let InsnPredicates = [HasMips3, NotMips64r6, NotCnMips]; + let InsnPredicates = [HasMips3, NotMips64r6, NotCnMips, NotR5900]; } let AdditionalPredicates = [NotInMicroMips] in { def DSDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, GPR64Opnd:$rt), "ddiv\t$rd, $rs, $rt">, - ISA_MIPS3_NOT_32R6_64R6; - def DSDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, imm64:$imm), - "ddiv\t$rd, $rs, $imm">, - ISA_MIPS3_NOT_32R6_64R6; + ISA_MIPS3_NOT_32R6_64R6_R5900; + def DSDivIMacro + : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, imm64:$imm), + "ddiv\t$rd, $rs, $imm">, + ISA_MIPS3_NOT_32R6_64R6_R5900; def DUDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, GPR64Opnd:$rt), "ddivu\t$rd, $rs, $rt">, - ISA_MIPS3_NOT_32R6_64R6; - def DUDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, imm64:$imm), - "ddivu\t$rd, $rs, $imm">, - ISA_MIPS3_NOT_32R6_64R6; + ISA_MIPS3_NOT_32R6_64R6_R5900; + def DUDivIMacro + : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, imm64:$imm), + "ddivu\t$rd, $rs, $imm">, + ISA_MIPS3_NOT_32R6_64R6_R5900; // GAS expands 'div' and 'ddiv' differently when the destination // register is $zero and the instruction is in the two operand // form. 'ddiv' gets expanded, while 'div' is not expanded. - def : MipsInstAlias<"ddiv $rs, $rt", (DSDivMacro GPR64Opnd:$rs, - GPR64Opnd:$rs, - GPR64Opnd:$rt), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"ddiv $rd, $imm", (DSDivIMacro GPR64Opnd:$rd, - GPR64Opnd:$rd, - imm64:$imm), 0>, - ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"ddiv $rs, $rt", + (DSDivMacro GPR64Opnd:$rs, GPR64Opnd:$rs, GPR64Opnd:$rt), + 0>, + ISA_MIPS3_NOT_32R6_64R6_R5900; + def : MipsInstAlias<"ddiv $rd, $imm", + (DSDivIMacro GPR64Opnd:$rd, GPR64Opnd:$rd, imm64:$imm), + 0>, + ISA_MIPS3_NOT_32R6_64R6_R5900; // GAS expands 'divu' and 'ddivu' differently when the destination // register is $zero and the instruction is in the two operand // form. 'ddivu' gets expanded, while 'divu' is not expanded. - def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR64Opnd:$rt, - GPR64Opnd:$rt, - GPR64Opnd:$rs), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"ddivu $rd, $imm", (DUDivIMacro GPR64Opnd:$rd, - GPR64Opnd:$rd, - imm64:$imm), 0>, - ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"ddivu $rt, $rs", + (DUDivMacro GPR64Opnd:$rt, GPR64Opnd:$rt, GPR64Opnd:$rs), + 0>, + ISA_MIPS3_NOT_32R6_64R6_R5900; + def : MipsInstAlias<"ddivu $rd, $imm", + (DUDivIMacro GPR64Opnd:$rd, GPR64Opnd:$rd, imm64:$imm), + 0>, + ISA_MIPS3_NOT_32R6_64R6_R5900; def DSRemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, GPR64Opnd:$rt), "drem\t$rd, $rs, $rt">, - ISA_MIPS3_NOT_32R6_64R6; + ISA_MIPS3_NOT_32R6_64R6_R5900; def DSRemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, simm32_relaxed:$imm), "drem\t$rd, $rs, $imm">, - ISA_MIPS3_NOT_32R6_64R6; + ISA_MIPS3_NOT_32R6_64R6_R5900; def DURemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, GPR64Opnd:$rt), "dremu\t$rd, $rs, $rt">, - ISA_MIPS3_NOT_32R6_64R6; + ISA_MIPS3_NOT_32R6_64R6_R5900; def DURemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, simm32_relaxed:$imm), "dremu\t$rd, $rs, $imm">, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"drem $rt, $rs", (DSRemMacro GPR64Opnd:$rt, - GPR64Opnd:$rt, - GPR64Opnd:$rs), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"drem $rd, $imm", (DSRemIMacro GPR64Opnd:$rd, - GPR64Opnd:$rd, - simm32_relaxed:$imm), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"dremu $rt, $rs", (DURemMacro GPR64Opnd:$rt, - GPR64Opnd:$rt, - GPR64Opnd:$rs), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"dremu $rd, $imm", (DURemIMacro GPR64Opnd:$rd, - GPR64Opnd:$rd, - simm32_relaxed:$imm), 0>, - ISA_MIPS3_NOT_32R6_64R6; + ISA_MIPS3_NOT_32R6_64R6_R5900; + def : MipsInstAlias<"drem $rt, $rs", + (DSRemMacro GPR64Opnd:$rt, GPR64Opnd:$rt, GPR64Opnd:$rs), + 0>, + ISA_MIPS3_NOT_32R6_64R6_R5900; + def : MipsInstAlias< + "drem $rd, $imm", + (DSRemIMacro GPR64Opnd:$rd, GPR64Opnd:$rd, simm32_relaxed:$imm), 0>, + ISA_MIPS3_NOT_32R6_64R6_R5900; + def : MipsInstAlias<"dremu $rt, $rs", + (DURemMacro GPR64Opnd:$rt, GPR64Opnd:$rt, GPR64Opnd:$rs), + 0>, + ISA_MIPS3_NOT_32R6_64R6_R5900; + def : MipsInstAlias< + "dremu $rd, $imm", + (DURemIMacro GPR64Opnd:$rd, GPR64Opnd:$rd, simm32_relaxed:$imm), 0>, + ISA_MIPS3_NOT_32R6_64R6_R5900; } def NORImm64 : NORIMM_DESC_BASE<GPR64Opnd, imm64>, GPR_64; diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index dbbeb75e673c3..b62669d5d5fa6 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -412,7 +412,10 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, ISD::OR, ISD::ADD, ISD::SUB, ISD::AssertZext, ISD::SHL, ISD::SIGN_EXTEND}); - if (Subtarget.isGP64bit()) + // R5900 has no LL/SC instructions for atomic operations + if (Subtarget.isR5900()) + setMaxAtomicSizeInBitsSupported(0); + else if (Subtarget.isGP64bit()) setMaxAtomicSizeInBitsSupported(64); else setMaxAtomicSizeInBitsSupported(32); diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 5b464ff2957e4..2a476e789032c 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -259,6 +259,10 @@ def UseIndirectJumpsHazard : Predicate<"Subtarget->useIndirectJumpsHazard()">, AssemblerPredicate<(all_of FeatureUseIndirectJumpsHazard)>; def NoIndirectJumpGuards : Predicate<"!Subtarget->useIndirectJumpsHazard()">, AssemblerPredicate<(all_of (not FeatureUseIndirectJumpsHazard))>; +def HasR5900 : Predicate<"Subtarget->isR5900()">, + AssemblerPredicate<(all_of FeatureR5900)>; +def NotR5900 : Predicate<"!Subtarget->isR5900()">, + AssemblerPredicate<(all_of (not FeatureR5900))>; def HasCRC : Predicate<"Subtarget->hasCRC()">, AssemblerPredicate<(all_of FeatureCRC)>; def HasVirt : Predicate<"Subtarget->hasVirt()">, @@ -312,14 +316,27 @@ class ISA_MIPS1_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6]; list<Predicate> EncodingPredicates = [HasStdEnc]; } +class ISA_MIPS1_NOT_32R6_64R6_R5900 { + list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6, NotR5900]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} class ISA_MIPS2 { list<Predicate> InsnPredicates = [HasMips2]; list<Predicate> EncodingPredicates = [HasStdEnc]; } +class ISA_MIPS2_NOT_R5900 { + list<Predicate> InsnPredicates = [HasMips2, NotR5900]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} class ISA_MIPS2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips2, NotMips32r6, NotMips64r6]; list<Predicate> EncodingPredicates = [HasStdEnc]; } +class ISA_MIPS2_NOT_32R6_64R6_R5900 { + list<Predicate> InsnPredicates = [HasMips2, NotMips32r6, NotMips64r6, + NotR5900]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} class ISA_MIPS3 { list<Predicate> InsnPredicates = [HasMips3]; list<Predicate> EncodingPredicates = [HasStdEnc]; @@ -328,6 +345,11 @@ class ISA_MIPS3_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips3, NotMips32r6, NotMips64r6]; list<Predicate> EncodingPredicates = [HasStdEnc]; } +class ISA_MIPS3_NOT_32R6_64R6_R5900 { + list<Predicate> InsnPredicates = [HasMips3, NotMips32r6, NotMips64r6, + NotR5900]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} class ISA_MIPS32 { list<Predicate> InsnPredicates = [HasMips32]; list<Predicate> EncodingPredicates = [HasStdEnc]; @@ -1837,11 +1859,15 @@ class Atomic2OpsPostRA<RegisterClass RC> : PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr), []> { let mayLoad = 1; let mayStore = 1; + let Predicates = [NotR5900]; } -class Atomic2OpsSubwordPostRA<RegisterClass RC> : - PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr, RC:$mask, RC:$mask2, - RC:$shiftamnt), []>; +class Atomic2OpsSubwordPostRA<RegisterClass RC> + : PseudoSE< + (outs RC:$dst), + (ins PtrRC:$ptr, RC:$incr, RC:$mask, RC:$mask2, RC:$shiftamnt), []> { + let Predicates = [NotR5900]; +} // Atomic Compare & Swap. // Atomic compare and swap is lowered into two stages. The first stage happens @@ -1856,6 +1882,7 @@ class AtomicCmpSwapPostRA<RegisterClass RC> : PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$cmp, RC:$swap), []> { let mayLoad = 1; let mayStore = 1; + let Predicates = [NotR5900]; } class AtomicCmpSwapSubwordPostRA<RegisterClass RC> : @@ -1863,6 +1890,7 @@ class AtomicCmpSwapSubwordPostRA<RegisterClass RC> : RC:$mask2, RC:$ShiftNewVal, RC:$ShiftAmt), []> { let mayLoad = 1; let mayStore = 1; + let Predicates = [NotR5900]; } class LLBase<string opstr, RegisterOperand RO, DAGOperand MO = mem> : @@ -2166,14 +2194,22 @@ def SDC2 : StdMMR6Rel, SW_FT2<"sdc2", COP2Opnd, II_SDC2, store>, // COP3 Memory Instructions let DecoderNamespace = "COP3_" in { - def LWC3 : LW_FT3<"lwc3", COP3Opnd, II_LWC3, load>, LW_FM<0x33>, - ISA_MIPS1_NOT_32R6_64R6, NOT_ASE_CNMIPS; - def SWC3 : SW_FT3<"swc3", COP3Opnd, II_SWC3, store>, LW_FM<0x3b>, - ISA_MIPS1_NOT_32R6_64R6, NOT_ASE_CNMIPS; - def LDC3 : LW_FT3<"ldc3", COP3Opnd, II_LDC3, load>, LW_FM<0x37>, - ISA_MIPS2, NOT_ASE_CNMIPS; - def SDC3 : SW_FT3<"sdc3", COP3Opnd, II_SDC3, store>, LW_FM<0x3f>, - ISA_MIPS2, NOT_ASE_CNMIPS; + def LWC3 : LW_FT3<"lwc3", COP3Opnd, II_LWC3, load>, + LW_FM<0x33>, + ISA_MIPS1_NOT_32R6_64R6_R5900, + NOT_ASE_CNMIPS; + def SWC3 : SW_FT3<"swc3", COP3Opnd, II_SWC3, store>, + LW_FM<0x3b>, + ISA_MIPS1_NOT_32R6_64R6_R5900, + NOT_ASE_CNMIPS; + def LDC3 : LW_FT3<"ldc3", COP3Opnd, II_LDC3, load>, + LW_FM<0x37>, + ISA_MIPS2_NOT_R5900, + NOT_ASE_CNMIPS; + def SDC3 : SW_FT3<"sdc3", COP3Opnd, II_SDC3, store>, + LW_FM<0x3f>, + ISA_MIPS2_NOT_R5900, + NOT_ASE_CNMIPS; } def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS2; @@ -2232,8 +2268,14 @@ let AdditionalPredicates = [NotInMicroMips] in { let AdditionalPredicates = [NotInMicroMips] in { /// Load-linked, Store-conditional -def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_32, ISA_MIPS2_NOT_32R6_64R6; -def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_32, ISA_MIPS2_NOT_32R6_64R6; +def LL : LLBase<"ll", GPR32Opnd>, + LW_FM<0x30>, + PTR_32, + ISA_MIPS2_NOT_32R6_64R6_R5900; +def SC : SCBase<"sc", GPR32Opnd>, + LW_FM<0x38>, + PTR_32, + ISA_MIPS2_NOT_32R6_64R6_R5900; } /// Jump and Branch Instructions let AdditionalPredicates = [NotInMicroMips, RelocNotPIC] in diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp index 0906ab56e1671..10885d0b01376 100644 --- a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp @@ -235,10 +235,19 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, if (Subtarget.hasCnMips()) setOperationAction(ISD::MUL, MVT::i64, Legal); - else if (Subtarget.isGP64bit()) + else if (Subtarget.isR5900()) { + // R5900 doesn't have DMULT/DMULTU/DDIV/DDIVU - expand to 32-bit ops + setOperationAction(ISD::MUL, MVT::i64, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::MULHS, MVT::i64, Expand); + setOperationAction(ISD::MULHU, MVT::i64, Expand); + setOperationAction(ISD::SDIVREM, MVT::i64, Expand); + setOperationAction(ISD::UDIVREM, MVT::i64, Expand); + } else if (Subtarget.isGP64bit()) setOperationAction(ISD::MUL, MVT::i64, Custom); - if (Subtarget.isGP64bit()) { + if (Subtarget.isGP64bit() && !Subtarget.isR5900()) { setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom); setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom); setOperationAction(ISD::MULHS, MVT::i64, Custom); diff --git a/llvm/test/MC/Mips/r5900-invalid.s b/llvm/test/MC/Mips/r5900-invalid.s new file mode 100644 index 0000000000000..4b1eed2f56bcc --- /dev/null +++ b/llvm/test/MC/Mips/r5900-invalid.s @@ -0,0 +1,59 @@ +# Instructions that are invalid on R5900 +# +# R5900 is a MIPS III-based processor with specific limitations: +# - No 64-bit multiply/divide (DMULT/DMULTU/DDIV/DDIVU) +# - No LL/SC atomic instructions +# - No COP3 instructions (LWC3, SWC3, LDC3, SDC3) +# +# RUN: not llvm-mc %s -triple=mips64el-unknown-linux -mcpu=r5900 2>%t1 +# RUN: FileCheck %s < %t1 + + .set noat + +# ============================================================================= +# MIPS3 64-bit multiply/divide instructions that R5900 does NOT support +# ============================================================================= + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + dmult $4, $5 + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + dmultu $6, $7 + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + ddiv $zero, $8, $9 + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + ddivu $zero, $10, $11 + +# ============================================================================= +# LL/SC atomic instructions that R5900 does NOT support +# ============================================================================= + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + ll $4, 0($5) + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + sc $4, 0($5) + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + lld $4, 0($5) + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + scd $4, 0($5) + +# ============================================================================= +# COP3 instructions that R5900 does NOT support +# ============================================================================= + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + lwc3 $4, 0($5) + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + swc3 $4, 0($5) + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + ldc3 $4, 0($5) + +# CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + sdc3 $4, 0($5) >From 038de93597eb2d1b5b0ef40e5e41d9054c2675e1 Mon Sep 17 00:00:00 2001 From: Rick Gaiser <[email protected]> Date: Sun, 18 Jan 2026 13:24:29 +0100 Subject: [PATCH 3/6] [Mips] Add r5900 short loop delay slot fix --- llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp | 79 +++++++++++++++++++- llvm/test/CodeGen/Mips/r5900-short-loop.ll | 59 +++++++++++++++ 2 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/Mips/r5900-short-loop.ll diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index 850d3b59be5de..da15423853559 100644 --- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -52,6 +52,8 @@ using namespace llvm; STATISTIC(FilledSlots, "Number of delay slots filled"); STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that" " are not NOP."); +STATISTIC(R5900ShortLoopNops, "Number of delay slots left as NOP for R5900 " + "short loop fix"); static cl::opt<bool> DisableDelaySlotFiller( "disable-mips-delay-filler", @@ -278,6 +280,65 @@ static bool hasUnoccupiedSlot(const MachineInstr *MI) { return MI->hasDelaySlot() && !MI->isBundledWithSucc(); } +/// Check if a branch is a short backward loop that triggers the R5900 erratum. +/// The erratum occurs when: +/// - A loop has 6 or fewer instructions (including branch + delay slot) +/// - The branch is a conditional backward branch +/// - The delay slot is not NOP +/// - No other branches exist in the loop body +static bool isR5900ShortLoopBranch(const MachineInstr *MI, + const MachineBasicBlock &MBB) { + // Must be a conditional branch (not jump or indirect branch) + if (!MI->isBranch() || MI->isIndirectBranch()) + return false; + + // Check if this is a conditional branch by looking for an MBB operand + const MachineBasicBlock *TargetMBB = nullptr; + for (const MachineOperand &MO : MI->operands()) { + if (MO.isMBB()) { + TargetMBB = MO.getMBB(); + break; + } + } + + // Must have a target and must target the same basic block (backward branch) + if (!TargetMBB || TargetMBB != &MBB) + return false; + + // Count instructions from the beginning of the block to the branch + // A short loop is 6 instructions or fewer (including branch + delay slot) + // The delay slot adds 1 more, so we check if instructions before branch <= 5 + unsigned InstrCount = 0; + bool HasOtherBranch = false; + + for (const MachineInstr &Instr : MBB) { + if (&Instr == MI) + break; + + // Skip debug and pseudo instructions + if (Instr.isDebugInstr() || Instr.isTransient()) + continue; + + ++InstrCount; + + // If there's another branch in the loop, the erratum doesn't apply + if (Instr.isBranch() || Instr.isCall()) { + HasOtherBranch = true; + break; + } + } + + // If there's another branch/call in the loop, erratum doesn't apply + if (HasOtherBranch) + return false; + + // Add 1 for the branch itself, +1 for delay slot = InstrCount + 2 + // Erratum triggers when total <= 6, so InstrCount + 2 <= 6 => InstrCount <= 4 + // But we're conservative: if InstrCount <= 5 (total <= 7), skip filling + // to match the exact condition from r5900check: offset -5 to -1 (2-6 instrs) + return InstrCount <= 5; +} + INITIALIZE_PASS(MipsDelaySlotFiller, DEBUG_TYPE, "Fill delay slot for MIPS", false, false) @@ -587,10 +648,20 @@ bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) { if (!hasUnoccupiedSlot(&*I)) continue; - // Delay slot filling is disabled at -O0, or in microMIPS32R6. - if (!DisableDelaySlotFiller && - (TM->getOptLevel() != CodeGenOptLevel::None) && - !(InMicroMipsMode && STI.hasMips32r6())) { + // R5900 short loop erratum fix: skip delay slot filling for short backward + // loops to avoid triggering a hardware bug where short loops may exit + // early. + if (STI.isR5900() && isR5900ShortLoopBranch(&*I, MBB)) { + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": skipping delay slot fill for R5900 " + "short loop branch.\n"); + ++R5900ShortLoopNops; + // Fall through to insert NOP in delay slot + } + // Delay slot filling is disabled at -O0, in microMIPS32R6, or for R5900 + // short loop branches. + else if (!DisableDelaySlotFiller && + (TM->getOptLevel() != CodeGenOptLevel::None) && + !(InMicroMipsMode && STI.hasMips32r6())) { bool Filled = false; diff --git a/llvm/test/CodeGen/Mips/r5900-short-loop.ll b/llvm/test/CodeGen/Mips/r5900-short-loop.ll new file mode 100644 index 0000000000000..a66f417f0c854 --- /dev/null +++ b/llvm/test/CodeGen/Mips/r5900-short-loop.ll @@ -0,0 +1,59 @@ +; RUN: llc -mtriple=mips64el -mcpu=r5900 < %s | FileCheck %s -check-prefix=FIX +; +; Test R5900 short loop erratum fix. +; The R5900 has a hardware bug where short loops (6 instructions or fewer) +; with a branch may exit after 1-2 iterations instead of the expected count. +; The fix ensures the delay slot contains a NOP for such short backward branches. +; The fix is always enabled for R5900 - there is no way to disable it. + +; Short loop test with store - delay slot NOT filled due to short loop fix +; bnez followed by nop (short loop workaround) + +; FIX-LABEL: test_short_loop_store: +; FIX: .LBB0_1: +; FIX: bnez +; FIX-NEXT: nop +define void @test_short_loop_store(ptr %arr, i32 %n) { +entry: + br label %loop + +loop: + %i = phi i32 [ 0, %entry ], [ %inc, %loop ] + %ptr = getelementptr i32, ptr %arr, i32 %i + store i32 %i, ptr %ptr + %inc = add i32 %i, 1 + %cmp = icmp slt i32 %inc, %n + br i1 %cmp, label %loop, label %exit + +exit: + ret void +} + +; Long loop - should NOT be affected by the fix (too many instructions) +; Delay slot can be filled since loop is longer than 6 instructions +; The scheduler may choose different instructions for the delay slot +; FIX-LABEL: test_long_loop: +; FIX: .LBB1_1: +; FIX: bnez ${{[0-9]+}}, .LBB1_1 +; Delay slot should be filled with actual instruction, not nop +; FIX-NEXT: {{sw|daddiu|addu}} +define i32 @test_long_loop(ptr %arr, i32 %n) { +entry: + br label %loop + +loop: + %i = phi i32 [ 0, %entry ], [ %inc, %loop ] + %sum = phi i32 [ 0, %entry ], [ %add, %loop ] + %ptr = getelementptr i32, ptr %arr, i32 %i + %val = load i32, ptr %ptr + %mul = mul i32 %val, %i + %add = add i32 %sum, %mul + %ptr2 = getelementptr i32, ptr %arr, i32 %add + store i32 %add, ptr %ptr2 + %inc = add i32 %i, 1 + %cmp = icmp slt i32 %inc, %n + br i1 %cmp, label %loop, label %exit + +exit: + ret i32 %add +} >From e80982d27cfc71d04a420371a5e2d1ce0fdfa4f4 Mon Sep 17 00:00:00 2001 From: Rick Gaiser <[email protected]> Date: Sun, 18 Jan 2026 13:25:11 +0100 Subject: [PATCH 4/6] [Mips] Set ISA extension AFL_EXT_5900 for r5900 Set the ISA extension field in .MIPS.abiflags to AFL_EXT_5900 when targeting the R5900, matching binutils behavior. This marks object files as compiled for the R5900, enabling linker compatibility checking. Also rename the display name in llvm-readobj from "MIPS R5900" to "Toshiba R5900" to match binutils readelf output. --- llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h | 2 ++ llvm/test/CodeGen/Mips/cpus.ll | 1 + llvm/tools/llvm-readobj/ELFDumper.cpp | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h index 1a5bb64863ee8..f7b2fa5537d31 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -143,6 +143,8 @@ struct MipsABIFlagsSection { ISAExtension = Mips::AFL_EXT_OCTEONP; else if (P.hasCnMips()) ISAExtension = Mips::AFL_EXT_OCTEON; + else if (P.isR5900()) + ISAExtension = Mips::AFL_EXT_5900; else ISAExtension = Mips::AFL_EXT_NONE; } diff --git a/llvm/test/CodeGen/Mips/cpus.ll b/llvm/test/CodeGen/Mips/cpus.ll index 14e7476d8f9ef..05d9a89660b7b 100644 --- a/llvm/test/CodeGen/Mips/cpus.ll +++ b/llvm/test/CodeGen/Mips/cpus.ll @@ -61,6 +61,7 @@ ; RUN: llc -mtriple=mips64el -mcpu=r5900 -filetype=obj < %s \ ; RUN: | llvm-readelf -A - | FileCheck %s --check-prefix=R5900 ; R5900: ISA: MIPS3 +; R5900: ISA Extension: Toshiba R5900 ; Check that we reject CPUs that are not implemented. diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 96c4668984965..0189c04bd1f03 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -3326,6 +3326,7 @@ MipsGOTParser<ELFT>::getPltSym(const Entry *E) const { } } +// clang-format off const EnumEntry<unsigned> ElfMipsISAExtType[] = { {"None", Mips::AFL_EXT_NONE}, {"Broadcom SB-1", Mips::AFL_EXT_SB1}, @@ -3338,7 +3339,6 @@ const EnumEntry<unsigned> ElfMipsISAExtType[] = { {"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F}, {"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A}, {"MIPS R4650", Mips::AFL_EXT_4650}, - {"MIPS R5900", Mips::AFL_EXT_5900}, {"MIPS R10000", Mips::AFL_EXT_10000}, {"NEC VR4100", Mips::AFL_EXT_4100}, {"NEC VR4111/VR4181", Mips::AFL_EXT_4111}, @@ -3346,8 +3346,10 @@ const EnumEntry<unsigned> ElfMipsISAExtType[] = { {"NEC VR5400", Mips::AFL_EXT_5400}, {"NEC VR5500", Mips::AFL_EXT_5500}, {"RMI Xlr", Mips::AFL_EXT_XLR}, - {"Toshiba R3900", Mips::AFL_EXT_3900} + {"Toshiba R3900", Mips::AFL_EXT_3900}, + {"Toshiba R5900", Mips::AFL_EXT_5900}, }; +// clang-format on const EnumEntry<unsigned> ElfMipsASEFlags[] = { {"DSP", Mips::AFL_ASE_DSP}, >From 1bbe1086a9268df7e620add679d6f3910ac25525 Mon Sep 17 00:00:00 2001 From: Rick Gaiser <[email protected]> Date: Sun, 18 Jan 2026 13:22:18 +0100 Subject: [PATCH 5/6] [clang][Mips] Add missing i6400 and i6500 to CPU test The test for valid MIPS CPU names was missing entries for i6400 and i6500, which are valid CPUs defined in LLVM. --- clang/test/Misc/target-invalid-cpu-note/mips.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/test/Misc/target-invalid-cpu-note/mips.c b/clang/test/Misc/target-invalid-cpu-note/mips.c index 17b6ff9c57084..e9d21b2253485 100644 --- a/clang/test/Misc/target-invalid-cpu-note/mips.c +++ b/clang/test/Misc/target-invalid-cpu-note/mips.c @@ -23,4 +23,6 @@ // CHECK-SAME: {{^}}, octeon // CHECK-SAME: {{^}}, octeon+ // CHECK-SAME: {{^}}, p5600 +// CHECK-SAME: {{^}}, i6400 +// CHECK-SAME: {{^}}, i6500 // CHECK-SAME: {{$}} >From 92358eb1733b6876cabc62314086a6920e583aae Mon Sep 17 00:00:00 2001 From: Rick Gaiser <[email protected]> Date: Sun, 18 Jan 2026 15:53:34 +0100 Subject: [PATCH 6/6] [clang][Mips] Add r5900 CPU support --- clang/lib/Basic/Targets/Mips.cpp | 4 +++- clang/test/Misc/target-invalid-cpu-note/mips.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/clang/lib/Basic/Targets/Mips.cpp b/clang/lib/Basic/Targets/Mips.cpp index a999d1410d254..76c9081567053 100644 --- a/clang/lib/Basic/Targets/Mips.cpp +++ b/clang/lib/Basic/Targets/Mips.cpp @@ -46,6 +46,7 @@ bool MipsTargetInfo::processorSupportsGPR64() const { .Case("mips64r6", true) .Case("octeon", true) .Case("octeon+", true) + .Case("r5900", true) .Case("i6400", true) .Case("i6500", true) .Default(false); @@ -55,7 +56,8 @@ static constexpr llvm::StringLiteral ValidCPUNames[] = { {"mips1"}, {"mips2"}, {"mips3"}, {"mips4"}, {"mips5"}, {"mips32"}, {"mips32r2"}, {"mips32r3"}, {"mips32r5"}, {"mips32r6"}, {"mips64"}, {"mips64r2"}, {"mips64r3"}, {"mips64r5"}, {"mips64r6"}, - {"octeon"}, {"octeon+"}, {"p5600"}, {"i6400"}, {"i6500"}}; + {"octeon"}, {"octeon+"}, {"p5600"}, {"r5900"}, {"i6400"}, + {"i6500"}}; bool MipsTargetInfo::isValidCPUName(StringRef Name) const { return llvm::is_contained(ValidCPUNames, Name); diff --git a/clang/test/Misc/target-invalid-cpu-note/mips.c b/clang/test/Misc/target-invalid-cpu-note/mips.c index e9d21b2253485..738362edf3c80 100644 --- a/clang/test/Misc/target-invalid-cpu-note/mips.c +++ b/clang/test/Misc/target-invalid-cpu-note/mips.c @@ -23,6 +23,7 @@ // CHECK-SAME: {{^}}, octeon // CHECK-SAME: {{^}}, octeon+ // CHECK-SAME: {{^}}, p5600 +// CHECK-SAME: {{^}}, r5900 // CHECK-SAME: {{^}}, i6400 // CHECK-SAME: {{^}}, i6500 // CHECK-SAME: {{$}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
