Index: contrib/llvm-project/clang/lib/AST/ExprConstant.cpp =================================================================== --- contrib/llvm-project/clang/lib/AST/ExprConstant.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/AST/ExprConstant.cpp (working copy) @@ -11542,7 +11542,8 @@ // Avoid emiting call for runtime decision on PowerPC 32-bit // The lock free possibilities on this platform are covered by the lines // above and we know in advance other cases require lock - if (Info.Ctx.getTargetInfo().getTriple().getArch() == llvm::Triple::ppc) { + if (Info.Ctx.getTargetInfo().getTriple().getArch() == llvm::Triple::ppc || + Info.Ctx.getTargetInfo().getTriple().getArch() == llvm::Triple::ppcle) { return Success(0, E); } Index: contrib/llvm-project/clang/lib/Basic/Targets/OSTargets.h =================================================================== --- contrib/llvm-project/clang/lib/Basic/Targets/OSTargets.h (revision 367806) +++ contrib/llvm-project/clang/lib/Basic/Targets/OSTargets.h (working copy) @@ -252,6 +252,7 @@ case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: this->MCountName = "_mcount"; @@ -408,6 +409,7 @@ case llvm::Triple::mips64: case llvm::Triple::mips64el: case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: this->MCountName = "_mcount"; Index: contrib/llvm-project/clang/lib/Basic/Targets/PPC.cpp =================================================================== --- contrib/llvm-project/clang/lib/Basic/Targets/PPC.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Basic/Targets/PPC.cpp (working copy) @@ -90,7 +90,8 @@ } // Target properties. - if (getTriple().getArch() == llvm::Triple::ppc64le) { + if (getTriple().getArch() == llvm::Triple::ppc64le || + getTriple().getArch() == llvm::Triple::ppcle) { Builder.defineMacro("_LITTLE_ENDIAN"); } else { if (!getTriple().isOSNetBSD() && Index: contrib/llvm-project/clang/lib/Basic/Targets/PPC.h =================================================================== --- contrib/llvm-project/clang/lib/Basic/Targets/PPC.h (revision 367806) +++ contrib/llvm-project/clang/lib/Basic/Targets/PPC.h (working copy) @@ -355,6 +355,8 @@ : PPCTargetInfo(Triple, Opts) { if (Triple.isOSAIX()) resetDataLayout("E-m:a-p:32:32-i64:64-n32"); + else if ((Triple.getArch() == llvm::Triple::ppcle)) + resetDataLayout("e-m:e-p:32:32-i64:64-n32"); else resetDataLayout("E-m:e-p:32:32-i64:64-n32"); Index: contrib/llvm-project/clang/lib/Basic/Targets.cpp =================================================================== --- contrib/llvm-project/clang/lib/Basic/Targets.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Basic/Targets.cpp (working copy) @@ -334,6 +334,16 @@ return new PPC32TargetInfo(Triple, Opts); } + case llvm::Triple::ppcle: + switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo(Triple, Opts); + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo(Triple, Opts); + default: + return new PPC32TargetInfo(Triple, Opts); + } + case llvm::Triple::ppc64: if (Triple.isOSDarwin()) return new DarwinPPC64TargetInfo(Triple, Opts); Index: contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp (working copy) @@ -4523,6 +4523,7 @@ case llvm::Triple::x86_64: return CGF->EmitX86BuiltinExpr(BuiltinID, E); case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: return CGF->EmitPPCBuiltinExpr(BuiltinID, E); Index: contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp (working copy) @@ -891,8 +891,8 @@ // PPC has no copy relocations and cannot use a plt entry as a symbol address. llvm::Triple::ArchType Arch = TT.getArch(); - if (Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppc64 || - Arch == llvm::Triple::ppc64le) + if (Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppcle || + Arch == llvm::Triple::ppc64 || Arch == llvm::Triple::ppc64le) return false; // If we can use copy relocations we can assume it is local. Index: contrib/llvm-project/clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- contrib/llvm-project/clang/lib/CodeGen/TargetInfo.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/CodeGen/TargetInfo.cpp (working copy) @@ -4838,7 +4838,8 @@ bool PPC32TargetCodeGenInfo::isStructReturnInRegABI( const llvm::Triple &Triple, const CodeGenOptions &Opts) { - assert(Triple.getArch() == llvm::Triple::ppc); + assert(Triple.getArch() == llvm::Triple::ppc || + Triple.getArch() == llvm::Triple::ppcle); switch (Opts.getStructReturnConvention()) { case CodeGenOptions::SRCK_Default: @@ -10874,6 +10875,13 @@ return SetCGInfo( new PPC32TargetCodeGenInfo(Types, IsSoftFloat, RetSmallStructInRegABI)); } + case llvm::Triple::ppcle: { + bool IsSoftFloat = CodeGenOpts.FloatABI == "soft"; + bool RetSmallStructInRegABI = + PPC32TargetCodeGenInfo::isStructReturnInRegABI(Triple, CodeGenOpts); + return SetCGInfo( + new PPC32TargetCodeGenInfo(Types, IsSoftFloat, RetSmallStructInRegABI)); + } case llvm::Triple::ppc64: if (Triple.isOSAIX()) return SetCGInfo(new AIXTargetCodeGenInfo(Types, /*Is64Bit*/ true)); Index: contrib/llvm-project/clang/lib/Driver/Driver.cpp =================================================================== --- contrib/llvm-project/clang/lib/Driver/Driver.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Driver/Driver.cpp (working copy) @@ -4932,6 +4932,7 @@ TC = std::make_unique(*this, Target, Args); else if (Target.getArch() == llvm::Triple::ppc || + Target.getArch() == llvm::Triple::ppcle || Target.getArch() == llvm::Triple::ppc64 || Target.getArch() == llvm::Triple::ppc64le) TC = std::make_unique(*this, Target, Index: contrib/llvm-project/clang/lib/Driver/ToolChain.cpp =================================================================== --- contrib/llvm-project/clang/lib/Driver/ToolChain.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Driver/ToolChain.cpp (working copy) @@ -238,6 +238,8 @@ return "arm64_32"; case llvm::Triple::ppc: return "ppc"; + case llvm::Triple::ppcle: + return "ppcle"; case llvm::Triple::ppc64: return "ppc64"; case llvm::Triple::ppc64le: Index: contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp (working copy) @@ -331,6 +331,7 @@ break; case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: ppc::getPPCTargetFeatures(D, Triple, Args, Features); @@ -527,6 +528,7 @@ // WebAssembly never wants frame pointers. return false; case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: case llvm::Triple::riscv32: @@ -1370,6 +1372,7 @@ return false; case llvm::Triple::hexagon: + case llvm::Triple::ppcle: case llvm::Triple::ppc64le: case llvm::Triple::riscv32: case llvm::Triple::riscv64: @@ -1586,6 +1589,7 @@ break; case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: AddPPCTargetArgs(Args, CmdArgs); Index: contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp (working copy) @@ -313,6 +313,7 @@ return ""; case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: { std::string TargetCPUName = ppc::getPPCTargetCPU(Args); Index: contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp =================================================================== --- contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp (working copy) @@ -42,6 +42,7 @@ CmdArgs.push_back("--32"); break; case llvm::Triple::ppc: + case llvm::Triple::ppcle: CmdArgs.push_back("-a32"); break; case llvm::Triple::mips: @@ -191,6 +192,11 @@ CmdArgs.push_back("-m"); CmdArgs.push_back("elf32ppc_fbsd"); break; + case llvm::Triple::ppcle: + CmdArgs.push_back("-m"); + // Use generic -- only usage is for freestanding. + CmdArgs.push_back("elf32lppc"); + break; case llvm::Triple::mips: CmdArgs.push_back("-m"); CmdArgs.push_back("elf32btsmip_fbsd"); @@ -372,7 +378,8 @@ // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall // back to '/usr/lib' if it doesn't exist. if ((Triple.getArch() == llvm::Triple::x86 || Triple.isMIPS32() || - Triple.getArch() == llvm::Triple::ppc) && + Triple.getArch() == llvm::Triple::ppc || + Triple.getArch() == llvm::Triple::ppcle) && D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o")) getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32"); else Index: contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp (working copy) @@ -116,6 +116,7 @@ break; case llvm::Triple::x86: case llvm::Triple::ppc: + case llvm::Triple::ppcle: CmdArgs.push_back("-m32"); break; case llvm::Triple::x86_64: @@ -271,6 +272,8 @@ return isArmBigEndian(T, Args) ? "armelfb_linux_eabi" : "armelf_linux_eabi"; case llvm::Triple::ppc: return "elf32ppclinux"; + case llvm::Triple::ppcle: + return "elf32lppc"; case llvm::Triple::ppc64: return "elf64ppc"; case llvm::Triple::ppc64le: @@ -736,6 +739,14 @@ ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple()))); break; } + case llvm::Triple::ppcle: { + CmdArgs.push_back("-a32"); + CmdArgs.push_back("-mppc"); + CmdArgs.push_back("-mlittle-endian"); + CmdArgs.push_back( + ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple()))); + break; + } case llvm::Triple::ppc64: { CmdArgs.push_back("-a64"); CmdArgs.push_back("-mppc64"); @@ -2125,6 +2136,12 @@ // On 32-bit PowerPC systems running SUSE Linux, gcc is configured as a // 64-bit compiler which defaults to "-m32", hence "powerpc64-suse-linux". "powerpc64-suse-linux", "powerpc-montavista-linuxspe"}; + // PPCLE is only used in niche situations such as bootloaders + // and compatibility shims. + static const char *const PPCLELibDirs[] = {"/lib32", "/lib"}; + static const char *const PPCLETriples[] = { + "powerpcle-unknown-elf", "powerpcle-unknown-linux-gnu", + "powerpcle-unknown-freebsd"}; static const char *const PPC64LibDirs[] = {"/lib64", "/lib"}; static const char *const PPC64Triples[] = { "powerpc64-linux-gnu", "powerpc64-unknown-linux-gnu", @@ -2365,6 +2382,12 @@ BiarchLibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs)); BiarchTripleAliases.append(begin(PPC64Triples), end(PPC64Triples)); break; + case llvm::Triple::ppcle: + LibDirs.append(begin(PPCLELibDirs), end(PPCLELibDirs)); + TripleAliases.append(begin(PPCLETriples), end(PPCLETriples)); + BiarchLibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs)); + BiarchTripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples)); + break; case llvm::Triple::ppc64: LibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs)); TripleAliases.append(begin(PPC64Triples), end(PPC64Triples)); @@ -2374,6 +2397,8 @@ case llvm::Triple::ppc64le: LibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs)); TripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples)); + BiarchLibDirs.append(begin(PPCLELibDirs), end(PPCLELibDirs)); + BiarchTripleAliases.append(begin(PPCLETriples), end(PPCLETriples)); break; case llvm::Triple::riscv32: LibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs)); @@ -2697,6 +2722,7 @@ case llvm::Triple::thumb: case llvm::Triple::thumbeb: case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: case llvm::Triple::riscv32: Index: contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp =================================================================== --- contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp (working copy) @@ -142,6 +142,10 @@ if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnu")) return "powerpc-linux-gnu"; break; + case llvm::Triple::ppcle: + if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnu")) + return "powerpcle-linux-gnu"; + break; case llvm::Triple::ppc64: if (D.getVFS().exists(SysRoot + "/lib/powerpc64-linux-gnu")) return "powerpc64-linux-gnu"; @@ -195,7 +199,8 @@ // reasoning about oslibdir spellings with the lib dir spellings in the // GCCInstallationDetector, but that is a more significant refactoring. if (Triple.getArch() == llvm::Triple::x86 || - Triple.getArch() == llvm::Triple::ppc) + Triple.getArch() == llvm::Triple::ppc || + Triple.getArch() == llvm::Triple::ppcle) return "lib32"; if (Triple.getArch() == llvm::Triple::x86_64 && @@ -495,6 +500,10 @@ LibDir = "lib"; Loader = "ld.so.1"; break; + case llvm::Triple::ppcle: + LibDir = "lib32"; // 32 bit LE is never a native arch. + Loader = "ld.so.1"; + break; case llvm::Triple::ppc64: LibDir = "lib64"; Loader = @@ -642,6 +651,8 @@ const StringRef PPCMultiarchIncludeDirs[] = { "/usr/include/powerpc-linux-gnu", "/usr/include/powerpc-linux-gnuspe"}; + const StringRef PPCLEMultiarchIncludeDirs[] = { + "/usr/include/powerpcle-linux-gnu"}; const StringRef PPC64MultiarchIncludeDirs[] = { "/usr/include/powerpc64-linux-gnu"}; const StringRef PPC64LEMultiarchIncludeDirs[] = { @@ -715,6 +726,9 @@ case llvm::Triple::ppc: MultiarchIncludeDirs = PPCMultiarchIncludeDirs; break; + case llvm::Triple::ppcle: + MultiarchIncludeDirs = PPCLEMultiarchIncludeDirs; + break; case llvm::Triple::ppc64: MultiarchIncludeDirs = PPC64MultiarchIncludeDirs; break; Index: contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp (working copy) @@ -3169,6 +3169,7 @@ if (TT.getArch() == llvm::Triple::UnknownArch || !(TT.getArch() == llvm::Triple::aarch64 || TT.getArch() == llvm::Triple::ppc || + TT.getArch() == llvm::Triple::ppcle || TT.getArch() == llvm::Triple::ppc64 || TT.getArch() == llvm::Triple::ppc64le || TT.getArch() == llvm::Triple::nvptx || Index: contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp =================================================================== --- contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp (revision 367806) +++ contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp (working copy) @@ -1425,6 +1425,7 @@ case llvm::Triple::x86_64: return CheckX86BuiltinFunctionCall(TI, BuiltinID, TheCall); case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: return CheckPPCBuiltinFunctionCall(TI, BuiltinID, TheCall); Index: contrib/llvm-project/lld/ELF/Driver.cpp =================================================================== --- contrib/llvm-project/lld/ELF/Driver.cpp (revision 367806) +++ contrib/llvm-project/lld/ELF/Driver.cpp (working copy) @@ -142,6 +142,7 @@ .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) .Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC}) + .Cases("elf32lppc", "elf32lppclinux", {ELF32LEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) Index: contrib/llvm-project/lld/ELF/InputFiles.cpp =================================================================== --- contrib/llvm-project/lld/ELF/InputFiles.cpp (revision 367806) +++ contrib/llvm-project/lld/ELF/InputFiles.cpp (working copy) @@ -1514,6 +1514,7 @@ case Triple::msp430: return EM_MSP430; case Triple::ppc: + case Triple::ppcle: return EM_PPC; case Triple::ppc64: case Triple::ppc64le: Index: contrib/llvm-project/lld/ELF/ScriptParser.cpp =================================================================== --- contrib/llvm-project/lld/ELF/ScriptParser.cpp (revision 367806) +++ contrib/llvm-project/lld/ELF/ScriptParser.cpp (working copy) @@ -410,6 +410,7 @@ .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) .Case("elf32-powerpc", {ELF32BEKind, EM_PPC}) + .Case("elf32-powerpcle", {ELF32LEKind, EM_PPC}) .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) Index: contrib/llvm-project/llvm/include/llvm/ADT/Triple.h =================================================================== --- contrib/llvm-project/llvm/include/llvm/ADT/Triple.h (revision 367806) +++ contrib/llvm-project/llvm/include/llvm/ADT/Triple.h (working copy) @@ -63,6 +63,7 @@ mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el msp430, // MSP430: msp430 ppc, // PPC: powerpc + ppcle, // PPCLE: powerpc (little endian) ppc64, // PPC64: powerpc64, ppu ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX Index: contrib/llvm-project/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def =================================================================== --- contrib/llvm-project/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def (revision 367806) +++ contrib/llvm-project/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def (working copy) @@ -1078,6 +1078,7 @@ __OMP_TRAIT_PROPERTY(device, arch, aarch64_be) __OMP_TRAIT_PROPERTY(device, arch, aarch64_32) __OMP_TRAIT_PROPERTY(device, arch, ppc) +__OMP_TRAIT_PROPERTY(device, arch, ppcle) __OMP_TRAIT_PROPERTY(device, arch, ppc64) __OMP_TRAIT_PROPERTY(device, arch, ppc64le) __OMP_TRAIT_PROPERTY(device, arch, x86) Index: contrib/llvm-project/llvm/include/llvm/Object/ELFObjectFile.h =================================================================== --- contrib/llvm-project/llvm/include/llvm/Object/ELFObjectFile.h (revision 367806) +++ contrib/llvm-project/llvm/include/llvm/Object/ELFObjectFile.h (working copy) @@ -1106,7 +1106,7 @@ case ELF::EM_MSP430: return "elf32-msp430"; case ELF::EM_PPC: - return "elf32-powerpc"; + return (IsLittleEndian ? "elf32-powerpcle" : "elf32-powerpc"); case ELF::EM_RISCV: return "elf32-littleriscv"; case ELF::EM_SPARC: @@ -1180,7 +1180,7 @@ case ELF::EM_MSP430: return Triple::msp430; case ELF::EM_PPC: - return Triple::ppc; + return IsLittleEndian ? Triple::ppcle : Triple::ppc; case ELF::EM_PPC64: return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; case ELF::EM_RISCV: Index: contrib/llvm-project/llvm/lib/CodeGen/TargetLoweringBase.cpp =================================================================== --- contrib/llvm-project/llvm/lib/CodeGen/TargetLoweringBase.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/CodeGen/TargetLoweringBase.cpp (working copy) @@ -135,7 +135,8 @@ setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C); // For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf". - if (TT.getArch() == Triple::ppc || TT.isPPC64()) { + if (TT.getArch() == Triple::ppc || TT.getArch() == Triple::ppcle || + TT.isPPC64()) { setLibcallName(RTLIB::ADD_F128, "__addkf3"); setLibcallName(RTLIB::SUB_F128, "__subkf3"); setLibcallName(RTLIB::MUL_F128, "__mulkf3"); Index: contrib/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- contrib/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (working copy) @@ -122,6 +122,7 @@ // Fallthrough if not using EHABI LLVM_FALLTHROUGH; case Triple::ppc: + case Triple::ppcle: case Triple::x86: PersonalityEncoding = isPositionIndependent() ? dwarf::DW_EH_PE_indirect | Index: contrib/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp =================================================================== --- contrib/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp (working copy) @@ -46,6 +46,7 @@ uint64_t OpdAddress = 0; // Find the .opd (function descriptor) section if any, for big-endian // PowerPC64 ELF. + // XXX Only act when using ELFv1! if (Obj->getArch() == Triple::ppc64) { for (section_iterator Section : Obj->sections()) { Expected NameOrErr = Section->getName(); Index: contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp =================================================================== --- contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp (working copy) @@ -961,7 +961,8 @@ resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; - case Triple::ppc: + case Triple::ppc: // Fall through. + case Triple::ppcle: resolvePPC32Relocation(Section, Offset, Value, Type, Addend); break; case Triple::ppc64: // Fall through. Index: contrib/llvm-project/llvm/lib/Frontend/OpenMP/OMPContext.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Frontend/OpenMP/OMPContext.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Frontend/OpenMP/OMPContext.cpp (working copy) @@ -40,6 +40,7 @@ case Triple::mips64: case Triple::mips64el: case Triple::ppc: + case Triple::ppcle: case Triple::ppc64: case Triple::ppc64le: case Triple::x86: Index: contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp (working copy) @@ -646,6 +646,7 @@ case Triple::x86: return {supportsX86, resolveX86}; case Triple::ppc: + case Triple::ppcle: return {supportsPPC32, resolvePPC32}; case Triple::arm: case Triple::armeb: Index: contrib/llvm-project/llvm/lib/Support/Triple.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Support/Triple.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Support/Triple.cpp (working copy) @@ -53,6 +53,7 @@ case ppc64: return "powerpc64"; case ppc64le: return "powerpc64le"; case ppc: return "powerpc"; + case ppcle: return "powerpcle"; case r600: return "r600"; case renderscript32: return "renderscript32"; case renderscript64: return "renderscript64"; @@ -100,7 +101,8 @@ case ppc64: case ppc64le: - case ppc: return "ppc"; + case ppc: + case ppcle: return "ppc"; case mips: case mipsel: @@ -286,6 +288,7 @@ .Case("ppc64", ppc64) .Case("ppc32", ppc) .Case("ppc", ppc) + .Case("ppcle", ppc) .Case("ppc64le", ppc64le) .Case("r600", r600) .Case("amdgcn", amdgcn) @@ -396,6 +399,7 @@ .Cases("i786", "i886", "i986", Triple::x86) .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64) .Cases("powerpc", "powerpcspe", "ppc", "ppc32", Triple::ppc) + .Cases("powerpcle", "ppcle", "ppc32le", Triple::ppcle) .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64) .Cases("powerpc64le", "ppc64le", Triple::ppc64le) .Case("xscale", Triple::arm) @@ -694,6 +698,7 @@ case Triple::msp430: case Triple::nvptx64: case Triple::nvptx: + case Triple::ppcle: case Triple::ppc64le: case Triple::r600: case Triple::renderscript32: @@ -1258,6 +1263,7 @@ case llvm::Triple::mipsel: case llvm::Triple::nvptx: case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::r600: case llvm::Triple::renderscript32: case llvm::Triple::riscv32: @@ -1321,7 +1327,6 @@ case Triple::bpfeb: case Triple::bpfel: case Triple::msp430: - case Triple::ppc64le: case Triple::systemz: case Triple::ve: T.setArch(UnknownArch); @@ -1341,6 +1346,7 @@ case Triple::mipsel: case Triple::nvptx: case Triple::ppc: + case Triple::ppcle: case Triple::r600: case Triple::renderscript32: case Triple::riscv32: @@ -1367,6 +1373,7 @@ case Triple::mips64el: T.setArch(Triple::mipsel); break; case Triple::nvptx64: T.setArch(Triple::nvptx); break; case Triple::ppc64: T.setArch(Triple::ppc); break; + case Triple::ppc64le: T.setArch(Triple::ppcle); break; case Triple::renderscript64: T.setArch(Triple::renderscript32); break; case Triple::riscv64: T.setArch(Triple::riscv32); break; case Triple::sparcv9: T.setArch(Triple::sparc); break; @@ -1430,6 +1437,7 @@ case Triple::mipsel: T.setArch(Triple::mips64el); break; case Triple::nvptx: T.setArch(Triple::nvptx64); break; case Triple::ppc: T.setArch(Triple::ppc64); break; + case Triple::ppcle: T.setArch(Triple::ppc64le); break; case Triple::renderscript32: T.setArch(Triple::renderscript64); break; case Triple::riscv32: T.setArch(Triple::riscv64); break; case Triple::sparc: T.setArch(Triple::sparcv9); break; @@ -1488,6 +1496,7 @@ case Triple::bpfel: T.setArch(Triple::bpfeb); break; case Triple::mips64el:T.setArch(Triple::mips64); break; case Triple::mipsel: T.setArch(Triple::mips); break; + case Triple::ppcle: T.setArch(Triple::ppc); break; case Triple::ppc64le: T.setArch(Triple::ppc64); break; case Triple::sparcel: T.setArch(Triple::sparc); break; case Triple::tcele: T.setArch(Triple::tce); break; @@ -1505,7 +1514,6 @@ switch (getArch()) { case Triple::UnknownArch: case Triple::lanai: - case Triple::ppc: case Triple::sparcv9: case Triple::systemz: @@ -1520,6 +1528,7 @@ case Triple::bpfeb: T.setArch(Triple::bpfel); break; case Triple::mips64: T.setArch(Triple::mips64el); break; case Triple::mips: T.setArch(Triple::mipsel); break; + case Triple::ppc: T.setArch(Triple::ppcle); break; case Triple::ppc64: T.setArch(Triple::ppc64le); break; case Triple::sparc: T.setArch(Triple::sparcel); break; case Triple::tce: T.setArch(Triple::tcele); break; @@ -1550,6 +1559,7 @@ case Triple::msp430: case Triple::nvptx64: case Triple::nvptx: + case Triple::ppcle: case Triple::ppc64le: case Triple::r600: case Triple::renderscript32: Index: contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp (working copy) @@ -1809,8 +1809,9 @@ /// Force static initialization. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmParser() { RegisterMCAsmParser A(getThePPC32Target()); - RegisterMCAsmParser B(getThePPC64Target()); - RegisterMCAsmParser C(getThePPC64LETarget()); + RegisterMCAsmParser B(getThePPC32LETarget()); + RegisterMCAsmParser C(getThePPC64Target()); + RegisterMCAsmParser D(getThePPC64LETarget()); } #define GET_REGISTER_MATCHER Index: contrib/llvm-project/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp (working copy) @@ -54,6 +54,8 @@ // Register the disassembler for each target. TargetRegistry::RegisterMCDisassembler(getThePPC32Target(), createPPCDisassembler); + TargetRegistry::RegisterMCDisassembler(getThePPC32LETarget(), + createPPCLEDisassembler); TargetRegistry::RegisterMCDisassembler(getThePPC64Target(), createPPCDisassembler); TargetRegistry::RegisterMCDisassembler(getThePPC64LETarget(), Index: contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp (working copy) @@ -26,7 +26,8 @@ if (is64Bit) { CodePointerSize = CalleeSaveStackSlotSize = 8; } - IsLittleEndian = T.getArch() == Triple::ppc64le; + IsLittleEndian = T.getArch() == Triple::ppc64le || + T.getArch() == Triple::ppcle; // ".comm align is in bytes but .align is pow-2." AlignmentIsInBytes = false; @@ -56,7 +57,7 @@ void PPCXCOFFMCAsmInfo::anchor() {} PPCXCOFFMCAsmInfo::PPCXCOFFMCAsmInfo(bool Is64Bit, const Triple &T) { - if (T.getArch() == Triple::ppc64le) + if (T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle) report_fatal_error("XCOFF is not supported for little-endian targets"); CodePointerSize = CalleeSaveStackSlotSize = Is64Bit ? 8 : 4; Index: contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp (working copy) @@ -335,7 +335,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() { for (Target *T : - {&getThePPC32Target(), &getThePPC64Target(), &getThePPC64LETarget()}) { + {&getThePPC32Target(), &getThePPC32LETarget(), &getThePPC64Target(), + &getThePPC64LETarget()}) { // Register the MC asm info. RegisterMCAsmInfoFn C(*T, createPPCMCAsmInfo); Index: contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp (working copy) @@ -1829,6 +1829,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmPrinter() { TargetRegistry::RegisterAsmPrinter(getThePPC32Target(), createPPCAsmPrinterPass); + TargetRegistry::RegisterAsmPrinter(getThePPC32LETarget(), + createPPCAsmPrinterPass); TargetRegistry::RegisterAsmPrinter(getThePPC64Target(), createPPCAsmPrinterPass); TargetRegistry::RegisterAsmPrinter(getThePPC64LETarget(), Index: contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp (working copy) @@ -174,7 +174,8 @@ // Determine endianness. // FIXME: Part of the TargetMachine. - IsLittleEndian = (TargetTriple.getArch() == Triple::ppc64le); + IsLittleEndian = (TargetTriple.getArch() == Triple::ppc64le || + TargetTriple.getArch() == Triple::ppcle); } bool PPCSubtarget::enableMachineScheduler() const { return true; } Index: contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp (working copy) @@ -98,8 +98,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTarget() { // Register the targets RegisterTargetMachine A(getThePPC32Target()); - RegisterTargetMachine B(getThePPC64Target()); - RegisterTargetMachine C(getThePPC64LETarget()); + RegisterTargetMachine B(getThePPC32LETarget()); + RegisterTargetMachine C(getThePPC64Target()); + RegisterTargetMachine D(getThePPC64LETarget()); PassRegistry &PR = *PassRegistry::getPassRegistry(); #ifndef NDEBUG @@ -128,8 +129,8 @@ bool is64Bit = T.getArch() == Triple::ppc64 || T.getArch() == Triple::ppc64le; std::string Ret; - // Most PPC* platforms are big endian, PPC64LE is little endian. - if (T.getArch() == Triple::ppc64le) + // Most PPC* platforms are big endian, PPC(64)LE is little endian. + if (T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle) Ret = "e"; else Ret = "E"; Index: contrib/llvm-project/llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp (working copy) @@ -14,6 +14,10 @@ static Target ThePPC32Target; return ThePPC32Target; } +Target &llvm::getThePPC32LETarget() { + static Target ThePPC32LETarget; + return ThePPC32LETarget; +} Target &llvm::getThePPC64Target() { static Target ThePPC64Target; return ThePPC64Target; @@ -24,9 +28,12 @@ } extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetInfo() { - RegisterTarget X(getThePPC32Target(), "ppc32", + RegisterTarget W(getThePPC32Target(), "ppc32", "PowerPC 32", "PPC"); + RegisterTarget X( + getThePPC32LETarget(), "ppc32le", "PowerPC 32 LE", "PPC"); + RegisterTarget Y(getThePPC64Target(), "ppc64", "PowerPC 64", "PPC"); Index: contrib/llvm-project/llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.h =================================================================== --- contrib/llvm-project/llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.h (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.h (working copy) @@ -14,6 +14,7 @@ class Target; Target &getThePPC32Target(); +Target &getThePPC32LETarget(); Target &getThePPC64Target(); Target &getThePPC64LETarget(); Index: contrib/llvm-project/llvm/lib/Target/TargetMachine.cpp =================================================================== --- contrib/llvm-project/llvm/lib/Target/TargetMachine.cpp (revision 367806) +++ contrib/llvm-project/llvm/lib/Target/TargetMachine.cpp (working copy) @@ -187,7 +187,7 @@ Triple::ArchType Arch = TT.getArch(); // PowerPC prefers avoiding copy relocations. - if (Arch == Triple::ppc || TT.isPPC64()) + if (Arch == Triple::ppc || Arch == Triple::ppcle || TT.isPPC64()) return false; // Check if we can use copy relocations. Index: stand/defs.mk =================================================================== --- stand/defs.mk (revision 367806) +++ stand/defs.mk (working copy) @@ -105,10 +105,12 @@ # Machine specific flags for all builds here -# Ensure PowerPC64 and PowerPC64LE boot loaders are compiled as 32 bit -# and in big endian. -.if ${MACHINE_ARCH:Mpowerpc64*} != "" +# Ensure PowerPC64 and PowerPC64LE boot loaders are compiled as 32 bit. +# PowerPC64LE boot loaders are 32-bit little-endian. +.if ${MACHINE_ARCH} == "powerpc64" CFLAGS+= -m32 -mcpu=powerpc -mbig-endian +.elif ${MACHINE_ARCH} == "powerpc64le" +CFLAGS+= -m32 -mcpu=powerpc -mlittle-endian .endif # For amd64, there's a bit of mixed bag. Some of the tree (i386, lib*32) is Index: stand/libofw/openfirm.c =================================================================== --- stand/libofw/openfirm.c (revision 367806) +++ stand/libofw/openfirm.c (working copy) @@ -58,6 +58,8 @@ #include __FBSDID("$FreeBSD$"); +#include + #include #include @@ -71,6 +73,13 @@ ihandle_t memory; int real_mode = 0; +#define IN(x) htobe32((cell_t)x) +#define OUT(x) be32toh(x) +#define SETUP(a, b, c, d) \ + a.name = IN( (b) ); \ + a.nargs = IN( (c) ); \ + a.nreturns = IN( (d) ); + /* Initialiser */ void @@ -117,16 +126,13 @@ cell_t nreturns; cell_t service; cell_t missing; - } args = { - (cell_t)"test", - 1, - 1, - }; + } args = {}; + SETUP(args, "test", 1, 1); - args.service = (cell_t)name; + args.service = IN(name); if (openfirmware(&args) == -1) return (-1); - return (args.missing); + return (OUT(args.missing)); } /* Return firmware millisecond count. */ @@ -138,14 +144,11 @@ cell_t nargs; cell_t nreturns; cell_t ms; - } args = { - (cell_t)"milliseconds", - 0, - 1, - }; + } args = {}; + SETUP(args, "milliseconds", 0, 1); openfirmware(&args); - return (args.ms); + return (OUT(args.ms)); } /* @@ -162,11 +165,8 @@ cell_t nreturns; cell_t node; cell_t next; - } args = { - (cell_t)"peer", - 1, - 1, - }; + } args = {}; + SETUP(args, "peer", 1, 1); args.node = node; if (openfirmware(&args) == -1) @@ -184,12 +184,9 @@ cell_t nreturns; cell_t node; cell_t child; - } args = { - (cell_t)"child", - 1, - 1, - }; - + } args = {}; + SETUP(args, "child", 1, 1); + args.node = node; if (openfirmware(&args) == -1) return (-1); @@ -206,11 +203,8 @@ cell_t nreturns; cell_t node; cell_t parent; - } args = { - (cell_t)"parent", - 1, - 1, - }; + } args = {}; + SETUP(args, "parent", 1, 1); args.node = node; if (openfirmware(&args) == -1) @@ -228,11 +222,8 @@ cell_t nreturns; cell_t instance; cell_t package; - } args = { - (cell_t)"instance-to-package", - 1, - 1, - }; + } args = {}; + SETUP(args, "instance-to-package", 1, 1); args.instance = instance; if (openfirmware(&args) == -1) @@ -251,17 +242,14 @@ cell_t package; cell_t propname; cell_t proplen; - } args = { - (cell_t)"getproplen", - 2, - 1, - }; + } args = {}; + SETUP(args, "getproplen", 2, 1); args.package = package; - args.propname = (cell_t)propname; + args.propname = IN(propname); if (openfirmware(&args) == -1) return (-1); - return (args.proplen); + return (OUT(args.proplen)); } /* Get the value of a property of a package. */ @@ -277,21 +265,33 @@ cell_t buf; cell_t buflen; cell_t size; - } args = { - (cell_t)"getprop", - 4, - 1, - }; + } args = {}; + SETUP(args, "getprop", 4, 1); args.package = package; - args.propname = (cell_t)propname; - args.buf = (cell_t)buf; - args.buflen = buflen; + args.propname = IN(propname); + args.buf = IN(buf); + args.buflen = IN(buflen); if (openfirmware(&args) == -1) return (-1); - return (args.size); + return (OUT(args.size)); } +/* Decode a binary property from a package. */ +int +OF_getencprop(phandle_t package, const char *propname, cell_t *buf, int buflen) +{ + int retval, i; + retval = OF_getprop(package, propname, buf, buflen); + if (retval == -1) + return (retval); + + for (i = 0; i < buflen/4; i++) + buf[i] = be32toh((uint32_t)buf[i]); + + return (retval); +} + /* Get the next property of a package. */ int OF_nextprop(phandle_t package, const char *previous, char *buf) @@ -304,18 +304,15 @@ cell_t previous; cell_t buf; cell_t flag; - } args = { - (cell_t)"nextprop", - 3, - 1, - }; + } args = {}; + SETUP(args, "nextprop", 3, 1); args.package = package; - args.previous = (cell_t)previous; - args.buf = (cell_t)buf; + args.previous = IN(previous); + args.buf = IN(buf); if (openfirmware(&args) == -1) return (-1); - return (args.flag); + return (OUT(args.flag)); } /* Set the value of a property of a package. */ @@ -332,19 +329,16 @@ cell_t buf; cell_t len; cell_t size; - } args = { - (cell_t)"setprop", - 4, - 1, - }; + } args = {}; + SETUP(args, "setprop", 4, 1); args.package = package; - args.propname = (cell_t)propname; - args.buf = (cell_t)buf; - args.len = len; + args.propname = IN(propname); + args.buf = IN(buf); + args.len = IN(len); if (openfirmware(&args) == -1) return (-1); - return (args.size); + return (OUT(args.size)); } /* Convert a device specifier to a fully qualified pathname. */ @@ -359,18 +353,15 @@ cell_t buf; cell_t len; cell_t size; - } args = { - (cell_t)"canon", - 3, - 1, - }; + } args = {}; + SETUP(args, "canon", 3, 1); - args.device = (cell_t)device; - args.buf = (cell_t)buf; - args.len = len; + args.device = IN(device); + args.buf = IN(buf); + args.len = IN(len); if (openfirmware(&args) == -1) return (-1); - return (args.size); + return (OUT(args.size)); } /* Return a package handle for the specified device. */ @@ -383,13 +374,10 @@ cell_t nreturns; cell_t device; cell_t package; - } args = { - (cell_t)"finddevice", - 1, - 1, - }; + } args = {}; + SETUP(args, "finddevice", 1, 1); - args.device = (cell_t)device; + args.device = IN(device); if (openfirmware(&args) == -1) return (-1); return (args.package); @@ -407,18 +395,15 @@ cell_t buf; cell_t len; cell_t size; - } args = { - (cell_t)"instance-to-path", - 3, - 1, - }; + } args = {}; + SETUP(args, "instance-to-path", 3, 1); args.instance = instance; - args.buf = (cell_t)buf; - args.len = len; + args.buf = IN(buf); + args.len = IN(len); if (openfirmware(&args) == -1) return (-1); - return (args.size); + return (OUT(args.size)); } /* Return the fully qualified pathname corresponding to a package. */ @@ -433,18 +418,15 @@ cell_t buf; cell_t len; cell_t size; - } args = { - (cell_t)"package-to-path", - 3, - 1, - }; + } args = {}; + SETUP(args, "package-to-path", 3, 1); args.package = package; - args.buf = (cell_t)buf; - args.len = len; + args.buf = IN(buf); + args.len = IN(len); if (openfirmware(&args) == -1) return (-1); - return (args.size); + return (OUT(args.size)); } /* Call the method in the scope of a given instance. */ @@ -459,30 +441,26 @@ cell_t method; cell_t instance; cell_t args_n_results[12]; - } args = { - (cell_t)"call-method", - 2, - 1, - }; + } args = {}; + SETUP(args, "call-method", nargs + 2, nreturns + 1); cell_t *cp; int n; if (nargs > 6) return (-1); - args.nargs = nargs + 2; - args.nreturns = nreturns + 1; - args.method = (cell_t)method; + args.method = IN(method); args.instance = instance; va_start(ap, nreturns); for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;) - *--cp = va_arg(ap, cell_t); + *--cp = IN(va_arg(ap, cell_t)); if (openfirmware(&args) == -1) return (-1); if (args.args_n_results[nargs]) - return (args.args_n_results[nargs]); + return (OUT(args.args_n_results[nargs])); + /* XXX what if ihandles or phandles are returned */ for (cp = (cell_t *)(args.args_n_results + nargs + (n = args.nreturns)); --n > 0;) - *va_arg(ap, cell_t *) = *--cp; + *va_arg(ap, cell_t *) = OUT(*--cp); va_end(ap); return (0); } @@ -501,13 +479,10 @@ cell_t nreturns; cell_t device; cell_t instance; - } args = { - (cell_t)"open", - 1, - 1, - }; + } args = {}; + SETUP(args, "open", 1, 1); - args.device = (cell_t)device; + args.device = IN(device); if (openfirmware(&args) == -1 || args.instance == 0) { return (-1); } @@ -523,10 +498,8 @@ cell_t nargs; cell_t nreturns; cell_t instance; - } args = { - (cell_t)"close", - 1, - }; + } args = {}; + SETUP(args, "close", 1, 0); args.instance = instance; openfirmware(&args); @@ -544,15 +517,12 @@ cell_t addr; cell_t len; cell_t actual; - } args = { - (cell_t)"read", - 3, - 1, - }; + } args = {}; + SETUP(args, "read", 3, 1); args.instance = instance; - args.addr = (cell_t)addr; - args.len = len; + args.addr = IN(addr); + args.len = IN(len); #if defined(OPENFIRM_DEBUG) printf("OF_read: called with instance=%08x, addr=%p, len=%d\n", @@ -567,7 +537,7 @@ args.instance, args.addr, args.len, args.actual); #endif - return (args.actual); + return (OUT(args.actual)); } /* Write to an instance. */ @@ -582,18 +552,15 @@ cell_t addr; cell_t len; cell_t actual; - } args = { - (cell_t)"write", - 3, - 1, - }; + } args = {}; + SETUP(args, "write", 3, 1); args.instance = instance; - args.addr = (cell_t)addr; - args.len = len; + args.addr = IN(addr); + args.len = IN(len); if (openfirmware(&args) == -1) return (-1); - return (args.actual); + return (OUT(args.actual)); } /* Seek to a position. */ @@ -608,18 +575,15 @@ cell_t poshi; cell_t poslo; cell_t status; - } args = { - (cell_t)"seek", - 3, - 1, - }; + } args = {}; + SETUP(args, "seek", 3, 1); args.instance = instance; - args.poshi = pos >> 32; - args.poslo = pos; + args.poshi = IN(((uint64_t)pos >> 32)); + args.poslo = IN(pos); if (openfirmware(&args) == -1) return (-1); - return (args.status); + return (OUT(args.status)); } /* Blocks. */ @@ -633,16 +597,13 @@ cell_t instance; cell_t result; cell_t blocks; - } args = { - (cell_t)"#blocks", - 2, - 1, - }; + } args = {}; + SETUP(args, "#blocks", 2, 1); args.instance = instance; if (openfirmware(&args) == -1) return ((unsigned int)-1); - return (args.blocks); + return (OUT(args.blocks)); } /* Block size. */ @@ -656,16 +617,13 @@ cell_t instance; cell_t result; cell_t size; - } args = { - (cell_t)"block-size", - 2, - 1, - }; + } args = {}; + SETUP(args, "block-size", 2, 1); args.instance = instance; if (openfirmware(&args) == -1) return (512); - return (args.size); + return (OUT(args.size)); } /* @@ -684,18 +642,15 @@ cell_t size; cell_t align; cell_t baseaddr; - } args = { - (cell_t)"claim", - 3, - 1, - }; + } args = {}; + SETUP(args, "claim", 3, 1); - args.virt = (cell_t)virt; - args.size = size; - args.align = align; + args.virt = IN(virt); + args.size = IN(size); + args.align = IN(align); if (openfirmware(&args) == -1) return ((void *)-1); - return ((void *)args.baseaddr); + return ((void *)OUT(args.baseaddr)); } /* Release an area of memory. */ @@ -708,13 +663,11 @@ cell_t nreturns; cell_t virt; cell_t size; - } args = { - (cell_t)"release", - 2, - }; + } args = {}; + SETUP(args, "release", 2, 0); - args.virt = (cell_t)virt; - args.size = size; + args.virt = IN(virt); + args.size = IN(size); openfirmware(&args); } @@ -731,12 +684,10 @@ cell_t nargs; cell_t nreturns; cell_t bootspec; - } args = { - (cell_t)"boot", - 1, - }; + } args = {}; + SETUP(args, "boot", 1, 0); - args.bootspec = (cell_t)bootspec; + args.bootspec = IN(bootspec); openfirmware(&args); for (;;) /* just in case */ ; @@ -750,9 +701,8 @@ cell_t name; cell_t nargs; cell_t nreturns; - } args = { - (cell_t)"enter", - }; + } args = {}; + SETUP(args, "enter", 0, 0); openfirmware(&args); /* We may come back. */ @@ -766,9 +716,8 @@ cell_t name; cell_t nargs; cell_t nreturns; - } args = { - (cell_t)"exit", - }; + } args = {}; + SETUP(args, "exit", 0, 0); openfirmware(&args); for (;;) /* just in case */ @@ -782,9 +731,8 @@ cell_t name; cell_t nargs; cell_t nreturns; - } args = { - (cell_t)"quiesce", - }; + } args = {}; + SETUP(args, "quiesce", 0, 0); openfirmware(&args); } @@ -803,16 +751,14 @@ cell_t entry; cell_t arg; cell_t len; - } args = { - (cell_t)"chain", - 5, - }; + } args = {}; + SETUP(args, "chain", 5, 0); - args.virt = (cell_t)virt; - args.size = size; - args.entry = (cell_t)entry; - args.arg = (cell_t)arg; - args.len = len; + args.virt = IN(virt); + args.size = IN(size); + args.entry = IN(entry); + args.arg = IN(arg); + args.len = IN(len); openfirmware(&args); } #else Index: stand/libofw/openfirm.h =================================================================== --- stand/libofw/openfirm.h (revision 367806) +++ stand/libofw/openfirm.h (working copy) @@ -65,9 +65,9 @@ #include #include -typedef unsigned int ihandle_t; -typedef unsigned int phandle_t; -typedef unsigned long int cell_t; +typedef uint32_t ihandle_t; +typedef uint32_t phandle_t; +typedef uint32_t cell_t; extern int (*openfirmware)(void *); extern phandle_t chosen; @@ -91,6 +91,7 @@ phandle_t OF_instance_to_package(ihandle_t); int OF_getproplen(phandle_t, const char *); int OF_getprop(phandle_t, const char *, void *, int); +int OF_getencprop(phandle_t, const char *, cell_t *, int); int OF_nextprop(phandle_t, const char *, char *); int OF_setprop(phandle_t, const char *, void *, int); int OF_canon(const char *, char *, int); Index: stand/powerpc/Makefile =================================================================== --- stand/powerpc/Makefile (revision 367806) +++ stand/powerpc/Makefile (working copy) @@ -4,10 +4,10 @@ .include -SUBDIR.yes= boot1.chrp ofw uboot +SUBDIR.yes= boot1.chrp ofw .if "${MACHINE_ARCH}" == "powerpc64" -SUBDIR.${MK_FDT}+= kboot +SUBDIR.${MK_FDT}+= uboot kboot .endif .include Index: stand/powerpc/boot1.chrp/boot1.c =================================================================== --- stand/powerpc/boot1.chrp/boot1.c (revision 367806) +++ stand/powerpc/boot1.chrp/boot1.c (working copy) @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -82,11 +83,11 @@ */ typedef uint32_t ofwcell_t; typedef uint32_t u_ofwh_t; -typedef int (*ofwfp_t)(void *); +typedef int (*ofwfp_t)(ofwcell_t *); ofwfp_t ofw; /* the prom Open Firmware entry */ ofwh_t chosenh; -void ofw_init(void *, int, int (*)(void *), char *, int); +void ofw_init(void *, int, ofwfp_t, char *, int); static ofwh_t ofw_finddevice(const char *); static ofwh_t ofw_open(const char *); static int ofw_close(ofwh_t); @@ -101,6 +102,16 @@ ofwh_t bootdevh; ofwh_t stdinh, stdouth; +/* + * Note about the entry point: + * + * For some odd reason, the first page of the load appears to have trouble + * when entering in LE. The first five instructions decode weirdly. + * I suspect it is some cache weirdness between the ELF headers and .text. + * + * Ensure we have a gap between the start of .text and the entry as a + * workaround. + */ __asm(" \n\ .data \n\ .align 4 \n\ @@ -108,6 +119,8 @@ .space 16384 \n\ \n\ .text \n\ + /* SLOF cache hack */ \n\ + .space 4096 \n\ .globl _start \n\ _start: \n\ lis %r1,stack@ha \n\ @@ -117,18 +130,94 @@ b ofw_init \n\ "); +#if BYTE_ORDER == LITTLE_ENDIAN +ofwfp_t realofw; + +/* + * Minimal endianness-swap trampoline for LE. + */ +__attribute__((naked)) int +ofwtramp(void *buf, ofwfp_t cb) +{ +__asm(" \n\ + mflr %r0 \n\ + stw %r0, 4(%r1) \n\ + stwu %r1, -16(%r1) \n\ + stw %r30, 8(%r1) \n\ + /* Save current MSR for restoration post-call. */ \n\ + mfmsr %r30 \n\ + mr %r5, %r30 \n\ + /* Remove LE bit from MSR. */ \n\ + clrrwi %r5, %r5, 1 \n\ + mtsrr0 %r4 \n\ + mtsrr1 %r5 \n\ + bcl 20, 31, .+4 /* LOAD_LR_NIA */ \n\ +1: \n\ + mflr %r4 \n\ + addi %r4, %r4, (2f - 1b) \n\ + mtlr %r4 \n\ + /* Switch to BE and transfer control to OF entry */ \n\ + rfid \n\ +2: \n\ + /* Control is returned here, but in BE. */ \n\ + .long 0x05009f42 /* LOAD_LR_NIA */\n\ + /* 0: */\n\ + .long 0xa603db7f /* mtsrr1 %r30 */\n\ + .long 0xa602c87f /* mflr %r30 */\n\ + .long 0x1400de3b /* addi %r30, %r30, (1f - 0b) */\n\ + .long 0xa603da7f /* mtsrr0 %r30 */\n\ + .long 0x2400004c /* rfid */\n\ + /* 1: */\n\ +1: \n\ + /* Back to normal. Tidy up for return. */ \n\ + lwz %r30, 8(%r1) \n\ + lwz %r0, 20(%r1) \n\ + addi %r1, %r1, 16 \n\ + mtlr %r0 \n\ + blr \n\ +"); +} + +/* + * Little-endian OFW entrypoint replacement. + * + * We are doing all the byteswapping in one place here to save space. + * This means instance handles will be byteswapped as well. + */ +int +call_ofw(ofwcell_t* buf) +{ + int ret, i, ncells; + ncells = 3 + buf[1] + buf[2]; + for (i = 0; i < ncells; i++) + buf[i] = htobe32(buf[i]); + + ret = (ofwtramp(buf, realofw)); + for (i = 0; i < ncells; i++) + buf[i] = be32toh(buf[i]); + return (ret); +} +#endif + void -ofw_init(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl) +ofw_init(void *vpd, int res, ofwfp_t openfirm, char *arg, int argl) { char *av[16]; char *p; int ac; +#if BYTE_ORDER == LITTLE_ENDIAN + realofw = openfirm; + ofw = call_ofw; +#else ofw = openfirm; +#endif chosenh = ofw_finddevice("/chosen"); ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); + stdinh = be32toh(stdinh); ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); + stdouth = be32toh(stdouth); ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); Index: stand/powerpc/ofw/Makefile =================================================================== --- stand/powerpc/ofw/Makefile (revision 367806) +++ stand/powerpc/ofw/Makefile (working copy) @@ -30,6 +30,10 @@ CFLAGS+= -DCAS .endif +.if ${MACHINE_ARCH} == "powerpc64le" +SRCS+= trampolineLE.S +.endif + HELP_FILES= ${FDTSRC}/help.fdt # Always add MI sources @@ -41,8 +45,14 @@ RELOC?= 0x1C00000 CFLAGS+= -DRELOC=${RELOC} -g -LDFLAGS= -nostdlib -static -T ${.CURDIR}/ldscript.powerpc +LDFLAGS= -nostdlib -static +.if ${MACHINE_ARCH} == "powerpc64le" +LDFLAGS+= -T ${.CURDIR}/ldscript.powerpcle +.else +LDFLAGS+= -T ${.CURDIR}/ldscript.powerpc +.endif + # Open Firmware standalone support library LIBOFW= ${BOOTOBJ}/libofw/libofw.a CFLAGS+= -I${BOOTSRC}/libofw Index: stand/powerpc/ofw/ldscript.powerpcle =================================================================== --- stand/powerpc/ofw/ldscript.powerpcle (nonexistent) +++ stand/powerpc/ofw/ldscript.powerpcle (working copy) @@ -0,0 +1,142 @@ +/* $FreeBSD: head/stand/powerpc/ofw/ldscript.powerpc 358304 2020-02-25 00:45:09Z bdragon $ */ + +OUTPUT_FORMAT("elf32-powerpcle-freebsd", "elf32-powerpcle-freebsd", + "elf32-powerpcle-freebsd") +OUTPUT_ARCH(powerpcle:common) +ENTRY(_start) +SEARCH_DIR(/usr/lib); +PROVIDE (__stack = 0); +PHDRS +{ + text PT_LOAD; +} +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0x02c00000 + SIZEOF_HEADERS; + .interp : { *(.interp) } :text + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.text : + { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rela.data : + { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rela.rodata : + { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rela.got : { *(.rela.got) } + .rela.got1 : { *(.rela.got1) } + .rela.got2 : { *(.rela.got2) } + .rela.ctors : { *(.rela.ctors) } + .rela.dtors : { *(.rela.dtors) } + .rela.init : { *(.rela.init) } + .rela.fini : { *(.rela.fini) } + .rela.bss : { *(.rela.bss) } + .rela.plt : { *(.rela.plt) } + .rela.sdata : { *(.rela.sdata) } + .rela.sbss : { *(.rela.sbss) } + .rela.sdata2 : { *(.rela.sdata2) } + .rela.sbss2 : { *(.rela.sbss2) } + .text : + { + *(.text) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } =0 + _etext = .; + PROVIDE (etext = .); + .init : { *(.init) } =0 + .fini : { *(.fini) } =0 + .rodata : { *(.rodata) *(.gnu.linkonce.r*) } + .rodata1 : { *(.rodata1) } + .sdata2 : { *(.sdata2) } + .sbss2 : { *(.sbss2) } + /* Adjust the address for the data segment to the next page up. */ + . = ((. + 0x1000) & ~(0x1000 - 1)); + .data : + { + *(.data) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } + .data1 : { *(.data1) } + .got1 : { *(.got1) } + .dynamic : { *(.dynamic) } + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + get relocated with -mrelocatable. Also put in the .fixup pointers. + The current compiler no longer needs this, but keep it around for 2.7.2 */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } + PROVIDE (__CTOR_LIST__ = .); + .ctors : { *(.ctors) } + PROVIDE (__CTOR_END__ = .); + PROVIDE (__DTOR_LIST__ = .); + .dtors : { *(.dtors) } + PROVIDE (__DTOR_END__ = .); + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } + PROVIDE (_FIXUP_END_ = .); + PROVIDE (_GOT2_END_ = .); + PROVIDE (_GOT_START_ = .); + .got : { *(.got) } + .got.plt : { *(.got.plt) } + PROVIDE (_GOT_END_ = .); + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + .sbss : + { + PROVIDE (__sbss_start = .); + *(.sbss) + *(.scommon) + *(.dynsbss) + PROVIDE (__sbss_end = .); + } + .plt : { *(.plt) } + .bss : + { + PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} + Index: stand/powerpc/ofw/main.c =================================================================== --- stand/powerpc/ofw/main.c (revision 367806) +++ stand/powerpc/ofw/main.c (working copy) @@ -28,11 +28,14 @@ #include __FBSDID("$FreeBSD$"); +#include + #include #include "openfirm.h" #include "libofw.h" #include "bootstrap.h" +#include #include struct arch_switch archsw; /* MI/MD interface boundary */ @@ -77,7 +80,7 @@ memsz = 0; memoryp = OF_instance_to_package(memory); - sz = OF_getprop(memoryp, "reg", ®, sizeof(reg)); + sz = OF_getencprop(memoryp, "reg", ®[0], sizeof(reg)); sz /= sizeof(reg[0]); for (i = 0; i < sz; i += (acells + scells)) { @@ -104,6 +107,26 @@ } #endif +#if BYTE_ORDER == LITTLE_ENDIAN +/* + * In Little-endian, we cannot just branch to the client interface. Since + * the client interface is big endian, we have to rfid to it. + * Likewise, when execution resumes, we are in the wrong endianness so + * we must do a fixup before returning to the caller. + */ +static int (*openfirmware_entry)(void *); +extern int openfirmware_trampoline(void *buf, int(*cb)(void*)); + +/* + * Wrapper to pass the real entry point to our trampoline. + */ +static int +openfirmware_docall(void *buf) +{ + return openfirmware_trampoline(buf, openfirmware_entry); +} +#endif + int main(int (*openfirm)(void *)) { @@ -117,13 +140,21 @@ /* * Initialise the Open Firmware routines by giving them the entry point. */ +#if BYTE_ORDER == LITTLE_ENDIAN + /* + * Use a trampoline entry point for endian fixups. + */ + openfirmware_entry = openfirm; + OF_init(openfirmware_docall); +#else OF_init(openfirm); +#endif root = OF_finddevice("/"); scells = acells = 1; - OF_getprop(root, "#address-cells", &acells, sizeof(acells)); - OF_getprop(root, "#size-cells", &scells, sizeof(scells)); + OF_getencprop(root, "#address-cells", &acells, sizeof(acells)); + OF_getencprop(root, "#size-cells", &scells, sizeof(scells)); /* * Initialise the heap as early as possible. Once this is done, Index: stand/powerpc/ofw/ofwfdt.c =================================================================== --- stand/powerpc/ofw/ofwfdt.c (revision 367806) +++ stand/powerpc/ofw/ofwfdt.c (working copy) @@ -112,7 +112,7 @@ node = OF_finddevice("/rtas"); OF_package_to_path(node, path, sizeof(path)); - OF_getprop(node, "rtas-size", &len, sizeof(len)); + OF_getencprop(node, "rtas-size", &len, sizeof(len)); /* Allocate memory */ rtasmem = OF_claim(0, len, 4096); Index: stand/powerpc/ofw/trampolineLE.S =================================================================== --- stand/powerpc/ofw/trampolineLE.S (nonexistent) +++ stand/powerpc/ofw/trampolineLE.S (working copy) @@ -0,0 +1,70 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Brandon Bergren + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include + +/** + * int openfirmware_trampoline(void *buf, int(*cb)(void*)); + */ +ASENTRY_NOPROF(openfirmware_trampoline) + mflr %r0 + stw %r0, 4(%r1) + stwu %r1, -16(%r1) + stw %r30, 8(%r1) + /* Save current MSR for restoration post-call. */ + mfmsr %r30 + mr %r5, %r30 + /* Remove LE bit from MSR. */ + clrrwi %r5, %r5, 1 + mtsrr0 %r4 + mtsrr1 %r5 + LOAD_LR_NIA +1: + mflr %r4 + addi %r4, %r4, (2f - 1b) + mtlr %r4 + /* Switch to BE and transfer control to OF entry */ + rfid +2: + /* Control is returned here, but in BE. */ + .long 0x05009f42 /* LOAD_LR_NIA */ + /* 0: */ + .long 0xa603db7f /* mtsrr1 %r30 */ + .long 0xa602c87f /* mflr %r30 */ + .long 0x1400de3b /* addi %r30, %r30, (1f - 0b) */ + .long 0xa603da7f /* mtsrr0 %r30 */ + .long 0x2400004c /* rfid */ + /* 1: */ +1: + /* Back to normal. Tidy up for return. */ + lwz %r30, 8(%r1) + lwz %r0, 20(%r1) + addi %r1, %r1, 16 + mtlr %r0 + blr Property changes on: stand/powerpc/ofw/trampolineLE.S ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property