From 83fbe074471099dbca95c1528fdba5ddacd0e127 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:50:10 +0100 Subject: [PATCH 01/22] external/llvm: Backport MIPS fixed-register support Backport the MIPS -ffixed-N implementation from llvm/llvm-project#217013. This also includes named-register support needed by LLVM 13 from upstream commit 64dfc26237d9. --- .../clang/include/clang/Driver/Options.td | 3 + .../clang/lib/Driver/ToolChains/Arch/Mips.cpp | 38 +++++++ .../llvm/dist/llvm/lib/Target/Mips/Mips.td | 5 + .../llvm/lib/Target/Mips/MipsISelLowering.cpp | 103 +++++++++++++++--- .../llvm/lib/Target/Mips/MipsISelLowering.h | 2 + .../llvm/lib/Target/Mips/MipsRegisterInfo.cpp | 6 + .../dist/llvm/lib/Target/Mips/MipsSubtarget.h | 9 ++ 7 files changed, 149 insertions(+), 17 deletions(-) diff --git a/external/apache2/llvm/dist/clang/include/clang/Driver/Options.td b/external/apache2/llvm/dist/clang/include/clang/Driver/Options.td index b08aac7071dcc..aa644235e7a0f 100644 --- a/external/apache2/llvm/dist/clang/include/clang/Driver/Options.td +++ b/external/apache2/llvm/dist/clang/include/clang/Driver/Options.td @@ -3460,6 +3460,9 @@ def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">, Group; def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">, Group; +foreach i = {1-31} in + def ffixed_#i : Flag<["-"], "ffixed-"#i>, Group, + HelpText<"Reserve the MIPS GPR "#i#" register (MIPS only)">; def mbranch_likely : Flag<["-"], "mbranch-likely">, Group, IgnoredGCCCompat; def mno_branch_likely : Flag<["-"], "mno-branch-likely">, Group, diff --git a/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/Arch/Mips.cpp index 5a509dbb2bd31..dd976a4c54542 100644 --- a/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/Arch/Mips.cpp @@ -196,6 +196,44 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, getMipsCPUAndABI(Args, Triple, CPUName, ABIName); ABIName = getGnuCompatibleMipsABIName(ABIName); + // Handle features corresponding to GCC's -ffixed-REG options. MIPS spells + // its GPRs numerically, so preserve that spelling in the driver interface. +#define RESERVE_GPR(REG) \ + if (Args.hasArg(options::OPT_ffixed_##REG)) \ + Features.push_back("+reserve-gpr" #REG); + RESERVE_GPR(1) + RESERVE_GPR(2) + RESERVE_GPR(3) + RESERVE_GPR(4) + RESERVE_GPR(5) + RESERVE_GPR(6) + RESERVE_GPR(7) + RESERVE_GPR(8) + RESERVE_GPR(9) + RESERVE_GPR(10) + RESERVE_GPR(11) + RESERVE_GPR(12) + RESERVE_GPR(13) + RESERVE_GPR(14) + RESERVE_GPR(15) + RESERVE_GPR(16) + RESERVE_GPR(17) + RESERVE_GPR(18) + RESERVE_GPR(19) + RESERVE_GPR(20) + RESERVE_GPR(21) + RESERVE_GPR(22) + RESERVE_GPR(23) + RESERVE_GPR(24) + RESERVE_GPR(25) + RESERVE_GPR(26) + RESERVE_GPR(27) + RESERVE_GPR(28) + RESERVE_GPR(29) + RESERVE_GPR(30) + RESERVE_GPR(31) +#undef RESERVE_GPR + // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI // extension was developed by Richard Sandiford & Code Sourcery to support diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/Mips.td b/external/apache2/llvm/dist/llvm/lib/Target/Mips/Mips.td index 792960332bcc7..d3523515528d2 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/Mips.td +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/Mips.td @@ -218,6 +218,11 @@ include "MipsInstrInfo.td" include "MipsCallingConv.td" include "MipsRegisterBanks.td" +foreach i = {1-31} in + def FeatureReserveGPR#i : + SubtargetFeature<"reserve-gpr"#i, "UserReservedGPR["#i#"]", "true", + "Reserve MIPS GPR "#i>; + // Avoid forward declaration issues. include "MipsScheduleP5600.td" include "MipsScheduleGeneric.td" diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.cpp index 7d5c71980c496..4f6ea857a9fe7 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -73,6 +73,7 @@ #include #include #include +#include #include #include @@ -4707,27 +4708,95 @@ MipsTargetLowering::emitPseudoD_SELECT(MachineInstr &MI, return BB; } -// FIXME? Maybe this could be a TableGen attribute on some registers and -// this table could be generated automatically from RegInfo. +// Copies the function MipsAsmParser::matchCPURegisterName. +int MipsTargetLowering::getCPURegisterIndex(StringRef Name) const { + int CC = StringSwitch(Name) + .Case("zero", 0) + .Case("at", 1) + .Case("a0", 4) + .Case("a1", 5) + .Case("a2", 6) + .Case("a3", 7) + .Case("v0", 2) + .Case("v1", 3) + .Case("s0", 16) + .Case("s1", 17) + .Case("s2", 18) + .Case("s3", 19) + .Case("s4", 20) + .Case("s5", 21) + .Case("s6", 22) + .Case("s7", 23) + .Case("k0", 26) + .Case("k1", 27) + .Case("gp", 28) + .Case("sp", 29) + .Case("fp", 30) + .Case("s8", 30) + .Case("ra", 31) + .Case("t0", 8) + .Case("t1", 9) + .Case("t2", 10) + .Case("t3", 11) + .Case("t4", 12) + .Case("t5", 13) + .Case("t6", 14) + .Case("t7", 15) + .Case("t8", 24) + .Case("t9", 25) + .Default(-1); + + if (!(ABI.IsN32() || ABI.IsN64())) + return CC; + + if (8 <= CC && CC <= 11) + CC += 4; + + if (CC == -1) + CC = StringSwitch(Name) + .Case("a4", 8) + .Case("a5", 9) + .Case("a6", 10) + .Case("a7", 11) + .Case("kt0", 26) + .Case("kt1", 27) + .Default(-1); + + return CC; +} + Register MipsTargetLowering::getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const { - // Named registers is expected to be fairly rare. For now, just support $28 - // since the linux kernel uses it. - if (Subtarget.isGP64bit()) { - Register Reg = StringSwitch(RegName) - .Case("$28", Mips::GP_64) - .Default(Register()); - if (Reg) - return Reg; - } else { - Register Reg = StringSwitch(RegName) - .Case("$28", Mips::GP) - .Default(Register()); - if (Reg) - return Reg; + StringRef Name(RegName); + Name.consume_front("$"); + + unsigned RegIdx; + if (Name.getAsInteger(10, RegIdx)) { + std::string LowerName = Name.lower(); + int NamedRegIdx = getCPURegisterIndex(LowerName); + if (NamedRegIdx < 0) + report_fatal_error( + Twine("Invalid register name \"" + StringRef(RegName) + "\".")); + RegIdx = NamedRegIdx; } - report_fatal_error("Invalid register name global variable"); + + if (RegIdx < 32) { + const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo(); + const MCRegisterClass &RC = Subtarget.isGP64bit() + ? MRI->getRegClass(Mips::GPR64RegClassID) + : MRI->getRegClass(Mips::GPR32RegClassID); + Register Reg = RC.getRegister(RegIdx); + BitVector ReservedRegs = + Subtarget.getRegisterInfo()->getReservedRegs(MF); + if (!ReservedRegs.test(Reg)) + report_fatal_error(Twine("Trying to obtain non-reserved register \"" + + StringRef(RegName) + "\".")); + return Reg; + } + + report_fatal_error( + Twine("Invalid register name \"" + StringRef(RegName) + "\".")); } MachineBasicBlock *MipsTargetLowering::emitLDR_W(MachineInstr &MI, diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.h b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.h index 3820c42ba8aa7..e75009b426d30 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.h @@ -671,6 +671,8 @@ class TargetRegisterClass; return true; } + int getCPURegisterIndex(StringRef Name) const; + /// Emit a sign-extension using sll/sra, seb, or seh appropriately. MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI, MachineBasicBlock *BB, diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsRegisterInfo.cpp index 7cba3118cd627..57ca72adbf33c 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsRegisterInfo.cpp @@ -172,6 +172,12 @@ getReservedRegs(const MachineFunction &MF) const { for (unsigned I = 0; I < array_lengthof(ReservedGPR64); ++I) Reserved.set(ReservedGPR64[I]); + // Mark user-reserved GPRs and their 64-bit super-registers. GPR32 is + // deliberately ordered by architectural register number. + for (unsigned I = 1; I < 32; ++I) + if (Subtarget.isGPRReservedByUser(I)) + markSuperRegs(Reserved, Mips::GPR32RegClass.getRegister(I)); + // For mno-abicalls, GP is a program invariant! if (!Subtarget.isABICalls()) { Reserved.set(Mips::GP); diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsSubtarget.h b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsSubtarget.h index 2b4c2b19a95d1..01577db98d7c0 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsSubtarget.h @@ -26,6 +26,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/Support/ErrorHandling.h" +#include #include #define GET_SUBTARGETINFO_HEADER @@ -102,6 +103,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // IsGP64bit - General-purpose registers are 64 bits wide bool IsGP64bit; + // MIPS GPRs explicitly reserved through -ffixed-REG. + std::bitset<32> UserReservedGPR; + // IsPTR64bit - Pointers are 64 bit wide bool IsPTR64bit; @@ -233,6 +237,11 @@ class MipsSubtarget : public MipsGenSubtargetInfo { const MipsABIInfo &getABI() const; bool isABI_FPXX() const { return isABI_O32() && IsFPXX; } + bool isGPRReservedByUser(unsigned GPR) const { + assert(GPR < UserReservedGPR.size() && "GPR number out of range"); + return UserReservedGPR[GPR]; + } + /// This constructor initializes the data members to match that /// of the specified triple. MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, bool little, From 0d6ff33db127977ea4d25a6e6ce43c45294707bc Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:50:18 +0100 Subject: [PATCH 02/22] external/llvm: Backport o32 support on 64-bit MIPS CPUs Backport llvm-project commits 7983f8aca82e and e676866368a8. The latter is adapted to cover LLVM 13's fixed and variadic calling-convention paths. --- .../dist/clang/lib/Basic/Targets/Mips.cpp | 25 ------------------- .../Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 8 +++--- .../Target/Mips/MCTargetDesc/MipsABIInfo.h | 2 +- .../llvm/lib/Target/Mips/MipsCallLowering.cpp | 3 ++- .../llvm/lib/Target/Mips/MipsCallingConv.td | 6 +++-- .../llvm/lib/Target/Mips/MipsISelLowering.cpp | 2 +- .../llvm/lib/Target/Mips/MipsSubtarget.cpp | 3 +-- 7 files changed, 14 insertions(+), 35 deletions(-) diff --git a/external/apache2/llvm/dist/clang/lib/Basic/Targets/Mips.cpp b/external/apache2/llvm/dist/clang/lib/Basic/Targets/Mips.cpp index 3a32fd492c6bb..ccca5d0fb13b5 100644 --- a/external/apache2/llvm/dist/clang/lib/Basic/Targets/Mips.cpp +++ b/external/apache2/llvm/dist/clang/lib/Basic/Targets/Mips.cpp @@ -238,37 +238,12 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const { Diags.Report(diag::err_target_unsupported_cpu_for_micromips) << CPU; return false; } - // FIXME: It's valid to use O32 on a 64-bit CPU but the backend can't handle - // this yet. It's better to fail here than on the backend assertion. - if (processorSupportsGPR64() && ABI == "o32") { - Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU; - return false; - } - // 64-bit ABI's require 64-bit CPU's. if (!processorSupportsGPR64() && (ABI == "n32" || ABI == "n64")) { Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU; return false; } - // FIXME: It's valid to use O32 on a mips64/mips64el triple but the backend - // can't handle this yet. It's better to fail here than on the - // backend assertion. - if (getTriple().isMIPS64() && ABI == "o32") { - Diags.Report(diag::err_target_unsupported_abi_for_triple) - << ABI << getTriple().str(); - return false; - } - - // FIXME: It's valid to use N32/N64 on a mips/mipsel triple but the backend - // can't handle this yet. It's better to fail here than on the - // backend assertion. - if (getTriple().isMIPS32() && (ABI == "n32" || ABI == "n64")) { - Diags.Report(diag::err_target_unsupported_abi_for_triple) - << ABI << getTriple().str(); - return false; - } - // -fpxx is valid only for the o32 ABI if (FPMode == FPXX && (ABI == "n32" || ABI == "n64")) { Diags.Report(diag::err_unsupported_abi_for_opt) << "-mfpxx" << "o32"; diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index 3315a8ba18d64..2cc6ee399c377 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -37,9 +37,12 @@ ArrayRef MipsABIInfo::GetByValArgRegs() const { llvm_unreachable("Unhandled ABI"); } -ArrayRef MipsABIInfo::GetVarArgRegs() const { - if (IsO32()) +ArrayRef MipsABIInfo::getVarArgRegs(bool IsGP64Bit) const { + if (IsO32()) { + if (IsGP64Bit) + return makeArrayRef(Mips64IntRegs); return makeArrayRef(O32IntRegs); + } if (IsN32() || IsN64()) return makeArrayRef(Mips64IntRegs); llvm_unreachable("Unhandled ABI"); @@ -124,4 +127,3 @@ unsigned MipsABIInfo::GetEhDataReg(unsigned I) const { return IsN64() ? EhDataReg64[I] : EhDataReg[I]; } - diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h index 046cc686b3118..2fa49a73fbbdc 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h @@ -46,7 +46,7 @@ class MipsABIInfo { ArrayRef GetByValArgRegs() const; /// The registers to use for the variable argument list. - ArrayRef GetVarArgRegs() const; + ArrayRef getVarArgRegs(bool IsGP64Bit) const; /// Obtain the size of the area allocated by the callee for arguments. /// CallingConv::FastCall affects the value for O32. diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsCallLowering.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsCallLowering.cpp index 9cd6f7f9e151d..85c4baee80dcd 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsCallLowering.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsCallLowering.cpp @@ -463,7 +463,8 @@ bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, return false; if (F.isVarArg()) { - ArrayRef ArgRegs = ABI.GetVarArgRegs(); + ArrayRef ArgRegs = + ABI.getVarArgRegs(MF.getSubtarget().isGP64bit()); unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs); int VaArgOffset; diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsCallingConv.td b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsCallingConv.td index 204f11f1107cf..e044e46e6928c 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsCallingConv.td +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsCallingConv.td @@ -339,14 +339,16 @@ def CC_Mips_FixedArg : CallingConv<[ CCIfCC<"CallingConv::Fast", CCDelegateTo>, - CCIfSubtarget<"isABI_O32()", CCDelegateTo>, + CCIfSubtarget<"isABI_O32()", + CCIfSubtargetNot<"isGP64bit()", CCDelegateTo>>, CCDelegateTo ]>; def CC_Mips_VarArg : CallingConv<[ CCIfByVal>, - CCIfSubtarget<"isABI_O32()", CCDelegateTo>, + CCIfSubtarget<"isABI_O32()", + CCIfSubtargetNot<"isGP64bit()", CCDelegateTo>>, CCDelegateTo ]>; diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.cpp index 4f6ea857a9fe7..15f130288d20c 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -4466,7 +4466,7 @@ void MipsTargetLowering::writeVarArgRegs(std::vector &OutChains, SDValue Chain, const SDLoc &DL, SelectionDAG &DAG, CCState &State) const { - ArrayRef ArgRegs = ABI.GetVarArgRegs(); + ArrayRef ArgRegs = ABI.getVarArgRegs(Subtarget.isGP64bit()); unsigned Idx = State.getFirstUnallocated(ArgRegs); unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); MVT RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsSubtarget.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsSubtarget.cpp index 8bb9d75e9173a..9b3edb5878a71 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -99,8 +99,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, report_fatal_error("Code generation for MIPS-V is not implemented", false); // Check if Architecture and ABI are compatible. - assert(((!isGP64bit() && isABI_O32()) || - (isGP64bit() && (isABI_N32() || isABI_N64()))) && + assert(((!isGP64bit() && isABI_O32()) || isGP64bit()) && "Invalid Arch & ABI pair."); if (hasMSA() && !isFP64bit()) From d337713cd4755a6e100b3b6b28e722ed3e688ce9 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:50:42 +0100 Subject: [PATCH 03/22] external/llvm: Backport MIPS immediate expression support Backport llvm-project commit b65e0947cade (llvm/llvm-project#127581), adapted to the LLVM 13 MC interfaces. --- .../Mips/MCTargetDesc/MipsAsmBackend.cpp | 7 ++++++ .../Target/Mips/MCTargetDesc/MipsBaseInfo.h | 4 +++ .../Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 3 ++- .../Target/Mips/MCTargetDesc/MipsFixupKinds.h | 3 +++ .../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 25 +++++++++++++++++-- .../Mips/MCTargetDesc/MipsMCCodeEmitter.h | 4 +++ 6 files changed, 43 insertions(+), 3 deletions(-) diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 94d338746a6c2..c3ab44c89a40c 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -63,6 +63,11 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case Mips::fixup_MIPS_PCLO16: Value &= 0xffff; break; + case Mips::fixup_Mips_AnyImm16: + if (!isInt<16>(Value) && !isUInt<16>(Value)) + Ctx.reportError(Fixup.getLoc(), + "fixup value out of range [-32768, 65535]"); + break; case FK_DTPRel_4: case FK_DTPRel_8: case FK_TPRel_4: @@ -355,6 +360,7 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_Mips_26", 0, 26, 0 }, { "fixup_Mips_HI16", 0, 16, 0 }, { "fixup_Mips_LO16", 0, 16, 0 }, + { "fixup_Mips_AnyImm16", 0, 16, 0 }, { "fixup_Mips_GPREL16", 0, 16, 0 }, { "fixup_Mips_LITERAL", 0, 16, 0 }, { "fixup_Mips_GOT", 0, 16, 0 }, @@ -434,6 +440,7 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_Mips_26", 6, 26, 0 }, { "fixup_Mips_HI16", 16, 16, 0 }, { "fixup_Mips_LO16", 16, 16, 0 }, + { "fixup_Mips_AnyImm16", 16, 16, 0 }, { "fixup_Mips_GPREL16", 16, 16, 0 }, { "fixup_Mips_LITERAL", 16, 16, 0 }, { "fixup_Mips_GOT", 16, 16, 0 }, diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index 02ab5ede2c1a4..14e5b1f891548 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -134,6 +134,10 @@ namespace MipsII { OPERAND_MEM_SIMM9 = OPERAND_FIRST_MIPS_MEM_IMM, OPERAND_LAST_MIPS_MEM_IMM = OPERAND_MEM_SIMM9 }; + + static inline unsigned getFormat(uint64_t TSFlags) { + return TSFlags & FormMask; + } } } diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 9c317e3f8840f..3f94384ca3e1b 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -388,7 +388,8 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, return ELF::R_MICROMIPS_JALR; } - llvm_unreachable("invalid fixup kind!"); + Ctx.reportError(Fixup.getLoc(), "unsupported relocation type"); + return ELF::R_MIPS_NONE; } /// Sort relocation table entries by offset except where another order is diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index b83d822bd8d03..2305768438c9c 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -40,6 +40,9 @@ namespace Mips { // Pure lower 16 bit fixup resulting in - R_MIPS_LO16. fixup_Mips_LO16, + // 16-bit fixup that must be resolved by the assembler. + fixup_Mips_AnyImm16, + // 16 bit fixup for GP offest resulting in - R_MIPS_GPREL16. fixup_Mips_GPREL16, diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index b81ebedfb9c74..190250115e091 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "MipsMCCodeEmitter.h" +#include "MCTargetDesc/MipsBaseInfo.h" #include "MCTargetDesc/MipsFixupKinds.h" #include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" @@ -743,9 +744,29 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, } else if (MO.isDFPImm()) { return static_cast(bit_cast(MO.getDFPImm())); } - // MO must be an Expr. + // TODO: Set EncoderMethod to "getImmOpValue" for immediate operands so + // getMachineOpValue will not be called for expression code paths. assert(MO.isExpr()); - return getExprOpValue(MO.getExpr(),Fixups, STI); + return getImmOpValue(MI, MO, Fixups, STI); +} + +unsigned MipsMCCodeEmitter::getImmOpValue( + const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + if (MO.isImm()) + return MO.getImm(); + assert(MO.isExpr() && "getImmOpValue expects an expression or immediate"); + const MCExpr *Expr = MO.getExpr(); + int64_t Res; + if (Expr->evaluateAsAbsolute(Res)) + return Res; + unsigned Form = MipsII::getFormat(MCII.get(MI.getOpcode()).TSFlags); + if (!isa(Expr) && Form == MipsII::FrmI) { + Fixups.push_back(MCFixup::create( + 0, Expr, MCFixupKind(Mips::fixup_Mips_AnyImm16))); + return 0; + } + return getExprOpValue(Expr, Fixups, STI); } /// Return binary encoding of memory related operand. diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 16e94c723b347..ed7e22feeade3 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -181,6 +181,10 @@ class MipsMCCodeEmitter : public MCCodeEmitter { SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getImmOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; From 0a963dd254ee5a5e340499ec175e502002c6619d Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:50:48 +0100 Subject: [PATCH 04/22] external/llvm: Backport build compatibility fixes Backport llvm-project commits 3ee9a2b63cfd (MIPS Memory.inc includes), 7abf44069aec (explicit cstdint include), and 8d5c0b8768f7 (valid integer conversion in typeinfo). --- external/apache2/llvm/dist/libcxx/include/typeinfo | 2 +- .../apache2/llvm/dist/llvm/lib/Support/Unix/Memory.inc | 8 -------- .../llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h | 1 + 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/external/apache2/llvm/dist/libcxx/include/typeinfo b/external/apache2/llvm/dist/libcxx/include/typeinfo index 70f372aacfe95..c5ed4ff8839cb 100644 --- a/external/apache2/llvm/dist/libcxx/include/typeinfo +++ b/external/apache2/llvm/dist/libcxx/include/typeinfo @@ -248,7 +248,7 @@ struct __type_info_implementations { _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __v) _NOEXCEPT { if (__is_type_name_unique(__v)) - return reinterpret_cast(__v); + return __v; return __non_unique_impl::__hash(__type_name_to_string(__v)); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE diff --git a/external/apache2/llvm/dist/llvm/lib/Support/Unix/Memory.inc b/external/apache2/llvm/dist/llvm/lib/Support/Unix/Memory.inc index be88e7db14002..b83477e0e4cc6 100644 --- a/external/apache2/llvm/dist/llvm/lib/Support/Unix/Memory.inc +++ b/external/apache2/llvm/dist/llvm/lib/Support/Unix/Memory.inc @@ -29,14 +29,6 @@ #include #endif -#if defined(__mips__) -# if defined(__OpenBSD__) -# include -# elif !defined(__FreeBSD__) -# include -# endif -#endif - #if defined(__APPLE__) extern "C" void sys_icache_invalidate(const void *Addr, size_t len); #else diff --git a/external/apache2/llvm/dist/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h b/external/apache2/llvm/dist/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h index 35604cd3ec0a2..93cb72ad7f8fc 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h +++ b/external/apache2/llvm/dist/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h @@ -13,6 +13,7 @@ #ifndef LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCTARGETDESC_H #define LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCTARGETDESC_H +#include #include #include From 2572de29aa1eae3124e72b3f43902bcc72190a08 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 17:47:21 +0100 Subject: [PATCH 05/22] external/llvm: Backport MIPS PIC la symbol binding fix Backport llvm-project commit eac7a7346250 (llvm/llvm-project#217566), adapted to LLVM 13. Use ELF symbol binding, rather than section membership, to decide whether PIC la expansion should use the local or global GOT form. This avoids adding a symbol low part twice for globals defined before their use. --- .../dist/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/external/apache2/llvm/dist/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index e4d61f8c210e7..4c96afc8d753b 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -2927,11 +2927,11 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, bool IsPtr64 = ABI.ArePtrs64bit(); bool IsLocalSym = - Res.getSymA()->getSymbol().isInSection() || Res.getSymA()->getSymbol().isTemporary() || - (Res.getSymA()->getSymbol().isELF() && - cast(Res.getSymA()->getSymbol()).getBinding() == - ELF::STB_LOCAL); + (Res.getSymA()->getSymbol().isELF() + ? cast(Res.getSymA()->getSymbol()).getBinding() == + ELF::STB_LOCAL + : Res.getSymA()->getSymbol().isInSection()); bool UseXGOT = STI->getFeatureBits()[Mips::FeatureXGOT] && !IsLocalSym; // The case where the result register is $25 is somewhat special. If the From 8e27f5622b2f43ce398e39e819ca0359cad5d419 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 17:48:40 +0100 Subject: [PATCH 06/22] external/llvm: Backport MIPS branch delay-slot fix Backport llvm-project commit 4639fa213220 (llvm/llvm-project#217565), adapted to LLVM 13. Mark immediate conditional-branch macros as having delay slots so the integrated assembler inserts a nop under .set reorder. Without this, a following branch can be emitted in the delay slot and trap as a reserved instruction. --- .../apache2/llvm/dist/llvm/lib/Target/Mips/MipsInstrInfo.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsInstrInfo.td b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsInstrInfo.td index 089fed9ec0bf4..2d1497684e12e 100644 --- a/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/external/apache2/llvm/dist/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -2972,7 +2972,7 @@ def BLEUL: CondBranchPseudo<"bleul">, ISA_MIPS2_NOT_32R6_64R6; def BGEUL: CondBranchPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6; def BGTUL: CondBranchPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; -let isCTI = 1 in +let hasDelaySlot = 1, isCTI = 1 in class CondBranchImmPseudo : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset), !strconcat(instr_asm, "\t$rs, $imm, $offset")>; From 72f94522cac08942a835ea2f7e9f4da829c10477 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:51:02 +0100 Subject: [PATCH 07/22] mips: Use compiler-rt and libc++ with Clang Set compiler-rt and libc++ as the defaults for all four MIPS ABIs in bsd.own.mk and the Clang NetBSD driver. Build clear_cache.c into MIPS libc and implement __clear_cache() with the NetBSD _cacheflush() function. --- .../dist/clang/lib/Driver/ToolChains/NetBSD.cpp | 8 ++++++++ lib/libc/compiler_rt/Makefile.inc | 5 +++++ share/mk/bsd.own.mk | 8 ++++++++ .../compiler_rt/dist/lib/builtins/clear_cache.c | 15 ++++++++++----- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/NetBSD.cpp b/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/NetBSD.cpp index 1ce5a2a203c24..010cc94fcdd50 100644 --- a/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/NetBSD.cpp +++ b/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/NetBSD.cpp @@ -276,6 +276,10 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: @@ -414,6 +418,10 @@ ToolChain::CXXStdlibType NetBSD::GetDefaultCXXStdlibType() const { case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: diff --git a/lib/libc/compiler_rt/Makefile.inc b/lib/libc/compiler_rt/Makefile.inc index 3306df6746eab..4b140491f121b 100644 --- a/lib/libc/compiler_rt/Makefile.inc +++ b/lib/libc/compiler_rt/Makefile.inc @@ -287,6 +287,11 @@ LINTFLAGS.trunctfdf2.c += -X 117,132 LINTFLAGS.trunctfsf2.c += -X 117,132 .endif +.if ${LIBC_MACHINE_CPU} == "mips" +GENERIC_SRCS+= \ + clear_cache.c +.endif + .if ${LIBC_MACHINE_ARCH} == "powerpc" || ${LIBC_MACHINE_ARCH} == "powerpc64" GENERIC_SRCS+= \ clear_cache.c diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk index b828fbd8e456b..bae3e66818a24 100644 --- a/share/mk/bsd.own.mk +++ b/share/mk/bsd.own.mk @@ -243,6 +243,10 @@ _LIBC_COMPILER_RT.${MACHINE_ARCH}= yes _LIBC_COMPILER_RT.aarch64= yes _LIBC_COMPILER_RT.aarch64eb= yes _LIBC_COMPILER_RT.i386= yes +_LIBC_COMPILER_RT.mipseb= yes +_LIBC_COMPILER_RT.mipsel= yes +_LIBC_COMPILER_RT.mips64eb= yes +_LIBC_COMPILER_RT.mips64el= yes _LIBC_COMPILER_RT.powerpc= yes _LIBC_COMPILER_RT.powerpc64= yes _LIBC_COMPILER_RT.sparc= yes @@ -1736,6 +1740,10 @@ _NEEDS_LIBCXX.${MACHINE_ARCH}= yes _NEEDS_LIBCXX.aarch64= yes _NEEDS_LIBCXX.aarch64eb= yes _NEEDS_LIBCXX.i386= yes +_NEEDS_LIBCXX.mipseb= yes +_NEEDS_LIBCXX.mipsel= yes +_NEEDS_LIBCXX.mips64eb= yes +_NEEDS_LIBCXX.mips64el= yes _NEEDS_LIBCXX.powerpc= yes _NEEDS_LIBCXX.powerpc64= yes _NEEDS_LIBCXX.sparc= yes diff --git a/sys/external/bsd/compiler_rt/dist/lib/builtins/clear_cache.c b/sys/external/bsd/compiler_rt/dist/lib/builtins/clear_cache.c index 1e22b3db8c8cb..0c68d3a2cd4fc 100644 --- a/sys/external/bsd/compiler_rt/dist/lib/builtins/clear_cache.c +++ b/sys/external/bsd/compiler_rt/dist/lib/builtins/clear_cache.c @@ -28,9 +28,13 @@ #endif #if defined(__mips__) - #include - #include - #include + #if defined(__NetBSD__) + #include + #else + #include + #include + #include + #endif #if defined(__ANDROID__) && defined(__LP64__) /* * clear_mips_cache - Invalidates instruction cache for Mips. @@ -118,7 +122,9 @@ void __clear_cache(void *start, void *end) { #elif defined(__mips__) const uintptr_t start_int = (uintptr_t) start; const uintptr_t end_int = (uintptr_t) end; - #if defined(__ANDROID__) && defined(__LP64__) + #if defined(__NetBSD__) + _cacheflush(start, end_int - start_int, BCACHE); + #elif defined(__ANDROID__) && defined(__LP64__) // Call synci implementation for short address range. const uintptr_t address_range_limit = 256; if ((end_int - start_int) <= address_range_limit) { @@ -171,4 +177,3 @@ void __clear_cache(void *start, void *end) { #endif #endif } - From 6d5e617d106edaff0246aa1e0425a0bcf42e351d Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:51:08 +0100 Subject: [PATCH 08/22] ld.elf_so: Build MIPS sources as PIC Pass -fPIC when building ld.elf_so on MIPS so Clang generates position-independent code. --- libexec/ld.elf_so/arch/mips/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/libexec/ld.elf_so/arch/mips/Makefile.inc b/libexec/ld.elf_so/arch/mips/Makefile.inc index ac6b3c236b27c..58cd02c905869 100644 --- a/libexec/ld.elf_so/arch/mips/Makefile.inc +++ b/libexec/ld.elf_so/arch/mips/Makefile.inc @@ -3,6 +3,7 @@ SRCS+= rtld_start.S mips_reloc.c COPTS+= -G0 +CPPFLAGS+= -fPIC CPPFLAGS+= -DELFSIZE=_MIPS_SZPTR CPPFLAGS+= -DRTLD_INHIBIT_COPY_RELOCS From 7b16f3332b63c938e7991e2a7034f2c80a5c8308 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 1 Sep 2026 04:42:42 +0100 Subject: [PATCH 09/22] openssl: Declare MIPS local symbols before use Add .local directives for internal functions and lookup tables in the AES and SHA assembly generators. This lets Clang identify forward references as local when expanding PIC la macros. Regenerate the MIPS assembly files. Upstream: https://github.com/openssl/openssl/pull/32620 --- .../apache2/openssl/dist/crypto/aes/asm/aes-mips.pl | 6 ++++++ .../apache2/openssl/dist/crypto/sha/asm/sha512-mips.pl | 1 + .../apache2/openssl/lib/libcrypto/arch/mips/aes-mips.S | 6 ++++++ .../apache2/openssl/lib/libcrypto/arch/mips/aes-mips64.S | 6 ++++++ .../apache2/openssl/lib/libcrypto/arch/mips/sha512-mips.S | 1 + .../apache2/openssl/lib/libcrypto/arch/mips/sha512-mips64.S | 1 + 6 files changed, 21 insertions(+) diff --git a/crypto/external/apache2/openssl/dist/crypto/aes/asm/aes-mips.pl b/crypto/external/apache2/openssl/dist/crypto/aes/asm/aes-mips.pl index 290621acc2cfc..4e9e18e1914b8 100644 --- a/crypto/external/apache2/openssl/dist/crypto/aes/asm/aes-mips.pl +++ b/crypto/external/apache2/openssl/dist/crypto/aes/asm/aes-mips.pl @@ -110,6 +110,12 @@ #include "mips_arch.h" .text +.local _mips_AES_encrypt +.local _mips_AES_decrypt +.local _mips_AES_set_encrypt_key +.local AES_Te +.local AES_Td +.local AES_Te4 #if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__)) .option pic2 #endif diff --git a/crypto/external/apache2/openssl/dist/crypto/sha/asm/sha512-mips.pl b/crypto/external/apache2/openssl/dist/crypto/sha/asm/sha512-mips.pl index 573bb574fc6d6..d685a2515ebaa 100644 --- a/crypto/external/apache2/openssl/dist/crypto/sha/asm/sha512-mips.pl +++ b/crypto/external/apache2/openssl/dist/crypto/sha/asm/sha512-mips.pl @@ -311,6 +311,7 @@ sub BODY_16_XX { #include "mips_arch.h" .text +.local K${label} .set noat #if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__)) .option pic2 diff --git a/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/aes-mips.S b/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/aes-mips.S index 9f020b6657ff0..4626c9049e397 100644 --- a/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/aes-mips.S +++ b/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/aes-mips.S @@ -1,6 +1,12 @@ #include "mips_arch.h" .text +.local _mips_AES_encrypt +.local _mips_AES_decrypt +.local _mips_AES_set_encrypt_key +.local AES_Te +.local AES_Td +.local AES_Te4 #if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__)) .option pic2 #endif diff --git a/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/aes-mips64.S b/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/aes-mips64.S index 7ea22e87212ed..3b1c19a43fe20 100644 --- a/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/aes-mips64.S +++ b/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/aes-mips64.S @@ -1,6 +1,12 @@ #include "mips_arch.h" .text +.local _mips_AES_encrypt +.local _mips_AES_decrypt +.local _mips_AES_set_encrypt_key +.local AES_Te +.local AES_Td +.local AES_Te4 #if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__)) .option pic2 #endif diff --git a/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/sha512-mips.S b/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/sha512-mips.S index 771e6e23708b7..f0909a02f4699 100644 --- a/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/sha512-mips.S +++ b/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/sha512-mips.S @@ -1,6 +1,7 @@ #include "mips_arch.h" .text +.local K256 .set noat #if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__)) .option pic2 diff --git a/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/sha512-mips64.S b/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/sha512-mips64.S index 2906baaf6e155..571279035c7c1 100644 --- a/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/sha512-mips64.S +++ b/crypto/external/apache2/openssl/lib/libcrypto/arch/mips/sha512-mips64.S @@ -1,6 +1,7 @@ #include "mips_arch.h" .text +.local K256 .set noat #if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__)) .option pic2 From 83eab1c251dfad180dfefb7a9b5137b25a5650b2 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:51:13 +0100 Subject: [PATCH 10/22] mips: Make libc profiling build with Clang Clang uses a CALL16 relocation for the inline assembly call to __mcount, which requires a global symbol. Give __mcount hidden global visibility for Clang instead of making it static. Do not treat the existing inline assembly warning in mcount.c as an error. --- lib/libc/gmon/Makefile.inc | 1 + sys/arch/mips/include/profile.h | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/libc/gmon/Makefile.inc b/lib/libc/gmon/Makefile.inc index 186535407947b..ce1dbc65d11cc 100644 --- a/lib/libc/gmon/Makefile.inc +++ b/lib/libc/gmon/Makefile.inc @@ -16,6 +16,7 @@ MLINKS+=moncontrol.3 monstartup.3 # mcount.c should be fixed and this test removed. # COPTS.mcount.c+=${${ACTIVE_CXX} == "gcc":? -Wa,--no-warn :} +COPTS.mcount.c+=${${ACTIVE_CC} == "clang":? -Wno-error=inline-asm :} .endif .if ${MACHINE_CPU} == "i386" diff --git a/sys/arch/mips/include/profile.h b/sys/arch/mips/include/profile.h index 0111e221f6aa2..aac4abb965349 100644 --- a/sys/arch/mips/include/profile.h +++ b/sys/arch/mips/include/profile.h @@ -50,8 +50,17 @@ int splhigh_noprof(void); \ void splx_noprof(int); #else /* !_KERNEL */ -/* Make __mcount static. */ +/* + * Clang emits a CALL16 relocation for the inline-assembly call below. MIPS + * ELF requires the target of that relocation to have global binding, so keep + * the helper private to libc with hidden visibility instead of making it a + * local symbol. + */ +#ifdef __clang__ +#define _KERNEL_MCOUNT_DECL __attribute__((visibility("hidden"))) +#else #define _KERNEL_MCOUNT_DECL static +#endif #endif /* !_KERNEL */ #ifdef _KERNEL From 4b3bd415238e3ee7ca109ff38eca5d5143142594 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:51:27 +0100 Subject: [PATCH 11/22] mips: Fix errors reported by Clang Use type names with _Alignof in the signal code, remove declarations and conversions that Clang rejects, and add the missing elf2ecoff function attributes. Ignore PT_GNU_STACK when elf2ecoff reads program headers. --- sys/arch/mips/mips/compat_16_machdep.c | 2 +- sys/arch/mips/mips/mips_stacktrace.c | 2 ++ sys/arch/mips/mips/netbsd32_machdep.c | 3 +-- sys/arch/mips/mips/sig_machdep.c | 2 +- sys/lib/libsa/loadfile_ecoff.c | 2 +- sys/sys/endian.h | 4 ++-- usr.bin/elf2ecoff/elf2ecoff.c | 5 +++-- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/sys/arch/mips/mips/compat_16_machdep.c b/sys/arch/mips/mips/compat_16_machdep.c index 5f607d58214b9..8d4f1e8b2487a 100644 --- a/sys/arch/mips/mips/compat_16_machdep.c +++ b/sys/arch/mips/mips/compat_16_machdep.c @@ -97,7 +97,7 @@ sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *returnmask) struct pcb * const pcb = lwp_getpcb(l); int onstack, error; struct sigcontext *scp = getframe(l, sig, &onstack, - sizeof(*scp), _Alignof(*scp)); + sizeof(*scp), _Alignof(struct sigcontext)); struct sigcontext ksc; struct trapframe * const tf = l->l_md.md_utf; sig_t catcher = SIGACTION(p, sig).sa_handler; diff --git a/sys/arch/mips/mips/mips_stacktrace.c b/sys/arch/mips/mips/mips_stacktrace.c index 2b5036f9e2caa..0cc128d943637 100644 --- a/sys/arch/mips/mips/mips_stacktrace.c +++ b/sys/arch/mips/mips/mips_stacktrace.c @@ -123,7 +123,9 @@ extern char mips64r2_systemcall[]; #define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */ #define MIPS_ERET 0x42000018 /* instruction code for eret */ +#ifdef _KERNEL int main(void *); /* XXX */ +#endif /* * Functions ``special'' enough to print by name diff --git a/sys/arch/mips/mips/netbsd32_machdep.c b/sys/arch/mips/mips/netbsd32_machdep.c index ae658dbfe346d..5bd50229648ea 100644 --- a/sys/arch/mips/mips/netbsd32_machdep.c +++ b/sys/arch/mips/mips/netbsd32_machdep.c @@ -95,7 +95,7 @@ netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) int onstack, error; int sig = ksi->ksi_signo; struct sigframe_siginfo32 *sfp = getframe(l, sig, &onstack, - sizeof(*sfp), _Alignof(*sfp)); + sizeof(*sfp), _Alignof(struct sigframe_siginfo32)); struct sigframe_siginfo32 sf; struct trapframe * const tf = l->l_md.md_utf; size_t sfsz; @@ -326,4 +326,3 @@ netbsd32_machdep_md_fini(void) MODULE_HOOK_UNSET(netbsd32_machine32_hook); } - diff --git a/sys/arch/mips/mips/sig_machdep.c b/sys/arch/mips/mips/sig_machdep.c index 49b61d782efa0..561e31c26e5e7 100644 --- a/sys/arch/mips/mips/sig_machdep.c +++ b/sys/arch/mips/mips/sig_machdep.c @@ -92,7 +92,7 @@ sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) int onstack, error; const int signo = ksi->ksi_signo; struct sigframe_siginfo *sf = getframe(l, signo, &onstack, - sizeof(*sf), _Alignof(*sf)); + sizeof(*sf), _Alignof(struct sigframe_siginfo)); struct sigframe_siginfo ksf; const sig_t catcher = SIGACTION(p, signo).sa_handler; diff --git a/sys/lib/libsa/loadfile_ecoff.c b/sys/lib/libsa/loadfile_ecoff.c index 73155d7417f91..674ff4b12d373 100644 --- a/sys/lib/libsa/loadfile_ecoff.c +++ b/sys/lib/libsa/loadfile_ecoff.c @@ -58,7 +58,7 @@ loadfile_coff(int fd, struct ecoff_exechdr *coff, u_long *marks, int flags) ssize_t nr; /* some ports dont use the offset */ - offset = offset; + (void)offset; /* Read in text. */ if (lseek(fd, ECOFF_TXTOFF(coff), SEEK_SET) == -1) { diff --git a/sys/sys/endian.h b/sys/sys/endian.h index 0f22016865d20..a6fc172a2261c 100644 --- a/sys/sys/endian.h +++ b/sys/sys/endian.h @@ -254,7 +254,7 @@ be16dec(const void *_buf) { const uint8_t *p = __CAST(const uint8_t *, _buf); - return ((__CAST(uint16_t, p[0]) << 8) | p[1]); + return __CAST(uint16_t, ((__CAST(uint16_t, p[0]) << 8) | p[1])); } static __inline uint16_t __unused @@ -262,7 +262,7 @@ le16dec(const void *_buf) { const uint8_t *p = __CAST(const uint8_t *, _buf); - return (p[0] | (__CAST(uint16_t, p[1]) << 8)); + return __CAST(uint16_t, (p[0] | (__CAST(uint16_t, p[1]) << 8))); } static __inline void __unused diff --git a/usr.bin/elf2ecoff/elf2ecoff.c b/usr.bin/elf2ecoff/elf2ecoff.c index 77bb0ce29936b..857db646e1d7f 100644 --- a/usr.bin/elf2ecoff/elf2ecoff.c +++ b/usr.bin/elf2ecoff/elf2ecoff.c @@ -101,7 +101,7 @@ static void elf_read_syms(struct elf_syms *, int, off_t, off_t, off_t, off_t); -static void +static __printflike(2, 3) void debug_printf(int level, const char *format, ...) { if (debug >= level) { @@ -112,7 +112,7 @@ debug_printf(int level, const char *format, ...) } } -static void +static __dead void usage(void) { fprintf(stderr, @@ -259,6 +259,7 @@ main(int argc, char **argv) case PT_NOTE: case PT_NULL: case PT_PHDR: + case PT_GNU_STACK: case PT_MIPS_ABIFLAGS: case PT_MIPS_REGINFO: /* Section types we can ignore... */ From 15cf0e3aeec9766a536744dd1e3e89387fbe14c5 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:51:39 +0100 Subject: [PATCH 12/22] mips: Make kernel assembly build with Clang IAS Fix preprocessor tests and assembler syntax that Clang IAS rejects. Use .balign and .space for the slowfault address, align pointer tables, give rddsp its mask, and enable hard-float only around the FPU instructions. Raise the assembler macro nesting limit only for the cache assembly files that need it. --- sys/arch/mips/conf/Makefile.mips | 7 +++++++ sys/arch/mips/conf/kern.ldscript | 2 +- sys/arch/mips/mips/locore_mips3.S | 8 ++++---- sys/arch/mips/mips/mipsX_subr.S | 4 +++- sys/arch/mips/mips/mips_dsp.c | 2 +- sys/arch/mips/mips/mips_fpu.c | 10 ++++++---- sys/arch/mips/mips/spl.S | 1 + 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/sys/arch/mips/conf/Makefile.mips b/sys/arch/mips/conf/Makefile.mips index a04013a55ce5a..b24077e9023e4 100644 --- a/sys/arch/mips/conf/Makefile.mips +++ b/sys/arch/mips/conf/Makefile.mips @@ -50,6 +50,13 @@ GP?= ${DEFGP} .if ${ACTIVE_CC} == "gcc" COPTS.mips_fpu.c+= -mhard-float -Wa,-mhard-float AFLAGS.fp.S+= -Wa,-mhard-float +.elif ${ACTIVE_CC} == "clang" +.for _f in cache_r4k_pcache16.S cache_r4k_pcache32.S \ + cache_r4k_pcache64.S cache_r4k_pcache128.S \ + cache_r4k_scache16.S cache_r4k_scache32.S \ + cache_r4k_scache64.S cache_r4k_scache128.S +AFLAGS.${_f}+= -mllvm -asm-macro-max-nesting-depth=64 +.endfor .endif CFLAGS+= ${GP} -mno-abicalls -msoft-float -ffixed-24 diff --git a/sys/arch/mips/conf/kern.ldscript b/sys/arch/mips/conf/kern.ldscript index 11b4fec408e64..0d03b69cfe169 100644 --- a/sys/arch/mips/conf/kern.ldscript +++ b/sys/arch/mips/conf/kern.ldscript @@ -3,7 +3,7 @@ #include "assym.h" /* ldscript for NetBSD/mips kernels and LKMs */ -OUTPUT_ARCH(mips) +OUTPUT_ARCH("mips") ENTRY(_start) /* Do we need any of these? __DYNAMIC = 0; */ diff --git a/sys/arch/mips/mips/locore_mips3.S b/sys/arch/mips/mips/locore_mips3.S index 4faef8554750f..3fd819af84c93 100644 --- a/sys/arch/mips/mips/locore_mips3.S +++ b/sys/arch/mips/mips/locore_mips3.S @@ -123,7 +123,7 @@ RCSID("$NetBSD: locore_mips3.S,v 1.116 2023/02/23 14:56:00 riastradh Exp $") *============================================================================ */ .set noreorder -#if (__mips < 3) || __mips_o32 +#if (__mips < 3) || defined(__mips_o32) .set mips3 #endif @@ -582,7 +582,7 @@ LEAF(mips3_cp0_pg_mask_write) JR_HB_RA END(mips3_cp0_pg_mask_write) -#if __mips != 32 +#if __mips != 32 || defined(__mips_o32) LEAF(mips3_ld) #if defined(__mips_o32) #if (MIPS64R2) > 0 @@ -719,7 +719,7 @@ END(baderr64) LEAF(mips3_cp0_tlb_entry_hi_probe) dmfc0 t0, MIPS_COP_0_TLB_HI li v0, -1 /* all 1s */ -#if defined(__mips_isa_rev) && __mips_isa_rev >= 2 +#if defined(__mips_isa_rev) && __mips_isa_rev >= 2 && !defined(__mips_o32) dinsu v0, zero, 62, 2 #else dsll v0, v0, 2 /* except the top 2 */ @@ -745,7 +745,7 @@ LEAF(mips3_cp0_tlb_entry_hi_probe) jr ra nop END(mips3_cp0_tlb_entry_hi_probe) -#endif /* __mips != 32 */ +#endif /* __mips != 32 || defined(__mips_o32) */ /* * uint64_t mips3_cp0_tlb_entry_lo_probe(void); diff --git a/sys/arch/mips/mips/mipsX_subr.S b/sys/arch/mips/mips/mipsX_subr.S index 0d9b49e4378d8..92a8b7286689e 100644 --- a/sys/arch/mips/mips/mipsX_subr.S +++ b/sys/arch/mips/mips/mipsX_subr.S @@ -679,7 +679,8 @@ _VECTOR_END(MIPSX(intr)) * *---------------------------------------------------------------------------- */ - .org ((. + 31) & ~31) + 12 + .balign 32 + .space 12 MIPSX(slowfault): .set noat mfc0 k0, MIPS_COP_0_STATUS @@ -2990,6 +2991,7 @@ END(MIPSX(pagezero)) #endif /* USE_64BIT_INSTRUCTIONS */ .rdata + .p2align PTR_SCALESHIFT .globl _C_LABEL(MIPSX(locore_vec)) _C_LABEL(MIPSX(locore_vec)): diff --git a/sys/arch/mips/mips/mips_dsp.c b/sys/arch/mips/mips/mips_dsp.c index 7cfeb31086031..0bf1c52092ef2 100644 --- a/sys/arch/mips/mips/mips_dsp.c +++ b/sys/arch/mips/mips/mips_dsp.c @@ -114,7 +114,7 @@ mips_dsp_state_save(lwp_t *l) "mfhi %[mulhi2], $ac2" "\n\t" "mflo %[mullo3], $ac3" "\n\t" "mfhi %[mulhi3], $ac3" "\n\t" - "rddsp %[dspctl]" "\n\t" + "rddsp %[dspctl], 0x3ff" "\n\t" "xor %[status], %[mips_sr_mx]" "\n\t" "mtc0 %[status], $%[cp0_status]" "\n\t" "ehb" "\n\t" diff --git a/sys/arch/mips/mips/mips_fpu.c b/sys/arch/mips/mips/mips_fpu.c index 37f980304cb91..5b327e799860c 100644 --- a/sys/arch/mips/mips/mips_fpu.c +++ b/sys/arch/mips/mips/mips_fpu.c @@ -102,15 +102,16 @@ mips_fpu_state_save(lwp_t *l) * interrupts remain on. */ __asm volatile ( + ".set push" "\n\t" ".set noreorder" "\n\t" ".set noat" "\n\t" + ".set hardfloat" "\n\t" "mfc0 %0, $%3" "\n\t" "mtc0 %2, $%3" "\n\t" ___STRING(COP0_HAZARD_FPUENABLE) "cfc1 %1, $31" "\n\t" "cfc1 %1, $31" "\n\t" - ".set at" "\n\t" - ".set reorder" "\n\t" + ".set pop" "\n\t" : "=&r" (status), "=r"(fpcsr) : "r"(tf->tf_regs[_R_SR] & (MIPS_SR_COP_1_BIT|MIPS3_SR_FR|MIPS_SR_KX|MIPS_SR_INT_IE)), "n"(MIPS_COP_0_STATUS)); @@ -341,13 +342,14 @@ mips_fpu_state_load(lwp_t *l, u_int flags) */ fpcsr &= ~MIPS_FCSR_CAUSE; __asm volatile( + ".set push" "\n\t" ".set noreorder" "\n\t" ".set noat" "\n\t" + ".set hardfloat" "\n\t" "ctc1 %0, $31" "\n\t" "nop" "\n\t" /* XXX: Hack */ "mtc0 %1, $%2" "\n\t" - ".set at" "\n\t" - ".set reorder" "\n\t" + ".set pop" "\n\t" :: "r"(fpcsr), "r"(status), "n"(MIPS_COP_0_STATUS)); } diff --git a/sys/arch/mips/mips/spl.S b/sys/arch/mips/mips/spl.S index d1883483ea847..b1b796e8e2f56 100644 --- a/sys/arch/mips/mips/spl.S +++ b/sys/arch/mips/mips/spl.S @@ -391,6 +391,7 @@ STATIC_LEAF(_splsw_splcheck) END(_splsw_splcheck) .rdata + .p2align PTR_SCALESHIFT .globl _C_LABEL(std_splsw) _C_LABEL(std_splsw): PTR_WORD _C_LABEL(_splsw_splhigh) From 7f730625e1fceabb3870aa3e52f060389b1f8663 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:51:56 +0100 Subject: [PATCH 13/22] mips: Initialize tlb_lo0 when PGSHIFT is odd mips_fixup_zero_relative initialized tlb_lo1 twice in this case. Put the first low-page TLB value in tlb_lo0. --- sys/arch/mips/mips/mips_fixup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/arch/mips/mips/mips_fixup.c b/sys/arch/mips/mips/mips_fixup.c index 1e316373e9a59..b99aee45d4361 100644 --- a/sys/arch/mips/mips/mips_fixup.c +++ b/sys/arch/mips/mips/mips_fixup.c @@ -216,7 +216,7 @@ mips_fixup_zero_relative(int32_t load_addr, uint32_t new_insns[2], void *arg) struct tlbmask tlbmask = { .tlb_hi = -PAGE_SIZE | KERNEL_PID, #if PGSHIFT & 1 - .tlb_lo1 = tlb_lo, + .tlb_lo0 = tlb_lo, .tlb_lo1 = tlb_lo + MIPS3_PG_NEXT, #else .tlb_lo0 = 0, From 2eb0cf45e1677b960202f6ce906381643db0c2a9 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:51:56 +0100 Subject: [PATCH 14/22] mips: Handle Clang stubs in mips_fixup_addr Accept ADDIU while reading an indirect-call stub. Ignore stack pointer adjustments and use other ADDIU instructions when calculating the target address. --- sys/arch/mips/mips/mips_fixup.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sys/arch/mips/mips/mips_fixup.c b/sys/arch/mips/mips/mips_fixup.c index b99aee45d4361..8d6a3c2a3ac62 100644 --- a/sys/arch/mips/mips/mips_fixup.c +++ b/sys/arch/mips/mips/mips_fixup.c @@ -320,6 +320,23 @@ mips_fixup_addr(const uint32_t *stubp) regs[insn.IType.rt] = (int16_t)insn.IType.imm << 16; used |= (1 << insn.IType.rt); break; + case OP_ADDIU: + /* + * Clang does not tail-call all of the indirect functions used + * for stubs. Accept its stack adjustment without trying to + * model the stack, and handle ADDIU used to form the address of + * an indirect function pointer. + */ + if (insn.IType.rs == _R_SP && insn.IType.rt == _R_SP) + break; + if ((used & (1 << insn.IType.rs)) == 0) { + errstr = "ADDIU"; + goto out; + } + regs[insn.IType.rt] = regs[insn.IType.rs] + + (int16_t)insn.IType.imm; + used |= (1 << insn.IType.rt); + break; #ifdef _LP64 case OP_LD: if ((used & (1 << insn.IType.rs)) == 0) { From 03d66f8fe53285e3a7aa14ffe9950417edbdce28 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:52:06 +0100 Subject: [PATCH 15/22] evbmips: Build MALTA for MIPS32 and MIPS32R2 CPUs Add the MIPS32R2 locore code to the MALTA kernel. Compile the common kernel code with -march=mips32 because Malta boards may have either a MIPS32 or MIPS32R2 CPU. --- sys/arch/evbmips/conf/MALTA | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/arch/evbmips/conf/MALTA b/sys/arch/evbmips/conf/MALTA index 5d96b39f6c358..ddb369892bd5f 100644 --- a/sys/arch/evbmips/conf/MALTA +++ b/sys/arch/evbmips/conf/MALTA @@ -9,7 +9,9 @@ include "arch/evbmips/conf/std.malta" maxusers 32 options MIPS32 +options MIPS32R2 options MIPS64 +makeoptions CPUFLAGS+="-march=mips32" options NOFPU # No FPU options FPEMUL # emulate FPU insn From 23fa884f4d5024e2cd5d11c91b7b0849767103d1 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 18 Aug 2026 16:52:12 +0100 Subject: [PATCH 16/22] tests/ld.elf_so: Allow the MIPS IFUNC linker warning MIPS BFD creates the IFUNC helper library but warns that dynamic IFUNC symbols are not supported. Pass --no-fatal-warnings when Clang links this helper. The IFUNC test is already skipped on MIPS. --- tests/libexec/ld.elf_so/helper.mk | 7 +++++++ tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/tests/libexec/ld.elf_so/helper.mk b/tests/libexec/ld.elf_so/helper.mk index 34d6bb8e46916..58b81f287d548 100644 --- a/tests/libexec/ld.elf_so/helper.mk +++ b/tests/libexec/ld.elf_so/helper.mk @@ -15,4 +15,11 @@ NOPICINSTALL= # defined NOPROFILE= # defined NOSTATICLIB= # defined +.if defined(MIPS_IFUNC_NO_FATAL_WARNINGS) +.include +.if ${MACHINE_CPU} == "mips" && ${ACTIVE_CC} == "clang" +LDADD+= -Wl,--no-fatal-warnings +.endif +.endif + .include diff --git a/tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile b/tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile index ccf7545d7da24..97588b5b85c5b 100644 --- a/tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile +++ b/tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile @@ -3,4 +3,10 @@ LIB= h_helper_ifunc_dso SRCS= h_helper_ifunc.c +# MIPS BFD emits the shared object, but warns that dynamic IFUNC symbols +# are not supported. The MIPS tests are skipped at runtime for that reason. +# GCC builds do not make linker warnings fatal; match that behaviour when +# building the same test helper with Clang. +MIPS_IFUNC_NO_FATAL_WARNINGS= yes + .include "../helper.mk" From 816b408268526571706dde3f7492e5af9f061c64 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Mon, 31 Aug 2026 06:44:45 +0100 Subject: [PATCH 17/22] ld.elf_so: Disable jump tables in MIPS relocation code Build mips_reloc.c with -fno-jump-tables. A jump table in this code uses the GOT before the runtime linker has relocated it. --- libexec/ld.elf_so/arch/mips/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/libexec/ld.elf_so/arch/mips/Makefile.inc b/libexec/ld.elf_so/arch/mips/Makefile.inc index 58cd02c905869..fdb89404224f4 100644 --- a/libexec/ld.elf_so/arch/mips/Makefile.inc +++ b/libexec/ld.elf_so/arch/mips/Makefile.inc @@ -3,6 +3,7 @@ SRCS+= rtld_start.S mips_reloc.c COPTS+= -G0 +COPTS.mips_reloc.c+= -fno-jump-tables CPPFLAGS+= -fPIC CPPFLAGS+= -DELFSIZE=_MIPS_SZPTR From 38701e8bb6e7e101d4868f7e5387cfcedfd6363c Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Mon, 31 Aug 2026 06:45:16 +0100 Subject: [PATCH 18/22] mips: Fix printf formats in trap.c Use PRIxREGISTER for saved registers and PRIxVADDR for virtual addresses. Do not assume these values have the same type as unsigned long. --- sys/arch/mips/mips/trap.c | 52 +++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/sys/arch/mips/mips/trap.c b/sys/arch/mips/mips/trap.c index 1cd655e71402e..37d811d694b9b 100644 --- a/sys/arch/mips/mips/trap.c +++ b/sys/arch/mips/mips/trap.c @@ -849,40 +849,54 @@ frame_dump(const struct trapframe *tf, struct pcb *pcb) { printf("trapframe %p\n", tf); - printf("ast %#018lx v0 %#018lx v1 %#018lx\n", + printf("ast %#018" PRIxREGISTER " v0 %#018" PRIxREGISTER + " v1 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_AST], tf->tf_regs[_R_V0], tf->tf_regs[_R_V1]); - printf(" a0 %#018lx a1 %#018lx a2 %#018lx\n", + printf(" a0 %#018" PRIxREGISTER " a1 %#018" PRIxREGISTER + " a2 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_A0], tf->tf_regs[_R_A1], tf->tf_regs[_R_A2]); #if defined(__mips_n32) || defined(__mips_n64) - printf(" a3 %#018lx a4 %#018lx a5 %#018lx\n", + printf(" a3 %#018" PRIxREGISTER " a4 %#018" PRIxREGISTER + " a5 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_A3], tf->tf_regs[_R_A4], tf->tf_regs[_R_A5]); - printf(" a6 %#018lx a7 %#018lx t0 %#018lx\n", + printf(" a6 %#018" PRIxREGISTER " a7 %#018" PRIxREGISTER + " t0 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_A6], tf->tf_regs[_R_A7], tf->tf_regs[_R_T0]); - printf(" t1 %#018lx t2 %#018lx t3 %#018lx\n", + printf(" t1 %#018" PRIxREGISTER " t2 %#018" PRIxREGISTER + " t3 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_T1], tf->tf_regs[_R_T2], tf->tf_regs[_R_T3]); #else - printf(" a3 %#018lx t0 %#018lx t1 %#018lx\n", + printf(" a3 %#018" PRIxREGISTER " t0 %#018" PRIxREGISTER + " t1 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_A3], tf->tf_regs[_R_T0], tf->tf_regs[_R_T1]); - printf(" t2 %#018lx t3 %#018lx t4 %#018lx\n", + printf(" t2 %#018" PRIxREGISTER " t3 %#018" PRIxREGISTER + " t4 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_T2], tf->tf_regs[_R_T3], tf->tf_regs[_R_T4]); - printf(" t5 %#018lx t6 %#018lx t7 %#018lx\n", + printf(" t5 %#018" PRIxREGISTER " t6 %#018" PRIxREGISTER + " t7 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_T5], tf->tf_regs[_R_T6], tf->tf_regs[_R_T7]); #endif - printf(" s0 %#018lx s1 %#018lx s2 %#018lx\n", + printf(" s0 %#018" PRIxREGISTER " s1 %#018" PRIxREGISTER + " s2 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_S0], tf->tf_regs[_R_S1], tf->tf_regs[_R_S2]); - printf(" s3 %#018lx s4 %#018lx s5 %#018lx\n", + printf(" s3 %#018" PRIxREGISTER " s4 %#018" PRIxREGISTER + " s5 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_S3], tf->tf_regs[_R_S4], tf->tf_regs[_R_S5]); - printf(" s6 %#018lx s7 %#018lx t8 %#018lx\n", + printf(" s6 %#018" PRIxREGISTER " s7 %#018" PRIxREGISTER + " t8 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_S6], tf->tf_regs[_R_S7], tf->tf_regs[_R_T8]); - printf(" t9 %#018lx k0 %#018lx k1 %#018lx\n", + printf(" t9 %#018" PRIxREGISTER " k0 %#018" PRIxREGISTER + " k1 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_T9], tf->tf_regs[_R_K0], tf->tf_regs[_R_K1]); - printf(" gp %#018lx sp %#018lx s8 %#018lx\n", + printf(" gp %#018" PRIxREGISTER " sp %#018" PRIxREGISTER + " s8 %#018" PRIxREGISTER "\n", tf->tf_regs[_R_GP], tf->tf_regs[_R_SP], tf->tf_regs[_R_S8]); - printf(" ra %#018lx sr %#018lx pc %#018lx\n", + printf(" ra %#018" PRIxREGISTER " sr %#018" PRIxREGISTER + " pc %#018" PRIxREGISTER "\n", tf->tf_regs[_R_RA], tf->tf_regs[_R_SR], tf->tf_regs[_R_PC]); - printf(" mullo %#018lx mulhi %#018lx\n", + printf(" mullo %#018" PRIxREGISTER " mulhi %#018" PRIxREGISTER "\n", tf->tf_regs[_R_MULLO], tf->tf_regs[_R_MULHI]); - printf(" badvaddr %#018lx cause %#018lx\n", + printf(" badvaddr %#018" PRIxREGISTER " cause %#018" PRIxREGISTER "\n", tf->tf_regs[_R_BADVADDR], tf->tf_regs[_R_CAUSE]); printf("\n"); hexdump(printf, "Stack dump", tf, 256); @@ -895,10 +909,10 @@ sigdebug(const struct trapframe *tf, const ksiginfo_t *ksi, int e, struct lwp *l = curlwp; struct proc *p = l->l_proc; - printf("pid %d.%d (%s): signal %d code=%d (trap %#lx) " - "@pc %#lx addr %#lx error=%d\n", + printf("pid %d.%d (%s): signal %d code=%d (trap %#" PRIxREGISTER ") " + "@pc %#" PRIxVADDR " addr %#" PRIxREGISTER " error=%d\n", p->p_pid, l->l_lid, p->p_comm, ksi->ksi_signo, ksi->ksi_code, - tf->tf_regs[_R_CAUSE], (unsigned long)pc, tf->tf_regs[_R_BADVADDR], + tf->tf_regs[_R_CAUSE], pc, tf->tf_regs[_R_BADVADDR], e); frame_dump(tf, lwp_getpcb(l)); } From 349bd731873d6b8e46c9a1039d4867c2f564509f Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Mon, 31 Aug 2026 06:45:24 +0100 Subject: [PATCH 19/22] mips: Add FPEMUL support for conditional moves Implement the single- and double-precision movf, movt, movz, and movn instructions. Copy the saved FPU register values directly so the move does not change NaN bits. --- sys/arch/mips/mips/fp.S | 124 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/sys/arch/mips/mips/fp.S b/sys/arch/mips/mips/fp.S index 33349b04b9962..2a33b1b5432fc 100644 --- a/sys/arch/mips/mips/fp.S +++ b/sys/arch/mips/mips/fp.S @@ -212,9 +212,11 @@ paired_single_op: #define floor_l_s ill #define cvt_l_s ill #define cvt_ps_s ill +#ifndef FPEMUL #define movcf_s ill #define movn_s ill #define movz_s ill +#endif #define rsqrt_s ill #define rsqrt1_s ill #define rsqrt2_s ill @@ -244,9 +246,11 @@ paired_single_op: #define recip1_d ill #define recip2_d ill #define cvt_l_d ill +#ifndef FPEMUL #define movcf_d ill #define movz_d ill #define movn_d ill +#endif #define recip_d ill #define rsqrt_d ill #define rsqrt1_d ill @@ -1674,6 +1678,126 @@ mov_d: jal _C_LABEL(get_fs_d) b result_fs_d +#ifdef FPEMUL +/* + * Conditional floating-point moves are part of MIPS32. NOFPU kernels + * must perform the move directly in the saved FP register file: using the + * usual unpack/repack helpers would change NaN payloads. + */ +movcf_s: + srl t0, a0, 18 # condition-code field + andi t0, t0, 7 + bne t0, zero, 1f + li v0, MIPS_FCSR_FCC0 + b 2f +1: addiu t0, t0, 24 # FCC1..FCC7 are bits 25..31 + li v0, 1 + sllv v0, v0, t0 +2: and v0, v0, a2 + sltu v0, zero, v0 + srl t0, a0, 16 # true/false selector + andi t0, t0, 1 + bne v0, t0, done + b move_s_cond + +movz_s: + REG_PROLOGUE + REG_S zero, TF_REG_ZERO(a1) + srl t0, a0, 16-REG_SCALESHIFT # rt is in bits 20:16 + andi t0, t0, REG_REGMASK + PTR_ADDU v0, a1, t0 + REG_L v0, TF_REG_ZERO(v0) + REG_EPILOGUE + bne v0, zero, done + b move_s_cond + +movn_s: + REG_PROLOGUE + REG_S zero, TF_REG_ZERO(a1) + srl t0, a0, 16-REG_SCALESHIFT # rt is in bits 20:16 + andi t0, t0, REG_REGMASK + PTR_ADDU v0, a1, t0 + REG_L v0, TF_REG_ZERO(v0) + REG_EPILOGUE + beq v0, zero, done + +move_s_cond: + srl t1, a0, 11-FPX_SCALESHIFT # fs is in bits 15:11 + PTR_L t0, L_PCB(MIPS_CURLWP) + andi t1, t1, FPX_REGMASK + PTR_ADDU t1, t0, t1 + FPX_L v0, PCB_FPREGS+FRAME_FP0(t1) + + srl t1, a0, 6-FPX_SCALESHIFT # fd is in bits 10:6 + andi t1, t1, FPX_REGMASK + PTR_ADDU t0, t0, t1 + FPX_S v0, PCB_FPREGS+FRAME_FP0(t0) + b done + +movcf_d: + srl t0, a0, 18 # condition-code field + andi t0, t0, 7 + bne t0, zero, 1f + li v0, MIPS_FCSR_FCC0 + b 2f +1: addiu t0, t0, 24 # FCC1..FCC7 are bits 25..31 + li v0, 1 + sllv v0, v0, t0 +2: and v0, v0, a2 + sltu v0, zero, v0 + srl t0, a0, 16 # true/false selector + andi t0, t0, 1 + bne v0, t0, done + b move_d_cond + +movz_d: + REG_PROLOGUE + REG_S zero, TF_REG_ZERO(a1) + srl t0, a0, 16-REG_SCALESHIFT # rt is in bits 20:16 + andi t0, t0, REG_REGMASK + PTR_ADDU v0, a1, t0 + REG_L v0, TF_REG_ZERO(v0) + REG_EPILOGUE + bne v0, zero, done + b move_d_cond + +movn_d: + REG_PROLOGUE + REG_S zero, TF_REG_ZERO(a1) + srl t0, a0, 16-REG_SCALESHIFT # rt is in bits 20:16 + andi t0, t0, REG_REGMASK + PTR_ADDU v0, a1, t0 + REG_L v0, TF_REG_ZERO(v0) + REG_EPILOGUE + beq v0, zero, done + +move_d_cond: + srl t1, a0, 11-FPX_SCALESHIFT # fs is in bits 15:11 + PTR_L t0, L_PCB(MIPS_CURLWP) +#if defined(__mips_o32) || defined(__mips_o64) + andi t1, t1, FPX_REGEVENMASK + PTR_ADDU t1, t0, t1 + FPX_L v0, PCB_FPREGS+FRAME_FP0(t1) + FPX_L v1, PCB_FPREGS+FRAME_FP0+SZFREG(t1) + + srl t1, a0, 6-FPX_SCALESHIFT # fd is in bits 10:6 + andi t1, t1, FPX_REGEVENMASK + PTR_ADDU t0, t0, t1 + FPX_S v0, PCB_FPREGS+FRAME_FP0(t0) + FPX_S v1, PCB_FPREGS+FRAME_FP0+SZFREG(t0) +#else + andi t1, t1, FPX_REGMASK + PTR_ADDU t1, t0, t1 + FPX_L v0, PCB_FPREGS+FRAME_FP0(t1) + + srl t1, a0, 6-FPX_SCALESHIFT # fd is in bits 10:6 + andi t1, t1, FPX_REGMASK + PTR_ADDU t0, t0, t1 + FPX_S v0, PCB_FPREGS+FRAME_FP0(t0) +#endif + b done +#endif /* FPEMUL */ + /* * Single precision negate. */ From 4ee3cced737c7f5a7baa431a6cad13d10076f729 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Mon, 31 Aug 2026 06:45:32 +0100 Subject: [PATCH 20/22] mips: Detect the FPU before using hardware or emulation When FPEMUL is enabled without NOFPU, check the Config1 FP bit before accessing COP1. Use the hardware FPU when it exists and run the instruction emulator when it does not. NOFPU still forces emulation. Report the detected result through machdep.fpu_present. --- sys/arch/mips/mips/locore.S | 14 ++++++++++++++ sys/arch/mips/mips/mips_machdep.c | 7 +------ sys/arch/mips/mips/trap.c | 14 +++++++++++--- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/sys/arch/mips/mips/locore.S b/sys/arch/mips/mips/locore.S index 731582c587ec1..49a3e3b6165a7 100644 --- a/sys/arch/mips/mips/locore.S +++ b/sys/arch/mips/mips/locore.S @@ -60,6 +60,7 @@ #include #include +#include #include #include @@ -155,6 +156,13 @@ EXPORT_OBJECT(kernel_text) # libkvm refers this #ifdef NOFPU li t1, 0 # Dummy FPU_ID #else +#if defined(FPEMUL) && defined(MIPSNN) + /* Avoid touching COP1 when Config1 says that no FPU is present. */ + mfc0 t1, MIPS_COP_0_CONFIG1 + andi t1, MIPSNN_CFG1_FP + beqz t1, 1f + nop +#endif /* Enable the FPU to read FPUID */ mfc0 k0, MIPS_COP_0_STATUS MFC0_HAZARD @@ -167,6 +175,12 @@ EXPORT_OBJECT(kernel_text) # libkvm refers this /* Disable again, we don't want it on in the kernel */ and k0, ~MIPS_SR_COP_1_BIT mtc0 k0, MIPS_COP_0_STATUS +#if defined(FPEMUL) && defined(MIPSNN) + b 2f + nop +1: li t1, 0 # No hardware FPU +2: +#endif #endif INT_S t0, _C_LABEL(mips_options)+MO_CPU_ID # save PRID register diff --git a/sys/arch/mips/mips/mips_machdep.c b/sys/arch/mips/mips/mips_machdep.c index a5ce772bf4364..39767ef99dd30 100644 --- a/sys/arch/mips/mips/mips_machdep.c +++ b/sys/arch/mips/mips/mips_machdep.c @@ -1810,12 +1810,7 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, CTLTYPE_INT, "fpu_present", NULL, - NULL, -#ifdef NOFPU - 0, -#else - 1, -#endif + NULL, mips_options.mips_fpu_id != 0, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); } diff --git a/sys/arch/mips/mips/trap.c b/sys/arch/mips/mips/trap.c index 37d811d694b9b..1f2450030190e 100644 --- a/sys/arch/mips/mips/trap.c +++ b/sys/arch/mips/mips/trap.c @@ -675,8 +675,9 @@ trap(uint32_t status, uint32_t cause, vaddr_t vaddr, vaddr_t pc, /* FALLTHROUGH */ case T_RES_INST+T_USER: case T_COP_UNUSABLE+T_USER: -#if !defined(FPEMUL) && !defined(NOFPU) - if (__SHIFTOUT(cause, MIPS_CR_COP_ERR) == MIPS_CR_COP_ERR_CU1) { +#if !defined(NOFPU) + if (mips_options.mips_fpu_id != 0 && + __SHIFTOUT(cause, MIPS_CR_COP_ERR) == MIPS_CR_COP_ERR_CU1) { fpu_load(); /* load FPA */ } else #endif @@ -686,7 +687,14 @@ trap(uint32_t status, uint32_t cause, vaddr_t vaddr, vaddr_t pc, userret(l); return; /* GEN */ case T_FPE+T_USER: -#if defined(FPEMUL) +#if defined(FPEMUL) && !defined(NOFPU) + if (mips_options.mips_fpu_id != 0) { + utf->tf_regs[_R_CAUSE] = cause; + mips_fpu_trap(pc, utf); + } else { + mips_emul_inst(status, cause, pc, utf); + } +#elif defined(FPEMUL) mips_emul_inst(status, cause, pc, utf); #elif !defined(NOFPU) utf->tf_regs[_R_CAUSE] = cause; From a2f940d818002a39bfbf09f5aa9f45facb3ab6ea Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Mon, 31 Aug 2026 06:45:53 +0100 Subject: [PATCH 21/22] evbmips: Let MALTA use a hardware FPU Remove NOFPU from the MALTA kernel and keep FPEMUL enabled. The kernel now uses a hardware FPU when one is present and emulates FPU instructions when one is not present. --- sys/arch/evbmips/conf/MALTA | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/arch/evbmips/conf/MALTA b/sys/arch/evbmips/conf/MALTA index ddb369892bd5f..bb5f99121f4dd 100644 --- a/sys/arch/evbmips/conf/MALTA +++ b/sys/arch/evbmips/conf/MALTA @@ -13,7 +13,6 @@ options MIPS32R2 options MIPS64 makeoptions CPUFLAGS+="-march=mips32" -options NOFPU # No FPU options FPEMUL # emulate FPU insn # Options for necessary to use MD From da1df1e56852e873b4a2e2bfe0914cf412710238 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Mon, 31 Aug 2026 06:45:53 +0100 Subject: [PATCH 22/22] evbmips: Add piixide to the MALTA kernel QEMU Malta puts its IDE disk behind an Intel PIIX4 controller. Add the piixide attachment so the kernel finds the wd disk and can mount it as the root filesystem. --- sys/arch/evbmips/conf/MALTA | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/arch/evbmips/conf/MALTA b/sys/arch/evbmips/conf/MALTA index bb5f99121f4dd..f3acedbf26a87 100644 --- a/sys/arch/evbmips/conf/MALTA +++ b/sys/arch/evbmips/conf/MALTA @@ -189,6 +189,7 @@ com1 at isa? port 0x2f8 irq 3 # how to set up DMA modes for this chip. This may work, or may cause # a machine hang with some controllers. pciide* at pci? dev ? function ? flags 0x0000 # GENERIC pciide driver +piixide* at pci? dev ? function ? # Intel IDE controllers acardide* at pci? dev ? function ? # Acard IDE controllers aceride* at pci? dev ? function ? # Acer Lab IDE controllers artsata* at pci? dev ? function ? # Intel i31244 SATA controller