mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-07 10:14:59 -06:00
Merge remote-tracking branch 'upstream/main' into quasifs
This commit is contained in:
commit
7a59a19bda
@ -228,8 +228,10 @@ find_package(half 1.12.0 MODULE)
|
|||||||
find_package(magic_enum 0.9.7 CONFIG)
|
find_package(magic_enum 0.9.7 CONFIG)
|
||||||
find_package(PNG 1.6 MODULE)
|
find_package(PNG 1.6 MODULE)
|
||||||
find_package(RenderDoc 1.6.0 MODULE)
|
find_package(RenderDoc 1.6.0 MODULE)
|
||||||
find_package(SDL3 3.1.2 CONFIG)
|
|
||||||
find_package(SDL3_mixer 2.8.1 CONFIG)
|
find_package(SDL3_mixer 2.8.1 CONFIG)
|
||||||
|
if (SDL3_mixer_FOUND)
|
||||||
|
find_package(SDL3 3.1.2 CONFIG)
|
||||||
|
endif()
|
||||||
find_package(stb MODULE)
|
find_package(stb MODULE)
|
||||||
find_package(toml11 4.2.0 CONFIG)
|
find_package(toml11 4.2.0 CONFIG)
|
||||||
find_package(tsl-robin-map 1.3.0 CONFIG)
|
find_package(tsl-robin-map 1.3.0 CONFIG)
|
||||||
@ -554,6 +556,8 @@ set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
|
|||||||
src/core/libraries/fiber/fiber_error.h
|
src/core/libraries/fiber/fiber_error.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set_source_files_properties(src/core/libraries/fiber/fiber_context.s PROPERTIES COMPILE_OPTIONS -Wno-unused-command-line-argument)
|
||||||
|
|
||||||
set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
||||||
src/core/libraries/videodec/videodec2_impl.h
|
src/core/libraries/videodec/videodec2_impl.h
|
||||||
src/core/libraries/videodec/videodec2.cpp
|
src/core/libraries/videodec/videodec2.cpp
|
||||||
@ -1141,22 +1145,22 @@ if (APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(shadps4 PRIVATE mincore wepoll)
|
target_link_libraries(shadps4 PRIVATE mincore wepoll wbemuuid)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# MSVC likes putting opinions on what people can use, disable:
|
# MSVC likes putting opinions on what people can use, disable:
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE _SCL_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN)
|
add_compile_definitions(NOMINMAX WIN32_LEAN_AND_MEAN)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# Needed for conflicts with time.h of windows.h
|
# Needed for conflicts with time.h of windows.h
|
||||||
add_definitions(-D_TIMESPEC_DEFINED)
|
add_compile_definitions(_TIMESPEC_DEFINED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Target Windows 10 RS5
|
# Target Windows 10 RS5
|
||||||
add_definitions(-DNTDDI_VERSION=0x0A000006 -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00)
|
add_compile_definitions(NTDDI_VERSION=0x0A000006 _WIN32_WINNT=0x0A00 WINVER=0x0A00)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_link_libraries(shadps4 PRIVATE clang_rt.builtins-x86_64.lib)
|
target_link_libraries(shadps4 PRIVATE clang_rt.builtins-x86_64.lib)
|
||||||
@ -1188,7 +1192,7 @@ if (WIN32)
|
|||||||
target_sources(shadps4 PRIVATE src/shadps4.rc)
|
target_sources(shadps4 PRIVATE src/shadps4.rc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(-DBOOST_ASIO_STANDALONE)
|
add_compile_definitions(BOOST_ASIO_STANDALONE)
|
||||||
|
|
||||||
target_include_directories(shadps4 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(shadps4 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
|||||||
2
externals/CMakeLists.txt
vendored
2
externals/CMakeLists.txt
vendored
@ -152,7 +152,7 @@ endif()
|
|||||||
# sirit
|
# sirit
|
||||||
add_subdirectory(sirit)
|
add_subdirectory(sirit)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_compile_options(sirit PUBLIC "-Wno-error=unused-command-line-argument")
|
target_compile_options(sirit PRIVATE "-Wno-error=unused-command-line-argument")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# half
|
# half
|
||||||
|
|||||||
@ -177,7 +177,7 @@ static ConfigEntry<bool> isFullscreen(false);
|
|||||||
static ConfigEntry<string> fullscreenMode("Windowed");
|
static ConfigEntry<string> fullscreenMode("Windowed");
|
||||||
static ConfigEntry<string> presentMode("Mailbox");
|
static ConfigEntry<string> presentMode("Mailbox");
|
||||||
static ConfigEntry<bool> isHDRAllowed(false);
|
static ConfigEntry<bool> isHDRAllowed(false);
|
||||||
static ConfigEntry<bool> fsrEnabled(true);
|
static ConfigEntry<bool> fsrEnabled(false);
|
||||||
static ConfigEntry<bool> rcasEnabled(true);
|
static ConfigEntry<bool> rcasEnabled(true);
|
||||||
static ConfigEntry<int> rcasAttenuation(250);
|
static ConfigEntry<int> rcasAttenuation(250);
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,7 @@ bool PSF::Open(const std::filesystem::path& filepath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const u64 psfSize = file.GetSize();
|
const u64 psfSize = file.GetSize();
|
||||||
|
ASSERT_MSG(psfSize != 0, "SFO file at {} is empty!", filepath.string());
|
||||||
std::vector<u8> psf(psfSize);
|
std::vector<u8> psf(psfSize);
|
||||||
file.Seek(0);
|
file.Seek(0);
|
||||||
file.Read(psf);
|
file.Read(psf);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "fiber.h"
|
#include "fiber.h"
|
||||||
@ -6,8 +6,8 @@
|
|||||||
#include "common/elf_info.h"
|
#include "common/elf_info.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/libraries/fiber/fiber_error.h"
|
#include "core/libraries/fiber/fiber_error.h"
|
||||||
|
#include "core/libraries/kernel/threads/pthread.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "core/tls.h"
|
|
||||||
|
|
||||||
namespace Libraries::Fiber {
|
namespace Libraries::Fiber {
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ static constexpr u64 kFiberStackSizeCheck = 0xdeadbeefdeadbeef;
|
|||||||
static std::atomic<u32> context_size_check = false;
|
static std::atomic<u32> context_size_check = false;
|
||||||
|
|
||||||
OrbisFiberContext* GetFiberContext() {
|
OrbisFiberContext* GetFiberContext() {
|
||||||
return Core::GetTcbBase()->tcb_fiber;
|
return Libraries::Kernel::g_curthread->tcb->tcb_fiber;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" s32 PS4_SYSV_ABI _sceFiberSetJmp(OrbisFiberContext* ctx) asm("_sceFiberSetJmp");
|
extern "C" s32 PS4_SYSV_ABI _sceFiberSetJmp(OrbisFiberContext* ctx) asm("_sceFiberSetJmp");
|
||||||
@ -269,7 +269,7 @@ s32 PS4_SYSV_ABI sceFiberRunImpl(OrbisFiber* fiber, void* addr_context, u64 size
|
|||||||
return ORBIS_FIBER_ERROR_INVALID;
|
return ORBIS_FIBER_ERROR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Tcb* tcb = Core::GetTcbBase();
|
Core::Tcb* tcb = Libraries::Kernel::g_curthread->tcb;
|
||||||
if (tcb->tcb_fiber) {
|
if (tcb->tcb_fiber) {
|
||||||
return ORBIS_FIBER_ERROR_PERMISSION;
|
return ORBIS_FIBER_ERROR_PERMISSION;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
@ -485,25 +486,41 @@ Common::NativeClock* GetClock() {
|
|||||||
s32 PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time,
|
s32 PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time,
|
||||||
struct OrbisTimesec* st, u64* dst_sec) {
|
struct OrbisTimesec* st, u64* dst_sec) {
|
||||||
LOG_TRACE(Kernel, "Called");
|
LOG_TRACE(Kernel, "Called");
|
||||||
|
#ifdef _WIN32
|
||||||
|
TIME_ZONE_INFORMATION tz{};
|
||||||
|
DWORD res = GetTimeZoneInformation(&tz);
|
||||||
|
*local_time = time - tz.Bias;
|
||||||
|
|
||||||
|
if (st != nullptr) {
|
||||||
|
st->t = time;
|
||||||
|
st->west_sec = -tz.Bias * 60;
|
||||||
|
st->dst_sec = res == TIME_ZONE_ID_DAYLIGHT ? -_dstbias : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst_sec != nullptr) {
|
||||||
|
*dst_sec = res == TIME_ZONE_ID_DAYLIGHT ? -_dstbias : 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// std::chrono::current_zone() not available yet.
|
// std::chrono::current_zone() not available yet.
|
||||||
const auto* time_zone = date::current_zone();
|
const auto* time_zone = date::current_zone();
|
||||||
#else
|
#else
|
||||||
const auto* time_zone = std::chrono::current_zone();
|
const auto* time_zone = std::chrono::current_zone();
|
||||||
#endif
|
#endif // __APPLE__
|
||||||
auto info = time_zone->get_info(std::chrono::system_clock::now());
|
auto info = time_zone->get_info(std::chrono::system_clock::now());
|
||||||
|
|
||||||
*local_time = info.offset.count() + info.save.count() * 60 + time;
|
*local_time = info.offset.count() + info.save.count() * 60 + time;
|
||||||
|
|
||||||
if (st != nullptr) {
|
if (st != nullptr) {
|
||||||
st->t = time;
|
st->t = time;
|
||||||
st->west_sec = info.offset.count() * 60;
|
st->west_sec = info.offset.count();
|
||||||
st->dst_sec = info.save.count() * 60;
|
st->dst_sec = info.save.count() * 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst_sec != nullptr) {
|
if (dst_sec != nullptr) {
|
||||||
*dst_sec = info.save.count() * 60;
|
*dst_sec = info.save.count() * 60;
|
||||||
}
|
}
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
@ -565,4 +582,4 @@ void RegisterTime(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", sceKernelConvertUtcToLocaltime);
|
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", sceKernelConvertUtcToLocaltime);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
|||||||
@ -368,7 +368,7 @@ bool Linker::Resolve(const std::string& name, Loader::SymbolType sym_type, Modul
|
|||||||
void* Linker::TlsGetAddr(u64 module_index, u64 offset) {
|
void* Linker::TlsGetAddr(u64 module_index, u64 offset) {
|
||||||
std::scoped_lock lk{mutex};
|
std::scoped_lock lk{mutex};
|
||||||
|
|
||||||
DtvEntry* dtv_table = GetTcbBase()->tcb_dtv;
|
DtvEntry* dtv_table = Libraries::Kernel::g_curthread->tcb->tcb_dtv;
|
||||||
if (dtv_table[0].counter != dtv_generation_counter) {
|
if (dtv_table[0].counter != dtv_generation_counter) {
|
||||||
// Generation counter changed, a dynamic module was either loaded or unloaded.
|
// Generation counter changed, a dynamic module was either loaded or unloaded.
|
||||||
const u32 old_num_dtvs = dtv_table[1].counter;
|
const u32 old_num_dtvs = dtv_table[1].counter;
|
||||||
@ -381,7 +381,7 @@ void* Linker::TlsGetAddr(u64 module_index, u64 offset) {
|
|||||||
delete[] dtv_table;
|
delete[] dtv_table;
|
||||||
|
|
||||||
// Update TCB pointer.
|
// Update TCB pointer.
|
||||||
GetTcbBase()->tcb_dtv = new_dtv_table;
|
Libraries::Kernel::g_curthread->tcb->tcb_dtv = new_dtv_table;
|
||||||
dtv_table = new_dtv_table;
|
dtv_table = new_dtv_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -596,6 +596,10 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory
|
|||||||
// On real hardware, GPU file mmaps cause a full system crash due to an internal error.
|
// On real hardware, GPU file mmaps cause a full system crash due to an internal error.
|
||||||
ASSERT_MSG(false, "Files cannot be mapped to GPU memory");
|
ASSERT_MSG(false, "Files cannot be mapped to GPU memory");
|
||||||
}
|
}
|
||||||
|
if (True(prot & MemoryProt::CpuExec)) {
|
||||||
|
// On real hardware, execute permissions are silently removed.
|
||||||
|
prot &= ~MemoryProt::CpuExec;
|
||||||
|
}
|
||||||
|
|
||||||
// Add virtual memory area
|
// Add virtual memory area
|
||||||
auto& new_vma = CarveVMA(mapped_addr, size)->second;
|
auto& new_vma = CarveVMA(mapped_addr, size)->second;
|
||||||
@ -802,10 +806,9 @@ s32 MemoryManager::QueryProtection(VAddr addr, void** start, void** end, u32* pr
|
|||||||
s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea& vma_base, u64 size,
|
s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea& vma_base, u64 size,
|
||||||
MemoryProt prot) {
|
MemoryProt prot) {
|
||||||
const auto start_in_vma = addr - vma_base.base;
|
const auto start_in_vma = addr - vma_base.base;
|
||||||
const auto adjusted_size =
|
const auto adjusted_size = std::min<u64>(vma_base.size - start_in_vma, size);
|
||||||
vma_base.size - start_in_vma < size ? vma_base.size - start_in_vma : size;
|
|
||||||
|
|
||||||
if (vma_base.type == VMAType::Free) {
|
if (vma_base.type == VMAType::Free || vma_base.type == VMAType::PoolReserved) {
|
||||||
// On PS4, protecting freed memory does nothing.
|
// On PS4, protecting freed memory does nothing.
|
||||||
return adjusted_size;
|
return adjusted_size;
|
||||||
}
|
}
|
||||||
@ -837,8 +840,9 @@ s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea& vma_base, u64 siz
|
|||||||
perms |= Core::MemoryPermission::ReadWrite;
|
perms |= Core::MemoryPermission::ReadWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vma_base.type == VMAType::Direct || vma_base.type == VMAType::Pooled) {
|
if (vma_base.type == VMAType::Direct || vma_base.type == VMAType::Pooled ||
|
||||||
// On PS4, execute permissions are hidden from direct memory mappings.
|
vma_base.type == VMAType::File) {
|
||||||
|
// On PS4, execute permissions are hidden from direct memory and file mappings.
|
||||||
// Tests show that execute permissions still apply, so handle this after reading perms.
|
// Tests show that execute permissions still apply, so handle this after reading perms.
|
||||||
prot &= ~MemoryProt::CpuExec;
|
prot &= ~MemoryProt::CpuExec;
|
||||||
}
|
}
|
||||||
@ -846,6 +850,12 @@ s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea& vma_base, u64 siz
|
|||||||
// Change protection
|
// Change protection
|
||||||
vma_base.prot = prot;
|
vma_base.prot = prot;
|
||||||
|
|
||||||
|
if (vma_base.type == VMAType::Reserved) {
|
||||||
|
// On PS4, protections change vma_map, but don't apply.
|
||||||
|
// Return early to avoid protecting memory that isn't mapped in address space.
|
||||||
|
return adjusted_size;
|
||||||
|
}
|
||||||
|
|
||||||
impl.Protect(addr, size, perms);
|
impl.Protect(addr, size, perms);
|
||||||
|
|
||||||
return adjusted_size;
|
return adjusted_size;
|
||||||
@ -862,22 +872,20 @@ s32 MemoryManager::Protect(VAddr addr, u64 size, MemoryProt prot) {
|
|||||||
// Ensure the range to modify is valid
|
// Ensure the range to modify is valid
|
||||||
ASSERT_MSG(IsValidMapping(addr, size), "Attempted to access invalid address {:#x}", addr);
|
ASSERT_MSG(IsValidMapping(addr, size), "Attempted to access invalid address {:#x}", addr);
|
||||||
|
|
||||||
// Validate protection flags
|
// Appropriately restrict flags.
|
||||||
constexpr static MemoryProt valid_flags =
|
constexpr static MemoryProt flag_mask =
|
||||||
MemoryProt::NoAccess | MemoryProt::CpuRead | MemoryProt::CpuWrite | MemoryProt::CpuExec |
|
MemoryProt::CpuReadWrite | MemoryProt::CpuExec | MemoryProt::GpuReadWrite;
|
||||||
MemoryProt::GpuRead | MemoryProt::GpuWrite | MemoryProt::GpuReadWrite;
|
MemoryProt valid_flags = prot & flag_mask;
|
||||||
|
|
||||||
MemoryProt invalid_flags = prot & ~valid_flags;
|
|
||||||
if (invalid_flags != MemoryProt::NoAccess) {
|
|
||||||
LOG_ERROR(Kernel_Vmm, "Invalid protection flags");
|
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protect all VMAs between addr and addr + size.
|
// Protect all VMAs between addr and addr + size.
|
||||||
s64 protected_bytes = 0;
|
s64 protected_bytes = 0;
|
||||||
while (protected_bytes < size) {
|
while (protected_bytes < size) {
|
||||||
auto it = FindVMA(addr + protected_bytes);
|
auto it = FindVMA(addr + protected_bytes);
|
||||||
auto& vma_base = it->second;
|
auto& vma_base = it->second;
|
||||||
|
if (vma_base.base > addr + protected_bytes) {
|
||||||
|
// Account for potential gaps in memory map.
|
||||||
|
protected_bytes += vma_base.base - (addr + protected_bytes);
|
||||||
|
}
|
||||||
auto result = ProtectBytes(addr + protected_bytes, vma_base, size - protected_bytes, prot);
|
auto result = ProtectBytes(addr + protected_bytes, vma_base, size - protected_bytes, prot);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
// ProtectBytes returned an error, return it
|
// ProtectBytes returned an error, return it
|
||||||
@ -913,13 +921,21 @@ s32 MemoryManager::VirtualQuery(VAddr addr, s32 flags,
|
|||||||
const auto& vma = it->second;
|
const auto& vma = it->second;
|
||||||
info->start = vma.base;
|
info->start = vma.base;
|
||||||
info->end = vma.base + vma.size;
|
info->end = vma.base + vma.size;
|
||||||
info->offset = vma.type == VMAType::Flexible ? 0 : vma.phys_base;
|
info->offset = 0;
|
||||||
info->protection = static_cast<s32>(vma.prot);
|
info->protection = static_cast<s32>(vma.prot);
|
||||||
info->is_flexible = vma.type == VMAType::Flexible ? 1 : 0;
|
info->is_flexible = vma.type == VMAType::Flexible ? 1 : 0;
|
||||||
info->is_direct = vma.type == VMAType::Direct ? 1 : 0;
|
info->is_direct = vma.type == VMAType::Direct ? 1 : 0;
|
||||||
info->is_stack = vma.type == VMAType::Stack ? 1 : 0;
|
info->is_stack = vma.type == VMAType::Stack ? 1 : 0;
|
||||||
info->is_pooled = vma.type == VMAType::PoolReserved || vma.type == VMAType::Pooled ? 1 : 0;
|
info->is_pooled = vma.type == VMAType::PoolReserved || vma.type == VMAType::Pooled ? 1 : 0;
|
||||||
info->is_committed = vma.IsMapped() ? 1 : 0;
|
info->is_committed = vma.IsMapped() ? 1 : 0;
|
||||||
|
if (vma.type == VMAType::Direct || vma.type == VMAType::Pooled) {
|
||||||
|
// Offset is only assigned for direct and pooled mappings.
|
||||||
|
info->offset = vma.phys_base;
|
||||||
|
}
|
||||||
|
if (vma.type == VMAType::Reserved || vma.type == VMAType::PoolReserved) {
|
||||||
|
// Protection is hidden from reserved mappings.
|
||||||
|
info->protection = 0;
|
||||||
|
}
|
||||||
|
|
||||||
strncpy(info->name, vma.name.data(), ::Libraries::Kernel::ORBIS_KERNEL_MAXIMUM_NAME_LENGTH);
|
strncpy(info->name, vma.name.data(), ::Libraries::Kernel::ORBIS_KERNEL_MAXIMUM_NAME_LENGTH);
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -46,10 +46,6 @@ void SetTcbBase(void* image_address) {
|
|||||||
ASSERT(result != 0);
|
ASSERT(result != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tcb* GetTcbBase() {
|
|
||||||
return reinterpret_cast<Tcb*>(TlsGetValue(GetTcbKey()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
||||||
|
|
||||||
// Apple x86_64
|
// Apple x86_64
|
||||||
@ -149,12 +145,6 @@ void SetTcbBase(void* image_address) {
|
|||||||
"Failed to store thread LDT page pointer: {}", errno);
|
"Failed to store thread LDT page pointer: {}", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tcb* GetTcbBase() {
|
|
||||||
Tcb* tcb;
|
|
||||||
asm volatile("mov %%fs:0x0, %0" : "=r"(tcb));
|
|
||||||
return tcb;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(ARCH_X86_64)
|
#elif defined(ARCH_X86_64)
|
||||||
|
|
||||||
// Other POSIX x86_64
|
// Other POSIX x86_64
|
||||||
@ -164,13 +154,6 @@ void SetTcbBase(void* image_address) {
|
|||||||
ASSERT_MSG(ret == 0, "Failed to set GS base: errno {}", errno);
|
ASSERT_MSG(ret == 0, "Failed to set GS base: errno {}", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tcb* GetTcbBase() {
|
|
||||||
void* tcb = nullptr;
|
|
||||||
const int ret = syscall(SYS_arch_prctl, ARCH_GET_GS, &tcb);
|
|
||||||
ASSERT_MSG(ret == 0, "Failed to get GS base: errno {}", errno);
|
|
||||||
return static_cast<Tcb*>(tcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// POSIX non-x86_64
|
// POSIX non-x86_64
|
||||||
@ -193,10 +176,6 @@ void SetTcbBase(void* image_address) {
|
|||||||
ASSERT(pthread_setspecific(GetTcbKey(), image_address) == 0);
|
ASSERT(pthread_setspecific(GetTcbKey(), image_address) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tcb* GetTcbBase() {
|
|
||||||
return static_cast<Tcb*>(pthread_getspecific(GetTcbKey()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
thread_local std::once_flag init_tls_flag;
|
thread_local std::once_flag init_tls_flag;
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Xbyak {
|
namespace Xbyak {
|
||||||
class CodeGenerator;
|
class CodeGenerator;
|
||||||
@ -36,9 +39,6 @@ u32 GetTcbKey();
|
|||||||
/// Sets the data pointer to the TCB block.
|
/// Sets the data pointer to the TCB block.
|
||||||
void SetTcbBase(void* image_address);
|
void SetTcbBase(void* image_address);
|
||||||
|
|
||||||
/// Retrieves Tcb structure for the calling thread.
|
|
||||||
Tcb* GetTcbBase();
|
|
||||||
|
|
||||||
/// Makes sure TLS is initialized for the thread before entering guest.
|
/// Makes sure TLS is initialized for the thread before entering guest.
|
||||||
void EnsureThreadInitialized();
|
void EnsureThreadInitialized();
|
||||||
|
|
||||||
|
|||||||
@ -1043,20 +1043,25 @@ void Translator::V_CMP_U32(ConditionOp op, bool is_signed, bool set_exec, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Translator::V_CMP_U64(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst) {
|
void Translator::V_CMP_U64(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst) {
|
||||||
const IR::U64 src0{GetSrc64(inst.src[0])};
|
ASSERT(inst.src[1].field == OperandField::ConstZero);
|
||||||
const IR::U64 src1{GetSrc64(inst.src[1])};
|
const IR::U1 src0 = [&] {
|
||||||
|
switch (inst.src[0].field) {
|
||||||
|
case OperandField::ScalarGPR:
|
||||||
|
return ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[0].code));
|
||||||
|
case OperandField::VccLo:
|
||||||
|
return ir.GetVcc();
|
||||||
|
default:
|
||||||
|
UNREACHABLE_MSG("src0 = {}", u32(inst.src[0].field));
|
||||||
|
}
|
||||||
|
}();
|
||||||
const IR::U1 result = [&] {
|
const IR::U1 result = [&] {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case ConditionOp::EQ:
|
case ConditionOp::EQ:
|
||||||
return ir.IEqual(src0, src1);
|
return ir.LogicalNot(src0);
|
||||||
case ConditionOp::LG: // NE
|
case ConditionOp::LG: // NE
|
||||||
return ir.INotEqual(src0, src1);
|
return src0;
|
||||||
case ConditionOp::GT:
|
case ConditionOp::GT:
|
||||||
if (src1.IsImmediate() && src1.U64() == 0) {
|
return ir.GroupAny(ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[0].code)));
|
||||||
ASSERT(inst.src[0].field == OperandField::ScalarGPR);
|
|
||||||
return ir.GroupAny(ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[0].code)));
|
|
||||||
}
|
|
||||||
return ir.IGreaterThan(src0, src1, is_signed);
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE_MSG("Unsupported V_CMP_U64 condition operation: {}", u32(op));
|
UNREACHABLE_MSG("Unsupported V_CMP_U64 condition operation: {}", u32(op));
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user