Minor decoder optimizations, kernel fixes, cpu backend fixes
This commit is contained in:
@@ -28,7 +28,11 @@
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
struct X_STRING {
|
||||
unsigned short length;
|
||||
unsigned short pad;
|
||||
uint32_t ptr;
|
||||
};
|
||||
// https://msdn.microsoft.com/en-us/library/ff561778
|
||||
dword_result_t RtlCompareMemory_entry(lpvoid_t source1, lpvoid_t source2,
|
||||
dword_t length) {
|
||||
@@ -142,38 +146,80 @@ dword_result_t RtlLowerChar_entry(dword_t in) {
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlLowerChar, kNone, kImplemented);
|
||||
|
||||
dword_result_t RtlCompareString_entry(lpstring_t string_1, lpstring_t string_2,
|
||||
dword_t case_insensitive) {
|
||||
int ret = case_insensitive ? xe_strcasecmp(string_1, string_2)
|
||||
: std::strcmp(string_1, string_2);
|
||||
|
||||
return ret;
|
||||
static int RtlCompareStringN_impl(uint8_t* string_1, unsigned int string_1_len,
|
||||
uint8_t* string_2, unsigned int string_2_len,
|
||||
int case_insensitive) {
|
||||
if (string_1_len == 0xFFFFFFFF) {
|
||||
uint8_t* string1_strlen_iter = string_1;
|
||||
while (*string1_strlen_iter++)
|
||||
;
|
||||
string_1_len =
|
||||
static_cast<unsigned int>(string1_strlen_iter - string_1 - 1);
|
||||
}
|
||||
if (string_2_len == 0xFFFFFFFF) {
|
||||
uint8_t* string2_strlen_iter = string_2;
|
||||
while (*string2_strlen_iter++)
|
||||
;
|
||||
string_2_len =
|
||||
static_cast<unsigned int>(string2_strlen_iter - string_2 - 1);
|
||||
}
|
||||
uint8_t* string1_end = &string_1[std::min(string_2_len, string_1_len)];
|
||||
if (case_insensitive) {
|
||||
while (string_1 < string1_end) {
|
||||
unsigned c1 = *string_1++;
|
||||
unsigned c2 = *string_2++;
|
||||
if (c1 != c2) {
|
||||
unsigned cu1 = rtl_upper_table[c1];
|
||||
unsigned cu2 = rtl_upper_table[c2];
|
||||
if (cu1 != cu2) {
|
||||
return cu1 - cu2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (string_1 < string1_end) {
|
||||
unsigned c1 = *string_1++;
|
||||
unsigned c2 = *string_2++;
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// why? not sure, but its the original logic
|
||||
return string_1_len - string_2_len;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlCompareString, kNone, kImplemented);
|
||||
|
||||
dword_result_t RtlCompareStringN_entry(lpstring_t string_1,
|
||||
dword_t string_1_len,
|
||||
lpstring_t string_2,
|
||||
dword_t string_2_len,
|
||||
dword_t case_insensitive) {
|
||||
uint32_t len1 = string_1_len;
|
||||
uint32_t len2 = string_2_len;
|
||||
|
||||
if (string_1_len == 0xFFFF) {
|
||||
len1 = uint32_t(std::strlen(string_1));
|
||||
}
|
||||
if (string_2_len == 0xFFFF) {
|
||||
len2 = uint32_t(std::strlen(string_2));
|
||||
}
|
||||
auto len = std::min(string_1_len, string_2_len);
|
||||
|
||||
int ret = case_insensitive ? xe_strncasecmp(string_1, string_2, len)
|
||||
: std::strncmp(string_1, string_2, len);
|
||||
|
||||
return ret;
|
||||
return RtlCompareStringN_impl(
|
||||
reinterpret_cast<uint8_t*>(string_1.host_address()), string_1_len,
|
||||
reinterpret_cast<uint8_t*>(string_2.host_address()), string_2_len,
|
||||
case_insensitive);
|
||||
}
|
||||
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlCompareStringN, kNone, kImplemented);
|
||||
|
||||
dword_result_t RtlCompareString_entry(lpvoid_t string_1, lpvoid_t string_2,
|
||||
dword_t case_insensitive) {
|
||||
X_STRING* xs1 = string_1.as<X_STRING*>();
|
||||
X_STRING* xs2 = string_2.as<X_STRING*>();
|
||||
|
||||
unsigned length_1 = xe::load_and_swap<uint16_t>(&xs1->length);
|
||||
unsigned length_2 = xe::load_and_swap<uint16_t>(&xs2->length);
|
||||
|
||||
uint32_t ptr_1 = xe::load_and_swap<uint32_t>(&xs1->ptr);
|
||||
|
||||
uint32_t ptr_2 = xe::load_and_swap<uint32_t>(&xs2->ptr);
|
||||
|
||||
auto kmem = kernel_memory();
|
||||
|
||||
return RtlCompareStringN_impl(
|
||||
kmem->TranslateVirtual<uint8_t*>(ptr_1), length_1,
|
||||
kmem->TranslateVirtual<uint8_t*>(ptr_2), length_2, case_insensitive);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlCompareString, kNone, kImplemented);
|
||||
// https://msdn.microsoft.com/en-us/library/ff561918
|
||||
void RtlInitAnsiString_entry(pointer_t<X_ANSI_STRING> destination,
|
||||
lpstring_t source) {
|
||||
@@ -188,13 +234,13 @@ void RtlInitAnsiString_entry(pointer_t<X_ANSI_STRING> destination,
|
||||
destination->pointer = source.guest_address();
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlInitAnsiString, kNone, kImplemented);
|
||||
//https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlupcaseunicodechar
|
||||
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlupcaseunicodechar
|
||||
dword_result_t RtlUpcaseUnicodeChar_entry(dword_t SourceCharacter) {
|
||||
return std::use_facet<std::ctype<char16_t>>(std::locale()).toupper(SourceCharacter);
|
||||
return std::use_facet<std::ctype<char16_t>>(std::locale())
|
||||
.toupper(SourceCharacter);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlUpcaseUnicodeChar, kNone, kImplemented);
|
||||
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/ff561899
|
||||
void RtlFreeAnsiString_entry(pointer_t<X_ANSI_STRING> string) {
|
||||
if (string->pointer) {
|
||||
@@ -206,8 +252,8 @@ void RtlFreeAnsiString_entry(pointer_t<X_ANSI_STRING> string) {
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlFreeAnsiString, kNone, kImplemented);
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/ff561934
|
||||
void RtlInitUnicodeString_entry(pointer_t<X_UNICODE_STRING> destination,
|
||||
lpu16string_t source) {
|
||||
pointer_result_t RtlInitUnicodeString_entry(
|
||||
pointer_t<X_UNICODE_STRING> destination, lpu16string_t source) {
|
||||
if (source) {
|
||||
destination->length = (uint16_t)source.value().size() * 2;
|
||||
destination->maximum_length = (uint16_t)(source.value().size() + 1) * 2;
|
||||
@@ -215,6 +261,7 @@ void RtlInitUnicodeString_entry(pointer_t<X_UNICODE_STRING> destination,
|
||||
} else {
|
||||
destination->reset();
|
||||
}
|
||||
return destination.guest_address();
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlInitUnicodeString, kNone, kImplemented);
|
||||
|
||||
@@ -671,6 +718,26 @@ dword_result_t RtlComputeCrc32_entry(dword_t seed, lpvoid_t buffer,
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlComputeCrc32, kNone, kImplemented);
|
||||
|
||||
static void RtlRip_entry(const ppc_context_t& ctx) {
|
||||
uint32_t arg1 = static_cast<uint32_t>(ctx->r[3]);
|
||||
uint32_t arg2 = static_cast<uint32_t>(ctx->r[4]);
|
||||
const char* msg_str1 = "";
|
||||
|
||||
const char* msg_str2 = "";
|
||||
|
||||
if (arg1) {
|
||||
msg_str1 = ctx->TranslateVirtual<const char*>(arg1);
|
||||
}
|
||||
|
||||
if (arg2) {
|
||||
msg_str2 = ctx->TranslateVirtual<const char*>(arg2);
|
||||
}
|
||||
|
||||
XELOGE("RtlRip called, arg1 = {}, arg2 = {}\n", msg_str1, msg_str2);
|
||||
|
||||
//we should break here... not sure what to do exactly
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(RtlRip, kNone, kImportant);
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/atomic.h"
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/logging.h"
|
||||
@@ -913,7 +912,7 @@ dword_result_t NtWaitForMultipleObjectsEx_entry(
|
||||
dword_t count, lpdword_t handles, dword_t wait_type, dword_t wait_mode,
|
||||
dword_t alertable, lpqword_t timeout_ptr) {
|
||||
uint64_t timeout = timeout_ptr ? static_cast<uint64_t>(*timeout_ptr) : 0u;
|
||||
if (!count || count > 64 || wait_type != 1 && wait_type) {
|
||||
if (!count || count > 64 || (wait_type != 1 && wait_type)) {
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
return xeNtWaitForMultipleObjectsEx(count, handles, wait_type, wait_mode,
|
||||
@@ -964,7 +963,7 @@ uint32_t xeKeKfAcquireSpinLock(uint32_t* lock, uint64_t r13 = 1) {
|
||||
PrefetchForCAS(lock);
|
||||
assert_true(*lock != static_cast<uint32_t>(r13));
|
||||
// Lock.
|
||||
while (!xe::atomic_cas(0, static_cast<uint32_t>(r13), lock)) {
|
||||
while (!xe::atomic_cas(0, xe::byte_swap(static_cast<uint32_t>(r13)), lock)) {
|
||||
// Spin!
|
||||
// TODO(benvanik): error on deadlock?
|
||||
xe::threading::MaybeYield();
|
||||
@@ -978,7 +977,7 @@ uint32_t xeKeKfAcquireSpinLock(uint32_t* lock, uint64_t r13 = 1) {
|
||||
}
|
||||
|
||||
dword_result_t KfAcquireSpinLock_entry(lpdword_t lock_ptr,
|
||||
ppc_context_t& ppc_context) {
|
||||
const ppc_context_t& ppc_context) {
|
||||
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
|
||||
return xeKeKfAcquireSpinLock(lock, ppc_context->r[13]);
|
||||
}
|
||||
@@ -997,9 +996,7 @@ void xeKeKfReleaseSpinLock(uint32_t* lock, dword_t old_irql) {
|
||||
}
|
||||
|
||||
void KfReleaseSpinLock_entry(lpdword_t lock_ptr, dword_t old_irql,
|
||||
ppc_context_t& ppc_ctx) {
|
||||
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
|
||||
|
||||
const ppc_context_t& ppc_ctx) {
|
||||
assert_true(*lock_ptr == static_cast<uint32_t>(ppc_ctx->r[13]));
|
||||
|
||||
*lock_ptr = 0;
|
||||
@@ -1014,14 +1011,14 @@ DECLARE_XBOXKRNL_EXPORT2(KfReleaseSpinLock, kThreading, kImplemented,
|
||||
kHighFrequency);
|
||||
// todo: this is not accurate
|
||||
void KeAcquireSpinLockAtRaisedIrql_entry(lpdword_t lock_ptr,
|
||||
ppc_context_t& ppc_ctx) {
|
||||
const ppc_context_t& ppc_ctx) {
|
||||
// Lock.
|
||||
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
|
||||
// must not be our own thread
|
||||
assert_true(*lock_ptr != static_cast<uint32_t>(ppc_ctx->r[13]));
|
||||
|
||||
PrefetchForCAS(lock);
|
||||
while (!xe::atomic_cas(0, static_cast<uint32_t>(ppc_ctx->r[13]), lock)) {
|
||||
while (!xe::atomic_cas(0, xe::byte_swap(static_cast<uint32_t>(ppc_ctx->r[13])), lock)) {
|
||||
#if XE_ARCH_AMD64 == 1
|
||||
// todo: this is just a nop if they don't have SMT, which is not great
|
||||
// either...
|
||||
@@ -1036,12 +1033,12 @@ DECLARE_XBOXKRNL_EXPORT3(KeAcquireSpinLockAtRaisedIrql, kThreading,
|
||||
kImplemented, kBlocking, kHighFrequency);
|
||||
|
||||
dword_result_t KeTryToAcquireSpinLockAtRaisedIrql_entry(
|
||||
lpdword_t lock_ptr, ppc_context_t& ppc_ctx) {
|
||||
lpdword_t lock_ptr, const ppc_context_t& ppc_ctx) {
|
||||
// Lock.
|
||||
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
|
||||
assert_true(*lock_ptr != static_cast<uint32_t>(ppc_ctx->r[13]));
|
||||
PrefetchForCAS(lock);
|
||||
if (!xe::atomic_cas(0, static_cast<uint32_t>(ppc_ctx->r[13]), lock)) {
|
||||
if (!xe::atomic_cas(0, xe::byte_swap(static_cast<uint32_t>(ppc_ctx->r[13])), lock)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -1050,10 +1047,9 @@ DECLARE_XBOXKRNL_EXPORT4(KeTryToAcquireSpinLockAtRaisedIrql, kThreading,
|
||||
kImplemented, kBlocking, kHighFrequency, kSketchy);
|
||||
|
||||
void KeReleaseSpinLockFromRaisedIrql_entry(lpdword_t lock_ptr,
|
||||
ppc_context_t& ppc_ctx) {
|
||||
const ppc_context_t& ppc_ctx) {
|
||||
// Unlock.
|
||||
assert_true(*lock_ptr == static_cast<uint32_t>(ppc_ctx->r[13]));
|
||||
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
|
||||
*lock_ptr = 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT2(KeReleaseSpinLockFromRaisedIrql, kThreading,
|
||||
@@ -1283,7 +1279,8 @@ void ExInitializeReadWriteLock_entry(pointer_t<X_ERWLOCK> lock_ptr) {
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ExInitializeReadWriteLock, kThreading, kImplemented);
|
||||
|
||||
void ExAcquireReadWriteLockExclusive_entry(pointer_t<X_ERWLOCK> lock_ptr, ppc_context_t& ppc_context) {
|
||||
void ExAcquireReadWriteLockExclusive_entry(pointer_t<X_ERWLOCK> lock_ptr,
|
||||
const ppc_context_t& ppc_context) {
|
||||
auto old_irql = xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
|
||||
int32_t lock_count = ++lock_ptr->lock_count;
|
||||
@@ -1301,7 +1298,7 @@ DECLARE_XBOXKRNL_EXPORT2(ExAcquireReadWriteLockExclusive, kThreading,
|
||||
kImplemented, kBlocking);
|
||||
|
||||
dword_result_t ExTryToAcquireReadWriteLockExclusive_entry(
|
||||
pointer_t<X_ERWLOCK> lock_ptr, ppc_context_t& ppc_context) {
|
||||
pointer_t<X_ERWLOCK> lock_ptr, const ppc_context_t& ppc_context) {
|
||||
auto old_irql =
|
||||
xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
|
||||
@@ -1320,7 +1317,7 @@ DECLARE_XBOXKRNL_EXPORT1(ExTryToAcquireReadWriteLockExclusive, kThreading,
|
||||
kImplemented);
|
||||
|
||||
void ExAcquireReadWriteLockShared_entry(pointer_t<X_ERWLOCK> lock_ptr,
|
||||
ppc_context_t& ppc_context) {
|
||||
const ppc_context_t& ppc_context) {
|
||||
auto old_irql = xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
|
||||
int32_t lock_count = ++lock_ptr->lock_count;
|
||||
@@ -1340,7 +1337,7 @@ DECLARE_XBOXKRNL_EXPORT2(ExAcquireReadWriteLockShared, kThreading, kImplemented,
|
||||
kBlocking);
|
||||
|
||||
dword_result_t ExTryToAcquireReadWriteLockShared_entry(
|
||||
pointer_t<X_ERWLOCK> lock_ptr, ppc_context_t& ppc_context) {
|
||||
pointer_t<X_ERWLOCK> lock_ptr, const ppc_context_t& ppc_context) {
|
||||
auto old_irql =
|
||||
xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
|
||||
@@ -1361,7 +1358,7 @@ DECLARE_XBOXKRNL_EXPORT1(ExTryToAcquireReadWriteLockShared, kThreading,
|
||||
kImplemented);
|
||||
|
||||
void ExReleaseReadWriteLock_entry(pointer_t<X_ERWLOCK> lock_ptr,
|
||||
ppc_context_t& ppc_context) {
|
||||
const ppc_context_t& ppc_context) {
|
||||
auto old_irql =
|
||||
xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
|
||||
@@ -1404,7 +1401,7 @@ pointer_result_t InterlockedPushEntrySList_entry(
|
||||
assert_not_null(entry);
|
||||
|
||||
alignas(8) X_SLIST_HEADER old_hdr = *plist_ptr;
|
||||
alignas(8) X_SLIST_HEADER new_hdr = {0};
|
||||
alignas(8) X_SLIST_HEADER new_hdr = {{0}, 0, 0};
|
||||
uint32_t old_head = 0;
|
||||
do {
|
||||
old_hdr = *plist_ptr;
|
||||
@@ -1428,8 +1425,8 @@ pointer_result_t InterlockedPopEntrySList_entry(
|
||||
assert_not_null(plist_ptr);
|
||||
|
||||
uint32_t popped = 0;
|
||||
alignas(8) X_SLIST_HEADER old_hdr = {0};
|
||||
alignas(8) X_SLIST_HEADER new_hdr = {0};
|
||||
alignas(8) X_SLIST_HEADER old_hdr = {{0}, 0, 0};
|
||||
alignas(8) X_SLIST_HEADER new_hdr = {{0}, 0, 0};
|
||||
do {
|
||||
old_hdr = *plist_ptr;
|
||||
auto next = kernel_memory()->TranslateVirtual<X_SINGLE_LIST_ENTRY*>(
|
||||
@@ -1456,7 +1453,7 @@ pointer_result_t InterlockedFlushSList_entry(
|
||||
assert_not_null(plist_ptr);
|
||||
|
||||
alignas(8) X_SLIST_HEADER old_hdr = *plist_ptr;
|
||||
alignas(8) X_SLIST_HEADER new_hdr = {0};
|
||||
alignas(8) X_SLIST_HEADER new_hdr = {{0}, 0, 0};
|
||||
uint32_t first = 0;
|
||||
do {
|
||||
old_hdr = *plist_ptr;
|
||||
|
||||
@@ -433,7 +433,7 @@ void VdSwap_entry(
|
||||
return;
|
||||
}
|
||||
gpu_fetch.base_address = frontbuffer_physical_address >> 12;
|
||||
|
||||
XE_MAYBE_UNUSED
|
||||
auto texture_format = gpu::xenos::TextureFormat(texture_format_ptr.value());
|
||||
auto color_space = *color_space_ptr;
|
||||
assert_true(texture_format == gpu::xenos::TextureFormat::k_8_8_8_8 ||
|
||||
|
||||
Reference in New Issue
Block a user