Code cleanup: moving poly/ into xenia/base/
This commit is contained in:
@@ -9,12 +9,12 @@
|
||||
|
||||
#include "xenia/apu/audio_system.h"
|
||||
|
||||
#include "poly/math.h"
|
||||
#include "xenia/apu/audio_driver.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/cpu/thread_state.h"
|
||||
#include "xenia/logging.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
// As with normal Microsoft, there are like twelve different ways to access
|
||||
@@ -59,13 +59,13 @@ AudioSystem::AudioSystem(Emulator* emulator)
|
||||
for (size_t i = 0; i < maximum_client_count_; ++i) {
|
||||
unused_clients_.push(i);
|
||||
}
|
||||
for (size_t i = 0; i < poly::countof(client_wait_handles_); ++i) {
|
||||
for (size_t i = 0; i < xe::countof(client_wait_handles_); ++i) {
|
||||
client_wait_handles_[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
AudioSystem::~AudioSystem() {
|
||||
for (size_t i = 0; i < poly::countof(client_wait_handles_); ++i) {
|
||||
for (size_t i = 0; i < xe::countof(client_wait_handles_); ++i) {
|
||||
CloseHandle(client_wait_handles_[i]);
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@ X_STATUS AudioSystem::Setup() {
|
||||
}
|
||||
|
||||
void AudioSystem::ThreadStart() {
|
||||
poly::threading::set_name("Audio Worker");
|
||||
xe::threading::set_name("Audio Worker");
|
||||
xe::Profiler::ThreadEnter("Audio Worker");
|
||||
|
||||
// Initialize driver and ringbuffer.
|
||||
@@ -118,7 +118,7 @@ void AudioSystem::ThreadStart() {
|
||||
// Main run loop.
|
||||
while (running_) {
|
||||
auto result =
|
||||
WaitForMultipleObjectsEx(DWORD(poly::countof(client_wait_handles_)),
|
||||
WaitForMultipleObjectsEx(DWORD(xe::countof(client_wait_handles_)),
|
||||
client_wait_handles_, FALSE, INFINITE, FALSE);
|
||||
if (result == WAIT_FAILED ||
|
||||
result == WAIT_OBJECT_0 + maximum_client_count_) {
|
||||
@@ -137,7 +137,7 @@ void AudioSystem::ThreadStart() {
|
||||
if (client_callback) {
|
||||
uint64_t args[] = {client_callback_arg};
|
||||
processor->Execute(thread_state_, client_callback, args,
|
||||
poly::countof(args));
|
||||
xe::countof(args));
|
||||
}
|
||||
pumped++;
|
||||
index++;
|
||||
@@ -219,7 +219,7 @@ X_STATUS AudioSystem::RegisterClient(uint32_t callback, uint32_t callback_arg,
|
||||
unused_clients_.pop();
|
||||
|
||||
uint32_t ptr = memory()->SystemHeapAlloc(0x4);
|
||||
poly::store_and_swap<uint32_t>(memory()->TranslateVirtual(ptr), callback_arg);
|
||||
xe::store_and_swap<uint32_t>(memory()->TranslateVirtual(ptr), callback_arg);
|
||||
|
||||
clients_[index] = {driver, callback, callback_arg, ptr};
|
||||
|
||||
@@ -276,13 +276,13 @@ uint64_t AudioSystem::ReadRegister(uint64_t addr) {
|
||||
value = registers_.current_context;
|
||||
}
|
||||
|
||||
value = poly::byte_swap(value);
|
||||
value = xe::byte_swap(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
void AudioSystem::WriteRegister(uint64_t addr, uint64_t value) {
|
||||
uint32_t r = addr & 0xFFFF;
|
||||
value = poly::byte_swap(uint32_t(value));
|
||||
value = xe::byte_swap(uint32_t(value));
|
||||
XELOGAPU("WriteRegister(%.4X, %.8X)", r, value);
|
||||
// 1804h is written to with 0x02000000 and 0x03000000 around a lock operation
|
||||
|
||||
@@ -303,15 +303,15 @@ void AudioSystem::WriteRegister(uint64_t addr, uint64_t value) {
|
||||
uint32_t guest_ptr =
|
||||
registers_.xma_context_array_ptr + context_id * kXmaContextSize;
|
||||
auto context_ptr = memory()->TranslateVirtual(guest_ptr);
|
||||
uint32_t dword0 = poly::load_and_swap<uint32_t>(context_ptr + 0);
|
||||
uint32_t dword0 = xe::load_and_swap<uint32_t>(context_ptr + 0);
|
||||
bool has_valid_input = (dword0 & 0x00300000) != 0;
|
||||
if (has_valid_input) {
|
||||
dword0 = dword0 & ~0x00300000;
|
||||
poly::store_and_swap<uint32_t>(context_ptr + 0, dword0);
|
||||
xe::store_and_swap<uint32_t>(context_ptr + 0, dword0);
|
||||
// Set output buffer to invalid.
|
||||
uint32_t dword1 = poly::load_and_swap<uint32_t>(context_ptr + 4);
|
||||
uint32_t dword1 = xe::load_and_swap<uint32_t>(context_ptr + 4);
|
||||
dword1 = dword1 & ~0x80000000;
|
||||
poly::store_and_swap<uint32_t>(context_ptr + 4, dword1);
|
||||
xe::store_and_swap<uint32_t>(context_ptr + 4, dword1);
|
||||
}
|
||||
}
|
||||
value >>= 1;
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
#include "xenia/apu/xaudio2/xaudio2_audio_driver.h"
|
||||
|
||||
#include "xenia/apu/apu-private.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/logging.h"
|
||||
|
||||
namespace xe {
|
||||
namespace apu {
|
||||
@@ -131,7 +131,7 @@ void XAudio2AudioDriver::SubmitFrame(uint32_t frame_ptr) {
|
||||
for (int index = 0, o = 0; index < channel_samples_; ++index) {
|
||||
for (int channel = 0, table = 0; channel < interleave_channels;
|
||||
++channel, table += channel_samples_) {
|
||||
output_frame[o++] = poly::byte_swap(input_frame[table + index]);
|
||||
output_frame[o++] = xe::byte_swap(input_frame[table + index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
src/xenia/base/README.md
Normal file
25
src/xenia/base/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
A lightweight cross-platform/compiler compatibility library.
|
||||
|
||||
This library presupposes C++11/14 support. As more compilers get C++14 it will
|
||||
assume that.
|
||||
|
||||
Other parts of the project use this to avoid creating spaghetti linkage. Code
|
||||
specific to the emulator should be kept out, as not all of the projects that
|
||||
depend on this need it.
|
||||
|
||||
Where possible, C++11/14 STL should be used instead of adding any code in here,
|
||||
and the code should be kept as small as possible (by reusing STL/etc). Third
|
||||
party dependencies should be kept to a minimum.
|
||||
|
||||
Target compilers:
|
||||
* MSVC++ 2013+
|
||||
* Clang 3.4+
|
||||
* GCC 4.8+.
|
||||
|
||||
Target platforms:
|
||||
* Windows 8+ (`_win.cc` suffix)
|
||||
* Mac OSX 10.9+ (`_mac.cc` suffix, falling back to `_posix.cc`)
|
||||
* Linux ? (`_posix.cc` suffix)
|
||||
|
||||
Avoid the use of platform-specific #ifdefs and instead try to put all
|
||||
platform-specific code in the appropriately suffixed cc files.
|
||||
103
src/xenia/base/arena.cc
Normal file
103
src/xenia/base/arena.cc
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/arena.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
Arena::Arena(size_t chunk_size)
|
||||
: chunk_size_(chunk_size), head_chunk_(nullptr), active_chunk_(nullptr) {}
|
||||
|
||||
Arena::~Arena() {
|
||||
Reset();
|
||||
Chunk* chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
Chunk* next = chunk->next;
|
||||
delete chunk;
|
||||
chunk = next;
|
||||
}
|
||||
head_chunk_ = nullptr;
|
||||
}
|
||||
|
||||
void Arena::Reset() {
|
||||
active_chunk_ = head_chunk_;
|
||||
if (active_chunk_) {
|
||||
active_chunk_->offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Arena::DebugFill() {
|
||||
auto chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
std::memset(chunk->buffer, 0xCD, chunk->capacity);
|
||||
chunk = chunk->next;
|
||||
}
|
||||
}
|
||||
|
||||
void* Arena::Alloc(size_t size) {
|
||||
if (active_chunk_) {
|
||||
if (active_chunk_->capacity - active_chunk_->offset < size + 4096) {
|
||||
Chunk* next = active_chunk_->next;
|
||||
if (!next) {
|
||||
assert_true(size < chunk_size_, "need to support larger chunks");
|
||||
next = new Chunk(chunk_size_);
|
||||
active_chunk_->next = next;
|
||||
}
|
||||
next->offset = 0;
|
||||
active_chunk_ = next;
|
||||
}
|
||||
} else {
|
||||
head_chunk_ = active_chunk_ = new Chunk(chunk_size_);
|
||||
}
|
||||
|
||||
uint8_t* p = active_chunk_->buffer + active_chunk_->offset;
|
||||
active_chunk_->offset += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
void* Arena::CloneContents() {
|
||||
size_t total_length = 0;
|
||||
Chunk* chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
total_length += chunk->offset;
|
||||
if (chunk == active_chunk_) {
|
||||
break;
|
||||
}
|
||||
chunk = chunk->next;
|
||||
}
|
||||
void* result = malloc(total_length);
|
||||
uint8_t* p = (uint8_t*)result;
|
||||
chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
std::memcpy(p, chunk->buffer, chunk->offset);
|
||||
p += chunk->offset;
|
||||
if (chunk == active_chunk_) {
|
||||
break;
|
||||
}
|
||||
chunk = chunk->next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Arena::Chunk::Chunk(size_t chunk_size)
|
||||
: next(nullptr), capacity(chunk_size), buffer(0), offset(0) {
|
||||
buffer = reinterpret_cast<uint8_t*>(malloc(capacity));
|
||||
}
|
||||
|
||||
Arena::Chunk::~Chunk() {
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
55
src/xenia/base/arena.h
Normal file
55
src/xenia/base/arena.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_ARENA_H_
|
||||
#define XENIA_BASE_ARENA_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace xe {
|
||||
|
||||
class Arena {
|
||||
public:
|
||||
Arena(size_t chunk_size = 4 * 1024 * 1024);
|
||||
~Arena();
|
||||
|
||||
void Reset();
|
||||
void DebugFill();
|
||||
|
||||
void* Alloc(size_t size);
|
||||
template <typename T>
|
||||
T* Alloc() {
|
||||
return reinterpret_cast<T*>(Alloc(sizeof(T)));
|
||||
}
|
||||
|
||||
void* CloneContents();
|
||||
|
||||
private:
|
||||
class Chunk {
|
||||
public:
|
||||
Chunk(size_t chunk_size);
|
||||
~Chunk();
|
||||
|
||||
Chunk* next;
|
||||
|
||||
size_t capacity;
|
||||
uint8_t* buffer;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
private:
|
||||
size_t chunk_size_;
|
||||
Chunk* head_chunk_;
|
||||
Chunk* active_chunk_;
|
||||
};
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_ARENA_H_
|
||||
77
src/xenia/base/assert.h
Normal file
77
src/xenia/base/assert.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_ASSERT_H_
|
||||
#define XENIA_BASE_ASSERT_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
#define static_assert_size(type, size) \
|
||||
static_assert(sizeof(type) == size, \
|
||||
"bad definition for " #type ": must be " #size " bytes")
|
||||
|
||||
// We rely on assert being compiled out in NDEBUG.
|
||||
#define xenia_assert assert
|
||||
|
||||
#define __XENIA_EXPAND(x) x
|
||||
#define __XENIA_ARGC(...) \
|
||||
__XENIA_EXPAND(__XENIA_ARGC_IMPL(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, \
|
||||
7, 6, 5, 4, 3, 2, 1, 0))
|
||||
#define __XENIA_ARGC_IMPL(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
|
||||
x13, x14, x15, N, ...) \
|
||||
N
|
||||
#define __XENIA_MACRO_DISPATCH(func, ...) \
|
||||
__XENIA_MACRO_DISPATCH_(func, __XENIA_ARGC(__VA_ARGS__))
|
||||
#define __XENIA_MACRO_DISPATCH_(func, nargs) \
|
||||
__XENIA_MACRO_DISPATCH__(func, nargs)
|
||||
#define __XENIA_MACRO_DISPATCH__(func, nargs) func##nargs
|
||||
|
||||
#define assert_always(...) xenia_assert(false)
|
||||
|
||||
#define assert_true(...) \
|
||||
__XENIA_MACRO_DISPATCH(assert_true, __VA_ARGS__)(__VA_ARGS__)
|
||||
#define assert_true1(expr) xenia_assert(expr)
|
||||
#define assert_true2(expr, message) xenia_assert((expr) || !message)
|
||||
|
||||
#define assert_false(...) \
|
||||
__XENIA_MACRO_DISPATCH(assert_false, __VA_ARGS__)(__VA_ARGS__)
|
||||
#define assert_false1(expr) xenia_assert(!(expr))
|
||||
#define assert_false2(expr, message) xenia_assert(!(expr) || !message)
|
||||
|
||||
#define assert_zero(...) \
|
||||
__XENIA_MACRO_DISPATCH(assert_zero, __VA_ARGS__)(__VA_ARGS__)
|
||||
#define assert_zero1(expr) xenia_assert((expr) == 0)
|
||||
#define assert_zero2(expr, message) xenia_assert((expr) == 0 || !message)
|
||||
|
||||
#define assert_not_zero(...) \
|
||||
__XENIA_MACRO_DISPATCH(assert_not_zero, __VA_ARGS__)(__VA_ARGS__)
|
||||
#define assert_not_zero1(expr) xenia_assert((expr) != 0)
|
||||
#define assert_not_zero2(expr, message) xenia_assert((expr) != 0 || !message)
|
||||
|
||||
#define assert_null(...) \
|
||||
__XENIA_MACRO_DISPATCH(assert_null, __VA_ARGS__)(__VA_ARGS__)
|
||||
#define assert_null1(expr) xenia_assert((expr) == nullptr)
|
||||
#define assert_null2(expr, message) xenia_assert((expr) == nullptr || !message)
|
||||
|
||||
#define assert_not_null(...) \
|
||||
__XENIA_MACRO_DISPATCH(assert_not_null, __VA_ARGS__)(__VA_ARGS__)
|
||||
#define assert_not_null1(expr) xenia_assert((expr) != nullptr)
|
||||
#define assert_not_null2(expr, message) \
|
||||
xenia_assert((expr) != nullptr || !message)
|
||||
|
||||
#define assert_unhandled_case(variable) \
|
||||
assert_always("unhandled switch(" #variable ") case")
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_ASSERT_H_
|
||||
184
src/xenia/base/atomic.h
Normal file
184
src/xenia/base/atomic.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_ATOMIC_H_
|
||||
#define XENIA_BASE_ATOMIC_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
#if XE_PLATFORM_MAC
|
||||
#include <libkern/OSAtomic.h>
|
||||
#endif // XE_PLATFORM_MAC
|
||||
|
||||
namespace xe {
|
||||
|
||||
// These functions are modeled off of the Apple OSAtomic routines
|
||||
// http://developer.apple.com/library/mac/#documentation/DriversKernelHardware/Reference/libkern_ref/OSAtomic_h/
|
||||
|
||||
#if XE_PLATFORM_MAC
|
||||
|
||||
inline int32_t atomic_inc(volatile int32_t* value) {
|
||||
return OSAtomicIncrement32Barrier(reinterpret_cast<volatile int32_t*>(value));
|
||||
}
|
||||
inline int32_t atomic_dec(volatile int32_t* value) {
|
||||
return OSAtomicDecrement32Barrier(reinterpret_cast<volatile int32_t*>(value));
|
||||
}
|
||||
|
||||
inline int32_t atomic_exchange(int32_t new_value, volatile int32_t* value) {
|
||||
return OSAtomicCompareAndSwap32Barrier(*value, new_value, value);
|
||||
}
|
||||
inline int64_t atomic_exchange(int64_t new_value, volatile int64_t* value) {
|
||||
return OSAtomicCompareAndSwap64Barrier(*value, new_value, value);
|
||||
}
|
||||
|
||||
inline int32_t atomic_exchange_add(int32_t amount, volatile int32_t* value) {
|
||||
return OSAtomicAdd32Barrier(amount, value) - amount;
|
||||
}
|
||||
inline int64_t atomic_exchange_add(int64_t amount, volatile int64_t* value) {
|
||||
return OSAtomicAdd64Barrier(amount, value) - amount;
|
||||
}
|
||||
|
||||
inline bool atomic_cas(int32_t old_value, int32_t new_value,
|
||||
volatile int32_t* value) {
|
||||
return OSAtomicCompareAndSwap32Barrier(
|
||||
old_value, new_value, reinterpret_cast<volatile int32_t*>(value));
|
||||
}
|
||||
inline bool atomic_cas(int64_t old_value, int64_t new_value,
|
||||
volatile int64_t* value) {
|
||||
return OSAtomicCompareAndSwap64Barrier(
|
||||
old_value, new_value, reinterpret_cast<volatile int64_t*>(value));
|
||||
}
|
||||
|
||||
#elif XE_PLATFORM_WIN32
|
||||
|
||||
inline int32_t atomic_inc(volatile int32_t* value) {
|
||||
return InterlockedIncrement(reinterpret_cast<volatile LONG*>(value));
|
||||
}
|
||||
inline int32_t atomic_dec(volatile int32_t* value) {
|
||||
return InterlockedDecrement(reinterpret_cast<volatile LONG*>(value));
|
||||
}
|
||||
|
||||
inline int32_t atomic_exchange(int32_t new_value, volatile int32_t* value) {
|
||||
return InterlockedExchange(reinterpret_cast<volatile LONG*>(value),
|
||||
new_value);
|
||||
}
|
||||
inline int64_t atomic_exchange(int64_t new_value, volatile int64_t* value) {
|
||||
return InterlockedExchange64(reinterpret_cast<volatile LONGLONG*>(value),
|
||||
new_value);
|
||||
}
|
||||
|
||||
inline int32_t atomic_exchange_add(int32_t amount, volatile int32_t* value) {
|
||||
return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(value),
|
||||
amount);
|
||||
}
|
||||
inline int64_t atomic_exchange_add(int64_t amount, volatile int64_t* value) {
|
||||
return InterlockedExchangeAdd64(reinterpret_cast<volatile LONGLONG*>(value),
|
||||
amount);
|
||||
}
|
||||
|
||||
inline bool atomic_cas(int32_t old_value, int32_t new_value,
|
||||
volatile int32_t* value) {
|
||||
return InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(value),
|
||||
new_value, old_value) == old_value;
|
||||
}
|
||||
inline bool atomic_cas(int64_t old_value, int64_t new_value,
|
||||
volatile int64_t* value) {
|
||||
return InterlockedCompareExchange64(reinterpret_cast<volatile LONG64*>(value),
|
||||
new_value, old_value) == old_value;
|
||||
}
|
||||
|
||||
#elif XE_PLATFORM_LINUX
|
||||
|
||||
inline int32_t atomic_inc(volatile int32_t* value) {
|
||||
return __sync_add_and_fetch(value, 1);
|
||||
}
|
||||
inline int32_t atomic_dec(volatile int32_t* value) {
|
||||
return __sync_sub_and_fetch(value, 1);
|
||||
}
|
||||
|
||||
inline int32_t atomic_exchange(int32_t new_value, volatile int32_t* value) {
|
||||
return __sync_val_compare_and_swap(*value, value, new_value);
|
||||
}
|
||||
inline int64_t atomic_exchange(int64_t new_value, volatile int64_t* value) {
|
||||
return __sync_val_compare_and_swap(*value, value, new_value);
|
||||
}
|
||||
|
||||
inline int32_t atomic_exchange_add(int32_t amount, volatile int32_t* value) {
|
||||
return __sync_fetch_and_add(amount, value);
|
||||
}
|
||||
inline int64_t atomic_exchange_add(int64_t amount, volatile int64_t* value) {
|
||||
return __sync_fetch_and_add(amount, value);
|
||||
}
|
||||
|
||||
inline bool atomic_cas(int32_t old_value, int32_t new_value,
|
||||
volatile int32_t* value) {
|
||||
return __sync_bool_compare_and_swap(
|
||||
reinterpret_cast<volatile int32_t*>(value), old_value, new_value);
|
||||
}
|
||||
inline bool atomic_cas(int64_t old_value, int64_t new_value,
|
||||
volatile int64_t* value) {
|
||||
return __sync_bool_compare_and_swap(
|
||||
reinterpret_cast<volatile int64_t*>(value), old_value, new_value);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error No atomic primitives defined for this platform/cpu combination.
|
||||
|
||||
#endif // OSX
|
||||
|
||||
inline uint32_t atomic_inc(volatile uint32_t* value) {
|
||||
return static_cast<uint32_t>(
|
||||
atomic_inc(reinterpret_cast<volatile int32_t*>(value)));
|
||||
}
|
||||
inline uint32_t atomic_dec(volatile uint32_t* value) {
|
||||
return static_cast<uint32_t>(
|
||||
atomic_dec(reinterpret_cast<volatile int32_t*>(value)));
|
||||
}
|
||||
|
||||
inline uint32_t atomic_exchange(uint32_t new_value, volatile uint32_t* value) {
|
||||
return static_cast<uint32_t>(
|
||||
atomic_exchange(static_cast<int32_t>(new_value),
|
||||
reinterpret_cast<volatile int32_t*>(value)));
|
||||
}
|
||||
inline uint64_t atomic_exchange(uint64_t new_value, volatile uint64_t* value) {
|
||||
return static_cast<uint64_t>(
|
||||
atomic_exchange(static_cast<int64_t>(new_value),
|
||||
reinterpret_cast<volatile int64_t*>(value)));
|
||||
}
|
||||
|
||||
inline uint32_t atomic_exchange_add(uint32_t amount, volatile uint32_t* value) {
|
||||
return static_cast<uint32_t>(
|
||||
atomic_exchange_add(static_cast<int32_t>(amount),
|
||||
reinterpret_cast<volatile int32_t*>(value)));
|
||||
}
|
||||
inline uint64_t atomic_exchange_add(uint64_t amount, volatile uint64_t* value) {
|
||||
return static_cast<uint64_t>(
|
||||
atomic_exchange_add(static_cast<int64_t>(amount),
|
||||
reinterpret_cast<volatile int64_t*>(value)));
|
||||
}
|
||||
|
||||
inline bool atomic_cas(uint32_t old_value, uint32_t new_value,
|
||||
volatile uint32_t* value) {
|
||||
return atomic_cas(static_cast<int32_t>(old_value),
|
||||
static_cast<int32_t>(new_value),
|
||||
reinterpret_cast<volatile int32_t*>(value));
|
||||
}
|
||||
inline bool atomic_cas(uint64_t old_value, uint64_t new_value,
|
||||
volatile uint64_t* value) {
|
||||
return atomic_cas(static_cast<int64_t>(old_value),
|
||||
static_cast<int64_t>(new_value),
|
||||
reinterpret_cast<volatile int64_t*>(value));
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_ATOMIC_H_
|
||||
83
src/xenia/base/byte_order.h
Normal file
83
src/xenia/base/byte_order.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_BYTE_ORDER_H_
|
||||
#define XENIA_BASE_BYTE_ORDER_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
#if XE_PLATFORM_MAC
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#endif // XE_PLATFORM_MAC
|
||||
|
||||
namespace xe {
|
||||
|
||||
#if XE_COMPILER_MSVC
|
||||
#define XENIA_BASE_BYTE_SWAP_16 _byteswap_ushort
|
||||
#define XENIA_BASE_BYTE_SWAP_32 _byteswap_ulong
|
||||
#define XENIA_BASE_BYTE_SWAP_64 _byteswap_uint64
|
||||
#elif XE_PLATFORM_MAC
|
||||
#define XENIA_BASE_BYTE_SWAP_16 OSSwapInt16
|
||||
#define XENIA_BASE_BYTE_SWAP_32 OSSwapInt32
|
||||
#define XENIA_BASE_BYTE_SWAP_64 OSSwapInt64
|
||||
#else
|
||||
#define XENIA_BASE_BYTE_SWAP_16 __bswap_16
|
||||
#define XENIA_BASE_BYTE_SWAP_32 __bswap_32
|
||||
#define XENIA_BASE_BYTE_SWAP_64 __bswap_64
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
inline int8_t byte_swap(int8_t value) { return value; }
|
||||
inline uint8_t byte_swap(uint8_t value) { return value; }
|
||||
inline int16_t byte_swap(int16_t value) {
|
||||
return static_cast<int16_t>(
|
||||
XENIA_BASE_BYTE_SWAP_16(static_cast<int16_t>(value)));
|
||||
}
|
||||
inline uint16_t byte_swap(uint16_t value) {
|
||||
return XENIA_BASE_BYTE_SWAP_16(value);
|
||||
}
|
||||
inline uint16_t byte_swap(wchar_t value) {
|
||||
return static_cast<wchar_t>(XENIA_BASE_BYTE_SWAP_16(value));
|
||||
}
|
||||
inline int32_t byte_swap(int32_t value) {
|
||||
return static_cast<int32_t>(
|
||||
XENIA_BASE_BYTE_SWAP_32(static_cast<int32_t>(value)));
|
||||
}
|
||||
inline uint32_t byte_swap(uint32_t value) {
|
||||
return XENIA_BASE_BYTE_SWAP_32(value);
|
||||
}
|
||||
inline int64_t byte_swap(int64_t value) {
|
||||
return static_cast<int64_t>(
|
||||
XENIA_BASE_BYTE_SWAP_64(static_cast<int64_t>(value)));
|
||||
}
|
||||
inline uint64_t byte_swap(uint64_t value) {
|
||||
return XENIA_BASE_BYTE_SWAP_64(value);
|
||||
}
|
||||
inline float byte_swap(float value) {
|
||||
uint32_t temp = byte_swap(*reinterpret_cast<uint32_t *>(&value));
|
||||
return *reinterpret_cast<float *>(&temp);
|
||||
}
|
||||
inline double byte_swap(double value) {
|
||||
uint64_t temp = byte_swap(*reinterpret_cast<uint64_t *>(&value));
|
||||
return *reinterpret_cast<double *>(&temp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct be {
|
||||
be() = default;
|
||||
be(const T &src) : value(xe::byte_swap(src)) {}
|
||||
be(const be &other) { value = other.value; }
|
||||
operator T() const { return xe::byte_swap(value); }
|
||||
T value;
|
||||
};
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_BYTE_ORDER_H_
|
||||
51
src/xenia/base/cxx_compat.h
Normal file
51
src/xenia/base/cxx_compat.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_CXX_COMPAT_H_
|
||||
#define XENIA_BASE_CXX_COMPAT_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
// C++11 thread local storage.
|
||||
// http://en.cppreference.com/w/cpp/language/storage_duration
|
||||
#if XE_COMPILER_MSVC
|
||||
// VC++2014 may have this.
|
||||
#define _ALLOW_KEYWORD_MACROS 1
|
||||
#define thread_local __declspec(thread)
|
||||
#elif XE_PLATFORM_MAC
|
||||
// Clang supports it on OSX but the runtime doesn't.
|
||||
#define thread_local __thread
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
// C++11 alignas keyword.
|
||||
// This will hopefully be coming soon, as most of the alignment spec is in the
|
||||
// latest CTP.
|
||||
#if XE_COMPILER_MSVC
|
||||
#define alignas(N) __declspec(align(N))
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
#if !XE_COMPILER_MSVC
|
||||
// C++1y make_unique.
|
||||
// http://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/
|
||||
// This is present in clang with -std=c++1y, but not otherwise.
|
||||
#if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 4)
|
||||
namespace std {
|
||||
template <typename T, typename... Args>
|
||||
unique_ptr<T> make_unique(Args&&... args) {
|
||||
return unique_ptr<T>(new T(forward<Args>(args)...));
|
||||
}
|
||||
} // namespace std
|
||||
#endif // clang < 3.4
|
||||
#endif // !XE_COMPILER_MSVC
|
||||
|
||||
namespace xe {} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_CXX_COMPAT_H_
|
||||
31
src/xenia/base/debugging.h
Normal file
31
src/xenia/base/debugging.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_DEBUGGING_H_
|
||||
#define XENIA_BASE_DEBUGGING_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xe {
|
||||
namespace debugging {
|
||||
|
||||
// Returns true if a debugger is attached to this process.
|
||||
// The state may change at any time (attach after launch, etc), so do not
|
||||
// cache this value. Determining if the debugger is attached is expensive,
|
||||
// though, so avoid calling it frequently.
|
||||
bool IsDebuggerAttached();
|
||||
|
||||
// Breaks into the debugger if it is attached.
|
||||
// If no debugger is present, a signal will be raised.
|
||||
void Break();
|
||||
|
||||
} // namespace debugging
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_DEBUGGING_H_
|
||||
35
src/xenia/base/debugging_mac.cc
Normal file
35
src/xenia/base/debugging_mac.cc
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/debugging.h"
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace xe {
|
||||
namespace debugging {
|
||||
|
||||
bool IsDebuggerAttached() {
|
||||
// https://developer.apple.com/library/mac/qa/qa1361/_index.html
|
||||
kinfo_proc info;
|
||||
info.kp_proc.p_flag = 0;
|
||||
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};
|
||||
size_t size = sizeof(info);
|
||||
sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0);
|
||||
return (info.kp_proc.p_flag & P_TRACED) != 0;
|
||||
}
|
||||
|
||||
// TODO(benvanik): find a more reliable way.
|
||||
void Break() {
|
||||
// __asm__("int $3");
|
||||
__builtin_debugtrap();
|
||||
}
|
||||
|
||||
} // namespace debugging
|
||||
} // namespace xe
|
||||
22
src/xenia/base/debugging_win.cc
Normal file
22
src/xenia/base/debugging_win.cc
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/debugging.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace xe {
|
||||
namespace debugging {
|
||||
|
||||
bool IsDebuggerAttached() { return IsDebuggerPresent() ? true : false; }
|
||||
|
||||
void Break() { __debugbreak(); }
|
||||
|
||||
} // namespace debugging
|
||||
} // namespace xe
|
||||
50
src/xenia/base/delegate.h
Normal file
50
src/xenia/base/delegate.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_DELEGATE_H_
|
||||
#define XENIA_BASE_DELEGATE_H_
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace xe {
|
||||
|
||||
// TODO(benvanik): go lockfree, and don't hold the lock while emitting.
|
||||
|
||||
template <typename... Args>
|
||||
class Delegate {
|
||||
public:
|
||||
typedef std::function<void(Args&...)> Listener;
|
||||
|
||||
void AddListener(Listener const& listener) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
listeners_.push_back(listener);
|
||||
}
|
||||
|
||||
void RemoveAllListeners() {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
listeners_.clear();
|
||||
}
|
||||
|
||||
void operator()(Args&... args) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
for (auto& listener : listeners_) {
|
||||
listener(args...);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex lock_;
|
||||
std::vector<Listener> listeners_;
|
||||
};
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_DELEGATE_H_
|
||||
182
src/xenia/base/fs.cc
Normal file
182
src/xenia/base/fs.cc
Normal file
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/fs.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace xe {
|
||||
namespace fs {
|
||||
|
||||
std::string CanonicalizePath(const std::string& original_path) {
|
||||
char path_sep('\\');
|
||||
std::string path(xe::fix_path_separators(original_path, path_sep));
|
||||
|
||||
std::vector<std::string::size_type> path_breaks;
|
||||
|
||||
std::string::size_type pos(path.find_first_of(path_sep));
|
||||
std::string::size_type pos_n(std::string::npos);
|
||||
|
||||
while (pos != std::string::npos) {
|
||||
if ((pos_n = path.find_first_of(path_sep, pos + 1)) == std::string::npos) {
|
||||
pos_n = path.size();
|
||||
}
|
||||
|
||||
auto diff(pos_n - pos);
|
||||
switch (diff) {
|
||||
case 0:
|
||||
pos_n = std::string::npos;
|
||||
break;
|
||||
case 1:
|
||||
// Duplicate separators
|
||||
path.erase(pos, 1);
|
||||
pos_n -= 1;
|
||||
break;
|
||||
case 2:
|
||||
// Potential marker for current directory
|
||||
if (path[pos + 1] == '.') {
|
||||
path.erase(pos, 2);
|
||||
pos_n -= 2;
|
||||
} else {
|
||||
path_breaks.push_back(pos);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// Potential marker for parent directory
|
||||
if (path[pos + 1] == '.' && path[pos + 2] == '.') {
|
||||
if (path_breaks.empty()) {
|
||||
// Ensure we don't override the device name
|
||||
std::string::size_type loc(path.find_first_of(':'));
|
||||
auto req(pos + 3);
|
||||
if (loc == std::string::npos || loc > req) {
|
||||
path.erase(0, req);
|
||||
pos_n -= req;
|
||||
} else {
|
||||
path.erase(loc + 1, req - (loc + 1));
|
||||
pos_n -= req - (loc + 1);
|
||||
}
|
||||
} else {
|
||||
auto last(path_breaks.back());
|
||||
auto last_diff((pos + 3) - last);
|
||||
path.erase(last, last_diff);
|
||||
pos_n = last;
|
||||
// Also remove path reference
|
||||
path_breaks.erase(path_breaks.end() - 1);
|
||||
}
|
||||
} else {
|
||||
path_breaks.push_back(pos);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
path_breaks.push_back(pos);
|
||||
break;
|
||||
}
|
||||
|
||||
pos = pos_n;
|
||||
}
|
||||
|
||||
// Remove trailing seperator
|
||||
if (!path.empty() && path.back() == path_sep) {
|
||||
path.erase(path.size() - 1);
|
||||
}
|
||||
|
||||
// Final sanity check for dead paths
|
||||
if ((path.size() == 1 && (path[0] == '.' || path[0] == path_sep)) ||
|
||||
(path.size() == 2 && path[0] == '.' && path[1] == '.')) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
WildcardFlags WildcardFlags::FIRST(true, false);
|
||||
WildcardFlags WildcardFlags::LAST(false, true);
|
||||
|
||||
WildcardFlags::WildcardFlags() : FromStart(false), ToEnd(false) {}
|
||||
|
||||
WildcardFlags::WildcardFlags(bool start, bool end)
|
||||
: FromStart(start), ToEnd(end) {}
|
||||
|
||||
WildcardRule::WildcardRule(const std::string& str_match,
|
||||
const WildcardFlags& flags)
|
||||
: match(str_match), rules(flags) {
|
||||
std::transform(match.begin(), match.end(), match.begin(), tolower);
|
||||
}
|
||||
|
||||
bool WildcardRule::Check(const std::string& str_lower,
|
||||
std::string::size_type& offset) const {
|
||||
if (match.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((str_lower.size() - offset) < match.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string::size_type result(str_lower.find(match, offset));
|
||||
|
||||
if (result != std::string::npos) {
|
||||
if (rules.FromStart && result != offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rules.ToEnd && result != (str_lower.size() - match.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
offset = (result + match.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WildcardEngine::PreparePattern(const std::string& pattern) {
|
||||
rules.clear();
|
||||
|
||||
WildcardFlags flags(WildcardFlags::FIRST);
|
||||
size_t n = 0;
|
||||
size_t last = 0;
|
||||
while ((n = pattern.find_first_of('*', last)) != pattern.npos) {
|
||||
if (last != n) {
|
||||
std::string str_str(pattern.substr(last, n - last));
|
||||
rules.push_back(WildcardRule(str_str, flags));
|
||||
}
|
||||
last = n + 1;
|
||||
flags = WildcardFlags();
|
||||
}
|
||||
if (last != pattern.size()) {
|
||||
std::string str_str(pattern.substr(last));
|
||||
rules.push_back(WildcardRule(str_str, WildcardFlags::LAST));
|
||||
}
|
||||
}
|
||||
|
||||
void WildcardEngine::SetRule(const std::string& pattern) {
|
||||
PreparePattern(pattern);
|
||||
}
|
||||
|
||||
bool WildcardEngine::Match(const std::string& str) const {
|
||||
std::string str_lc;
|
||||
std::transform(str.begin(), str.end(), std::back_inserter(str_lc), tolower);
|
||||
|
||||
std::string::size_type offset(0);
|
||||
for (const auto& rule : rules) {
|
||||
if (!(rule.Check(str_lc, offset))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xe
|
||||
79
src/xenia/base/fs.h
Normal file
79
src/xenia/base/fs.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_FS_H_
|
||||
#define XENIA_BASE_FS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "xenia/base/string.h"
|
||||
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
|
||||
namespace xe {
|
||||
namespace fs {
|
||||
|
||||
bool PathExists(const std::wstring& path);
|
||||
|
||||
bool CreateFolder(const std::wstring& path);
|
||||
|
||||
bool DeleteFolder(const std::wstring& path);
|
||||
|
||||
struct FileInfo {
|
||||
enum class Type {
|
||||
kFile,
|
||||
kDirectory,
|
||||
};
|
||||
Type type;
|
||||
std::wstring name;
|
||||
size_t total_size;
|
||||
};
|
||||
std::vector<FileInfo> ListFiles(const std::wstring& path);
|
||||
|
||||
std::string CanonicalizePath(const std::string& original_path);
|
||||
|
||||
class WildcardFlags {
|
||||
public:
|
||||
bool FromStart : 1, ToEnd : 1;
|
||||
|
||||
WildcardFlags();
|
||||
WildcardFlags(bool start, bool end);
|
||||
|
||||
static WildcardFlags FIRST;
|
||||
static WildcardFlags LAST;
|
||||
};
|
||||
|
||||
class WildcardRule {
|
||||
public:
|
||||
WildcardRule(const std::string& str_match, const WildcardFlags& flags);
|
||||
bool Check(const std::string& str_lower,
|
||||
std::string::size_type& offset) const;
|
||||
|
||||
private:
|
||||
std::string match;
|
||||
WildcardFlags rules;
|
||||
};
|
||||
|
||||
class WildcardEngine {
|
||||
public:
|
||||
void SetRule(const std::string& pattern);
|
||||
|
||||
// Always ignoring case
|
||||
bool Match(const std::string& str) const;
|
||||
|
||||
private:
|
||||
std::vector<WildcardRule> rules;
|
||||
void PreparePattern(const std::string& pattern);
|
||||
};
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_FS_H_
|
||||
77
src/xenia/base/fs_win.cc
Normal file
77
src/xenia/base/fs_win.cc
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/fs.h"
|
||||
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
namespace xe {
|
||||
namespace fs {
|
||||
|
||||
bool PathExists(const std::wstring& path) {
|
||||
DWORD attrib = GetFileAttributes(path.c_str());
|
||||
return attrib != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
bool CreateFolder(const std::wstring& path) {
|
||||
wchar_t folder[MAX_PATH] = {0};
|
||||
auto end = std::wcschr(path.c_str(), L'\\');
|
||||
while (end) {
|
||||
wcsncpy(folder, path.c_str(), end - path.c_str() + 1);
|
||||
CreateDirectory(folder, NULL);
|
||||
end = wcschr(++end, L'\\');
|
||||
}
|
||||
return PathExists(path);
|
||||
}
|
||||
|
||||
bool DeleteFolder(const std::wstring& path) {
|
||||
auto double_null_path = path + L"\0";
|
||||
SHFILEOPSTRUCT op = {0};
|
||||
op.wFunc = FO_DELETE;
|
||||
op.pFrom = double_null_path.c_str();
|
||||
op.fFlags = FOF_NO_UI;
|
||||
return SHFileOperation(&op) == 0;
|
||||
}
|
||||
|
||||
std::vector<FileInfo> ListFiles(const std::wstring& path) {
|
||||
std::vector<FileInfo> result;
|
||||
|
||||
WIN32_FIND_DATA ffd;
|
||||
HANDLE handle = FindFirstFile((path + L"\\*").c_str(), &ffd);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
return result;
|
||||
}
|
||||
do {
|
||||
if (std::wcscmp(ffd.cFileName, L".") == 0 ||
|
||||
std::wcscmp(ffd.cFileName, L"..") == 0) {
|
||||
continue;
|
||||
}
|
||||
FileInfo info;
|
||||
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
info.type = FileInfo::Type::kDirectory;
|
||||
info.total_size = 0;
|
||||
} else {
|
||||
info.type = FileInfo::Type::kFile;
|
||||
info.total_size =
|
||||
(ffd.nFileSizeHigh * (size_t(MAXDWORD) + 1)) + ffd.nFileSizeLow;
|
||||
}
|
||||
info.name = ffd.cFileName;
|
||||
result.push_back(info);
|
||||
} while (FindNextFile(handle, &ffd) != 0);
|
||||
FindClose(handle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xe
|
||||
@@ -7,16 +7,16 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/logging.h"
|
||||
#include "xenia/base/logging.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "poly/cxx_compat.h"
|
||||
#include "poly/main.h"
|
||||
#include "poly/math.h"
|
||||
#include "poly/threading.h"
|
||||
#include "xenia/base/cxx_compat.h"
|
||||
#include "xenia/base/main.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/threading.h"
|
||||
|
||||
DEFINE_bool(fast_stdout, false,
|
||||
"Don't lock around stdout/stderr. May introduce weirdness.");
|
||||
@@ -34,7 +34,7 @@ void format_log_line(char* buffer, size_t buffer_count, const char* file_path,
|
||||
char* buffer_ptr;
|
||||
if (FLAGS_log_filenames) {
|
||||
// Strip out just the filename from the path.
|
||||
const char* filename = strrchr(file_path, poly::path_separator);
|
||||
const char* filename = strrchr(file_path, xe::path_separator);
|
||||
if (filename) {
|
||||
// Slash - skip over it.
|
||||
filename++;
|
||||
@@ -46,15 +46,15 @@ void format_log_line(char* buffer, size_t buffer_count, const char* file_path,
|
||||
// Format string - add a trailing newline if required.
|
||||
const char* outfmt = "%c> %.2X %s:%d: ";
|
||||
buffer_ptr = buffer + snprintf(buffer, buffer_count - 1, outfmt, level_char,
|
||||
poly::threading::current_thread_id(),
|
||||
filename, line_number);
|
||||
xe::threading::current_thread_id(), filename,
|
||||
line_number);
|
||||
} else {
|
||||
buffer_ptr = buffer;
|
||||
*(buffer_ptr++) = level_char;
|
||||
*(buffer_ptr++) = '>';
|
||||
*(buffer_ptr++) = ' ';
|
||||
buffer_ptr +=
|
||||
sprintf(buffer_ptr, "%.4X", poly::threading::current_thread_id());
|
||||
sprintf(buffer_ptr, "%.4X", xe::threading::current_thread_id());
|
||||
*(buffer_ptr++) = ' ';
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ void log_line(const char* file_path, const uint32_t line_number,
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
format_log_line(log_buffer, poly::countof(log_buffer), file_path, line_number,
|
||||
format_log_line(log_buffer, xe::countof(log_buffer), file_path, line_number,
|
||||
level_char, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
@@ -103,8 +103,8 @@ void handle_fatal(const char* file_path, const uint32_t line_number,
|
||||
char buffer[2048];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
format_log_line(buffer, poly::countof(buffer), file_path, line_number, 'X',
|
||||
fmt, args);
|
||||
format_log_line(buffer, xe::countof(buffer), file_path, line_number, 'X', fmt,
|
||||
args);
|
||||
va_end(args);
|
||||
|
||||
if (!FLAGS_fast_stdout) {
|
||||
@@ -121,7 +121,7 @@ void handle_fatal(const char* file_path, const uint32_t line_number,
|
||||
}
|
||||
|
||||
#if XE_PLATFORM_WIN32
|
||||
if (!poly::has_console_attached()) {
|
||||
if (!xe::has_console_attached()) {
|
||||
MessageBoxA(NULL, buffer, "Xenia Error",
|
||||
MB_OK | MB_ICONERROR | MB_APPLMODAL | MB_SETFOREGROUND);
|
||||
}
|
||||
@@ -12,20 +12,20 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "poly/string.h"
|
||||
#include "xenia/base/string.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
#define XE_OPTION_ENABLE_LOGGING 1
|
||||
#define XE_OPTION_LOG_ERROR 1
|
||||
#define XE_OPTION_LOG_WARNING 1
|
||||
#define XE_OPTION_LOG_INFO 1
|
||||
#define XE_OPTION_LOG_DEBUG 1
|
||||
#define XE_OPTION_LOG_CPU 1
|
||||
#define XE_OPTION_LOG_APU 1
|
||||
#define XE_OPTION_LOG_GPU 1
|
||||
#define XE_OPTION_LOG_KERNEL 1
|
||||
#define XE_OPTION_LOG_FS 1
|
||||
#define XE_OPTION_ENABLE_LOGGING 1
|
||||
#define XE_OPTION_LOG_ERROR 1
|
||||
#define XE_OPTION_LOG_WARNING 1
|
||||
#define XE_OPTION_LOG_INFO 1
|
||||
#define XE_OPTION_LOG_DEBUG 1
|
||||
#define XE_OPTION_LOG_CPU 1
|
||||
#define XE_OPTION_LOG_APU 1
|
||||
#define XE_OPTION_LOG_GPU 1
|
||||
#define XE_OPTION_LOG_KERNEL 1
|
||||
#define XE_OPTION_LOG_FS 1
|
||||
|
||||
#define XE_EMPTY_MACRO \
|
||||
do { \
|
||||
39
src/xenia/base/main.h
Normal file
39
src/xenia/base/main.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_MAIN_H_
|
||||
#define XENIA_BASE_MAIN_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
// Returns true if there is a user-visible console attached to receive stdout.
|
||||
bool has_console_attached();
|
||||
|
||||
// Extern defined by user code. This must be present for the application to
|
||||
// launch.
|
||||
struct EntryInfo {
|
||||
std::wstring name;
|
||||
std::wstring usage;
|
||||
int (*entry_point)(std::vector<std::wstring>& args);
|
||||
};
|
||||
EntryInfo GetEntryInfo();
|
||||
|
||||
#define DEFINE_ENTRY_POINT(name, usage, entry_point) \
|
||||
xe::EntryInfo xe::GetEntryInfo() { \
|
||||
return xe::EntryInfo({name, usage, entry_point}); \
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_MAIN_H_
|
||||
40
src/xenia/base/main_posix.cc
Normal file
40
src/xenia/base/main_posix.cc
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/main.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include "xenia/base/string.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
bool has_console_attached() { return true; }
|
||||
|
||||
} // namespace xe
|
||||
|
||||
extern "C" int main(int argc, char** argv) {
|
||||
auto entry_info = xe::GetEntryInfo();
|
||||
|
||||
google::SetUsageMessage(std::string("usage: ") +
|
||||
xe::to_string(entry_info.usage));
|
||||
google::SetVersionString("1.0");
|
||||
google::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
std::vector<std::wstring> args;
|
||||
for (int n = 0; n < argc; n++) {
|
||||
args.push_back(xe::to_wstring(argv[n]));
|
||||
}
|
||||
|
||||
// Call app-provided entry point.
|
||||
int result = entry_info.entry_point(args);
|
||||
|
||||
google::ShutDownCommandLineFlags();
|
||||
return result;
|
||||
}
|
||||
127
src/xenia/base/main_win.cc
Normal file
127
src/xenia/base/main_win.cc
Normal file
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/main.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include "xenia/base/string.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
bool has_console_attached_ = true;
|
||||
|
||||
bool has_console_attached() { return has_console_attached_; }
|
||||
|
||||
void AttachConsole() {
|
||||
bool has_console = ::AttachConsole(ATTACH_PARENT_PROCESS) == TRUE;
|
||||
if (!has_console) {
|
||||
// We weren't launched from a console, so just return.
|
||||
// We could alloc our own console, but meh:
|
||||
// has_console = AllocConsole() == TRUE;
|
||||
has_console_attached_ = false;
|
||||
return;
|
||||
}
|
||||
has_console_attached_ = true;
|
||||
|
||||
auto std_handle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
auto con_handle = _open_osfhandle(std_handle, _O_TEXT);
|
||||
auto fp = _fdopen(con_handle, "w");
|
||||
*stdout = *fp;
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
|
||||
std_handle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
|
||||
con_handle = _open_osfhandle(std_handle, _O_TEXT);
|
||||
fp = _fdopen(con_handle, "w");
|
||||
*stderr = *fp;
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
||||
// Used in console mode apps; automatically picked based on subsystem.
|
||||
int wmain(int argc, wchar_t* argv[]) {
|
||||
auto entry_info = xe::GetEntryInfo();
|
||||
|
||||
google::SetUsageMessage(std::string("usage: ") +
|
||||
xe::to_string(entry_info.usage));
|
||||
google::SetVersionString("1.0");
|
||||
|
||||
// Convert all args to narrow, as gflags doesn't support wchar.
|
||||
int argca = argc;
|
||||
char** argva = (char**)alloca(sizeof(char*) * argca);
|
||||
for (int n = 0; n < argca; n++) {
|
||||
size_t len = wcslen(argv[n]);
|
||||
argva[n] = (char*)alloca(len + 1);
|
||||
wcstombs_s(nullptr, argva[n], len + 1, argv[n], _TRUNCATE);
|
||||
}
|
||||
|
||||
// Parse flags; this may delete some of them.
|
||||
google::ParseCommandLineFlags(&argc, &argva, true);
|
||||
|
||||
// Widen all remaining flags and convert to usable strings.
|
||||
std::vector<std::wstring> args;
|
||||
for (int n = 0; n < argc; n++) {
|
||||
args.push_back(xe::to_wstring(argva[n]));
|
||||
}
|
||||
|
||||
// Setup COM on the main thread.
|
||||
// NOTE: this may fail if COM has already been initialized - that's OK.
|
||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
|
||||
// Call app-provided entry point.
|
||||
int result = entry_info.entry_point(args);
|
||||
|
||||
google::ShutDownCommandLineFlags();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Used in windowed apps; automatically picked based on subsystem.
|
||||
int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR command_line, int) {
|
||||
// Attach a console so we can write output to stdout. If the user hasn't
|
||||
// redirected output themselves it'll pop up a window.
|
||||
xe::AttachConsole();
|
||||
|
||||
auto entry_info = xe::GetEntryInfo();
|
||||
|
||||
// Convert to an argv-like format so we can share code/use gflags.
|
||||
std::wstring buffer = entry_info.name + L" " + command_line;
|
||||
int argc;
|
||||
wchar_t** argv = CommandLineToArgvW(buffer.c_str(), &argc);
|
||||
if (!argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Run normal entry point.
|
||||
int result = wmain(argc, argv);
|
||||
|
||||
LocalFree(argv);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined _M_IX86
|
||||
#pragma comment( \
|
||||
linker, \
|
||||
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
#elif defined _M_IA64
|
||||
#pragma comment( \
|
||||
linker, \
|
||||
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
#elif defined _M_X64
|
||||
#pragma comment( \
|
||||
linker, \
|
||||
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
#else
|
||||
#pragma comment( \
|
||||
linker, \
|
||||
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
#endif
|
||||
46
src/xenia/base/mapped_memory.h
Normal file
46
src/xenia/base/mapped_memory.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_MAPPED_MEMORY_H_
|
||||
#define XENIA_BASE_MAPPED_MEMORY_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace xe {
|
||||
|
||||
class MappedMemory {
|
||||
public:
|
||||
enum class Mode {
|
||||
kRead,
|
||||
kReadWrite,
|
||||
};
|
||||
|
||||
virtual ~MappedMemory() = default;
|
||||
|
||||
static std::unique_ptr<MappedMemory> Open(const std::wstring& path, Mode mode,
|
||||
size_t offset = 0,
|
||||
size_t length = 0);
|
||||
|
||||
uint8_t* data() const { return reinterpret_cast<uint8_t*>(data_); }
|
||||
size_t size() const { return size_; }
|
||||
|
||||
protected:
|
||||
MappedMemory(const std::wstring& path, Mode mode)
|
||||
: path_(path), mode_(mode), data_(nullptr), size_(0) {}
|
||||
|
||||
std::wstring path_;
|
||||
Mode mode_;
|
||||
void* data_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_MAPPED_MEMORY_H_
|
||||
77
src/xenia/base/mapped_memory_posix.cc
Normal file
77
src/xenia/base/mapped_memory_posix.cc
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/mapped_memory.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include "xenia/base/string.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
class PosixMappedMemory : public MappedMemory {
|
||||
public:
|
||||
PosixMappedMemory(const std::wstring& path, Mode mode)
|
||||
: MappedMemory(path, mode), file_handle(nullptr) {}
|
||||
|
||||
~PosixMappedMemory() override {
|
||||
if (data_) {
|
||||
munmap(data_, size_);
|
||||
}
|
||||
if (file_handle) {
|
||||
fclose(file_handle);
|
||||
}
|
||||
}
|
||||
|
||||
FILE* file_handle;
|
||||
};
|
||||
|
||||
std::unique_ptr<MappedMemory> MappedMemory::Open(const std::wstring& path,
|
||||
Mode mode, size_t offset,
|
||||
size_t length) {
|
||||
const char* mode_str;
|
||||
int prot;
|
||||
switch (mode) {
|
||||
case Mode::READ:
|
||||
mode_str = "rb";
|
||||
prot = PROT_READ;
|
||||
break;
|
||||
case Mode::READ_WRITE:
|
||||
mode_str = "r+b";
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
auto mm = std::make_unique<PosixMappedMemory>(path, mode);
|
||||
|
||||
mm->file_handle = fopen(xe::to_string(path).c_str(), mode_str);
|
||||
if (!mm->file_handle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t map_length;
|
||||
map_length = length;
|
||||
if (!length) {
|
||||
fseeko(mm->file_handle, 0, SEEK_END);
|
||||
map_length = ftello(mm->file_handle);
|
||||
fseeko(mm->file_handle, 0, SEEK_SET);
|
||||
}
|
||||
mm->size_ = map_length;
|
||||
|
||||
mm->data_ =
|
||||
mmap(0, map_length, prot, MAP_SHARED, fileno(mm->file_handle), offset);
|
||||
if (!mm->data_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::move(mm);
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
105
src/xenia/base/mapped_memory_win.cc
Normal file
105
src/xenia/base/mapped_memory_win.cc
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/mapped_memory.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace xe {
|
||||
|
||||
class Win32MappedMemory : public MappedMemory {
|
||||
public:
|
||||
Win32MappedMemory(const std::wstring& path, Mode mode)
|
||||
: MappedMemory(path, mode),
|
||||
file_handle(nullptr),
|
||||
mapping_handle(nullptr) {}
|
||||
|
||||
~Win32MappedMemory() override {
|
||||
if (data_) {
|
||||
UnmapViewOfFile(data_);
|
||||
}
|
||||
if (mapping_handle) {
|
||||
CloseHandle(mapping_handle);
|
||||
}
|
||||
if (file_handle) {
|
||||
CloseHandle(file_handle);
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE file_handle;
|
||||
HANDLE mapping_handle;
|
||||
};
|
||||
|
||||
std::unique_ptr<MappedMemory> MappedMemory::Open(const std::wstring& path,
|
||||
Mode mode, size_t offset,
|
||||
size_t length) {
|
||||
DWORD file_access = 0;
|
||||
DWORD file_share = 0;
|
||||
DWORD create_mode = 0;
|
||||
DWORD mapping_protect = 0;
|
||||
DWORD view_access = 0;
|
||||
switch (mode) {
|
||||
case Mode::kRead:
|
||||
file_access |= GENERIC_READ;
|
||||
file_share |= FILE_SHARE_READ;
|
||||
create_mode |= OPEN_EXISTING;
|
||||
mapping_protect |= PAGE_READONLY;
|
||||
view_access |= FILE_MAP_READ;
|
||||
break;
|
||||
case Mode::kReadWrite:
|
||||
file_access |= GENERIC_READ | GENERIC_WRITE;
|
||||
file_share |= 0;
|
||||
create_mode |= OPEN_EXISTING;
|
||||
mapping_protect |= PAGE_READWRITE;
|
||||
view_access |= FILE_MAP_READ | FILE_MAP_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetSystemInfo(&systemInfo);
|
||||
|
||||
const size_t aligned_offset =
|
||||
offset & ~static_cast<size_t>(systemInfo.dwAllocationGranularity - 1);
|
||||
const size_t aligned_length = length + (offset - aligned_offset);
|
||||
|
||||
auto mm = std::make_unique<Win32MappedMemory>(path, mode);
|
||||
|
||||
mm->file_handle = CreateFile(path.c_str(), file_access, file_share, nullptr,
|
||||
create_mode, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (!mm->file_handle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mm->mapping_handle = CreateFileMapping(mm->file_handle, nullptr,
|
||||
mapping_protect, 0, 0, nullptr);
|
||||
//(DWORD)(aligned_length >> 32), (DWORD)(aligned_length & 0xFFFFFFFF), NULL);
|
||||
if (!mm->mapping_handle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mm->data_ = reinterpret_cast<uint8_t*>(MapViewOfFile(
|
||||
mm->mapping_handle, view_access, static_cast<DWORD>(aligned_offset >> 32),
|
||||
static_cast<DWORD>(aligned_offset & 0xFFFFFFFF), aligned_length));
|
||||
if (!mm->data_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (length) {
|
||||
mm->size_ = aligned_length;
|
||||
} else {
|
||||
DWORD length_high;
|
||||
size_t map_length = GetFileSize(mm->file_handle, &length_high);
|
||||
map_length |= static_cast<uint64_t>(length_high) << 32;
|
||||
mm->size_ = map_length - aligned_offset;
|
||||
}
|
||||
|
||||
return std::move(mm);
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
69
src/xenia/base/math.cc
Normal file
69
src/xenia/base/math.cc
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/math.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
// TODO(benvanik): replace with alternate implementation.
|
||||
// XMConvertFloatToHalf
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
uint16_t float_to_half(float value) {
|
||||
uint32_t Result;
|
||||
uint32_t IValue = ((uint32_t *)(&value))[0];
|
||||
uint32_t Sign = (IValue & 0x80000000U) >> 16U;
|
||||
IValue = IValue & 0x7FFFFFFFU; // Hack off the sign
|
||||
if (IValue > 0x47FFEFFFU) {
|
||||
// The number is too large to be represented as a half. Saturate to
|
||||
// infinity.
|
||||
Result = 0x7FFFU;
|
||||
} else {
|
||||
if (IValue < 0x38800000U) {
|
||||
// The number is too small to be represented as a normalized half.
|
||||
// Convert it to a denormalized value.
|
||||
uint32_t Shift = 113U - (IValue >> 23U);
|
||||
IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift;
|
||||
} else {
|
||||
// Rebias the exponent to represent the value as a normalized half.
|
||||
IValue += 0xC8000000U;
|
||||
}
|
||||
Result = ((IValue + 0x0FFFU + ((IValue >> 13U) & 1U)) >> 13U) & 0x7FFFU;
|
||||
}
|
||||
return (uint16_t)(Result | Sign);
|
||||
}
|
||||
|
||||
// TODO(benvanik): replace with alternate implementation.
|
||||
// XMConvertHalfToFloat
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
float half_to_float(uint16_t value) {
|
||||
uint32_t Mantissa = (uint32_t)(value & 0x03FF);
|
||||
uint32_t Exponent;
|
||||
if ((value & 0x7C00) != 0) {
|
||||
// The value is normalized
|
||||
Exponent = (uint32_t)((value >> 10) & 0x1F);
|
||||
} else if (Mantissa != 0) {
|
||||
// The value is denormalized
|
||||
// Normalize the value in the resulting float
|
||||
Exponent = 1;
|
||||
do {
|
||||
Exponent--;
|
||||
Mantissa <<= 1;
|
||||
} while ((Mantissa & 0x0400) == 0);
|
||||
Mantissa &= 0x03FF;
|
||||
} else {
|
||||
// The value is zero
|
||||
Exponent = (uint32_t)-112;
|
||||
}
|
||||
uint32_t Result = ((value & 0x8000) << 16) | // Sign
|
||||
((Exponent + 112) << 23) | // Exponent
|
||||
(Mantissa << 13); // Mantissa
|
||||
return *(float *)&Result;
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
225
src/xenia/base/math.h
Normal file
225
src/xenia/base/math.h
Normal file
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_MATH_H_
|
||||
#define XENIA_BASE_MATH_H_
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
template <typename T, size_t N>
|
||||
size_t countof(T (&arr)[N]) {
|
||||
return std::extent<T[N]>::value;
|
||||
}
|
||||
|
||||
// Rounds up the given value to the given alignment.
|
||||
template <typename T>
|
||||
T align(T value, T alignment) {
|
||||
return (value + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
// Rounds the given number up to the next highest multiple.
|
||||
template <typename T, typename V>
|
||||
T round_up(T value, V multiple) {
|
||||
return value ? (((value + multiple - 1) / multiple) * multiple) : multiple;
|
||||
}
|
||||
|
||||
inline float saturate(float value) {
|
||||
return std::max(std::min(1.0f, value), -1.0f);
|
||||
}
|
||||
|
||||
// Gets the next power of two value that is greater than or equal to the given
|
||||
// value.
|
||||
template <typename T>
|
||||
T next_pow2(T value) {
|
||||
value--;
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
value++;
|
||||
return value;
|
||||
}
|
||||
|
||||
// lzcnt instruction, typed for integers of all sizes.
|
||||
// The number of leading zero bits in the value parameter. If value is zero, the
|
||||
// return value is the size of the input operand (8, 16, 32, or 64). If the most
|
||||
// significant bit of value is one, the return value is zero.
|
||||
#if XE_COMPILER_MSVC
|
||||
#if 1
|
||||
inline uint8_t lzcnt(uint8_t v) {
|
||||
return static_cast<uint8_t>(__lzcnt16(v) - 8);
|
||||
}
|
||||
inline uint8_t lzcnt(uint16_t v) { return static_cast<uint8_t>(__lzcnt16(v)); }
|
||||
inline uint8_t lzcnt(uint32_t v) { return static_cast<uint8_t>(__lzcnt(v)); }
|
||||
inline uint8_t lzcnt(uint64_t v) { return static_cast<uint8_t>(__lzcnt64(v)); }
|
||||
#else
|
||||
inline uint8_t lzcnt(uint8_t v) {
|
||||
DWORD index;
|
||||
DWORD mask = v;
|
||||
BOOLEAN is_nonzero = _BitScanReverse(&index, mask);
|
||||
return static_cast<uint8_t>(is_nonzero ? int8_t(index - 24) ^ 0x7 : 8);
|
||||
}
|
||||
inline uint8_t lzcnt(uint16_t v) {
|
||||
DWORD index;
|
||||
DWORD mask = v;
|
||||
BOOLEAN is_nonzero = _BitScanReverse(&index, mask);
|
||||
return static_cast<uint8_t>(is_nonzero ? int8_t(index - 16) ^ 0xF : 16);
|
||||
}
|
||||
inline uint8_t lzcnt(uint32_t v) {
|
||||
DWORD index;
|
||||
DWORD mask = v;
|
||||
BOOLEAN is_nonzero = _BitScanReverse(&index, mask);
|
||||
return static_cast<uint8_t>(is_nonzero ? int8_t(index) ^ 0x1F : 32);
|
||||
}
|
||||
inline uint8_t lzcnt(uint64_t v) {
|
||||
DWORD index;
|
||||
DWORD64 mask = v;
|
||||
BOOLEAN is_nonzero = _BitScanReverse64(&index, mask);
|
||||
return static_cast<uint8_t>(is_nonzero ? int8_t(index) ^ 0x3F : 64);
|
||||
}
|
||||
#endif // LZCNT supported
|
||||
#else
|
||||
inline uint8_t lzcnt(uint8_t v) {
|
||||
return static_cast<uint8_t>(__builtin_clzs(v) - 8);
|
||||
}
|
||||
inline uint8_t lzcnt(uint16_t v) {
|
||||
return static_cast<uint8_t>(__builtin_clzs(v));
|
||||
}
|
||||
inline uint8_t lzcnt(uint32_t v) {
|
||||
return static_cast<uint8_t>(__builtin_clz(v));
|
||||
}
|
||||
inline uint8_t lzcnt(uint64_t v) {
|
||||
return static_cast<uint8_t>(__builtin_clzll(v));
|
||||
}
|
||||
#endif // XE_COMPILER_MSVC
|
||||
inline uint8_t lzcnt(int8_t v) { return lzcnt(static_cast<uint8_t>(v)); }
|
||||
inline uint8_t lzcnt(int16_t v) { return lzcnt(static_cast<uint16_t>(v)); }
|
||||
inline uint8_t lzcnt(int32_t v) { return lzcnt(static_cast<uint32_t>(v)); }
|
||||
inline uint8_t lzcnt(int64_t v) { return lzcnt(static_cast<uint64_t>(v)); }
|
||||
|
||||
// BitScanForward (bsf).
|
||||
// Search the value from least significant bit (LSB) to the most significant bit
|
||||
// (MSB) for a set bit (1).
|
||||
// Returns false if no bits are set and the output index is invalid.
|
||||
#if XE_COMPILER_MSVC
|
||||
inline bool bit_scan_forward(uint32_t v, uint32_t* out_first_set_index) {
|
||||
return _BitScanForward(reinterpret_cast<unsigned long*>(out_first_set_index),
|
||||
v) != 0;
|
||||
}
|
||||
inline bool bit_scan_forward(uint64_t v, uint32_t* out_first_set_index) {
|
||||
return _BitScanForward64(
|
||||
reinterpret_cast<unsigned long*>(out_first_set_index), v) != 0;
|
||||
}
|
||||
#else
|
||||
inline bool bit_scan_forward(uint32_t v, uint32_t* out_first_set_index) {
|
||||
int i = ffs(v);
|
||||
*out_first_set_index = i;
|
||||
return i != 0;
|
||||
}
|
||||
inline bool bit_scan_forward(uint64_t v, uint32_t* out_first_set_index) {
|
||||
int i = ffsll(v);
|
||||
*out_first_set_index = i;
|
||||
return i != 0;
|
||||
}
|
||||
#endif // XE_COMPILER_MSVC
|
||||
inline bool bit_scan_forward(int32_t v, uint32_t* out_first_set_index) {
|
||||
return bit_scan_forward(static_cast<uint32_t>(v), out_first_set_index);
|
||||
}
|
||||
inline bool bit_scan_forward(int64_t v, uint32_t* out_first_set_index) {
|
||||
return bit_scan_forward(static_cast<uint64_t>(v), out_first_set_index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T log2_floor(T v) {
|
||||
return sizeof(T) * 8 - 1 - lzcnt(v);
|
||||
}
|
||||
template <typename T>
|
||||
inline T log2_ceil(T v) {
|
||||
return sizeof(T) * 8 - lzcnt(v - 1);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T rotate_left(T v, uint8_t sh) {
|
||||
return (T(v) << sh) | (T(v) >> ((sizeof(T) * 8) - sh));
|
||||
}
|
||||
#if XE_COMPILER_MSVC
|
||||
template <>
|
||||
inline uint8_t rotate_left(uint8_t v, uint8_t sh) {
|
||||
return _rotl8(v, sh);
|
||||
}
|
||||
template <>
|
||||
inline uint16_t rotate_left(uint16_t v, uint8_t sh) {
|
||||
return _rotl16(v, sh);
|
||||
}
|
||||
template <>
|
||||
inline uint32_t rotate_left(uint32_t v, uint8_t sh) {
|
||||
return _rotl(v, sh);
|
||||
}
|
||||
template <>
|
||||
inline uint64_t rotate_left(uint64_t v, uint8_t sh) {
|
||||
return _rotl64(v, sh);
|
||||
}
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
// Utilities for SSE values.
|
||||
template <int N>
|
||||
float m128_f32(const __m128& v) {
|
||||
float ret;
|
||||
_mm_store_ss(&ret, _mm_shuffle_ps(v, v, _MM_SHUFFLE(N, N, N, N)));
|
||||
return ret;
|
||||
}
|
||||
template <int N>
|
||||
int32_t m128_i32(const __m128& v) {
|
||||
union {
|
||||
float f;
|
||||
int32_t i;
|
||||
} ret;
|
||||
_mm_store_ss(&ret.f, _mm_shuffle_ps(v, v, _MM_SHUFFLE(N, N, N, N)));
|
||||
return ret.i;
|
||||
}
|
||||
template <int N>
|
||||
double m128_f64(const __m128d& v) {
|
||||
double ret;
|
||||
_mm_store_sd(&ret, _mm_shuffle_pd(v, v, _MM_SHUFFLE2(N, N)));
|
||||
return ret;
|
||||
}
|
||||
template <int N>
|
||||
double m128_f64(const __m128& v) {
|
||||
return m128_f64<N>(_mm_castps_pd(v));
|
||||
}
|
||||
template <int N>
|
||||
int64_t m128_i64(const __m128d& v) {
|
||||
union {
|
||||
double f;
|
||||
int64_t i;
|
||||
} ret;
|
||||
_mm_store_sd(&ret.f, _mm_shuffle_pd(v, v, _MM_SHUFFLE2(N, N)));
|
||||
return ret.i;
|
||||
}
|
||||
template <int N>
|
||||
int64_t m128_i64(const __m128& v) {
|
||||
return m128_i64<N>(_mm_castps_pd(v));
|
||||
}
|
||||
|
||||
uint16_t float_to_half(float value);
|
||||
float half_to_float(uint16_t value);
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_MATH_H_
|
||||
321
src/xenia/base/memory.h
Normal file
321
src/xenia/base/memory.h
Normal file
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_MEMORY_H_
|
||||
#define XENIA_BASE_MEMORY_H_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/byte_order.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
inline size_t hash_combine(size_t seed) { return seed; }
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
size_t hash_combine(size_t seed, const T& v, const Ts&... vs) {
|
||||
std::hash<T> hasher;
|
||||
seed ^= hasher(v) + 0x9E3779B9 + (seed << 6) + (seed >> 2);
|
||||
return hash_combine(seed, vs...);
|
||||
}
|
||||
|
||||
size_t page_size();
|
||||
|
||||
void copy_and_swap_16_aligned(uint16_t* dest, const uint16_t* src,
|
||||
size_t count);
|
||||
void copy_and_swap_16_unaligned(uint16_t* dest, const uint16_t* src,
|
||||
size_t count);
|
||||
void copy_and_swap_32_aligned(uint32_t* dest, const uint32_t* src,
|
||||
size_t count);
|
||||
void copy_and_swap_32_unaligned(uint32_t* dest, const uint32_t* src,
|
||||
size_t count);
|
||||
void copy_and_swap_64_aligned(uint64_t* dest, const uint64_t* src,
|
||||
size_t count);
|
||||
void copy_and_swap_64_unaligned(uint64_t* dest, const uint64_t* src,
|
||||
size_t count);
|
||||
|
||||
template <typename T>
|
||||
void copy_and_swap(T* dest, const T* src, size_t count) {
|
||||
bool is_aligned = reinterpret_cast<uintptr_t>(dest) % 32 == 0 &&
|
||||
reinterpret_cast<uintptr_t>(src) % 32 == 0;
|
||||
if (sizeof(T) == 1) {
|
||||
std::memcpy(dest, src, count);
|
||||
} else if (sizeof(T) == 2) {
|
||||
auto ps = reinterpret_cast<const uint16_t*>(src);
|
||||
auto pd = reinterpret_cast<uint16_t*>(dest);
|
||||
if (is_aligned) {
|
||||
copy_and_swap_16_aligned(pd, ps, count);
|
||||
} else {
|
||||
copy_and_swap_16_unaligned(pd, ps, count);
|
||||
}
|
||||
} else if (sizeof(T) == 4) {
|
||||
auto ps = reinterpret_cast<const uint32_t*>(src);
|
||||
auto pd = reinterpret_cast<uint32_t*>(dest);
|
||||
if (is_aligned) {
|
||||
copy_and_swap_32_aligned(pd, ps, count);
|
||||
} else {
|
||||
copy_and_swap_32_unaligned(pd, ps, count);
|
||||
}
|
||||
} else if (sizeof(T) == 8) {
|
||||
auto ps = reinterpret_cast<const uint64_t*>(src);
|
||||
auto pd = reinterpret_cast<uint64_t*>(dest);
|
||||
if (is_aligned) {
|
||||
copy_and_swap_64_aligned(pd, ps, count);
|
||||
} else {
|
||||
copy_and_swap_64_unaligned(pd, ps, count);
|
||||
}
|
||||
} else {
|
||||
assert_always("Invalid xe::copy_and_swap size");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T load(const void* mem);
|
||||
template <>
|
||||
inline int8_t load<int8_t>(const void* mem) {
|
||||
return *reinterpret_cast<const int8_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline uint8_t load<uint8_t>(const void* mem) {
|
||||
return *reinterpret_cast<const uint8_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline int16_t load<int16_t>(const void* mem) {
|
||||
return *reinterpret_cast<const int16_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline uint16_t load<uint16_t>(const void* mem) {
|
||||
return *reinterpret_cast<const uint16_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline int32_t load<int32_t>(const void* mem) {
|
||||
return *reinterpret_cast<const int32_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline uint32_t load<uint32_t>(const void* mem) {
|
||||
return *reinterpret_cast<const uint32_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline int64_t load<int64_t>(const void* mem) {
|
||||
return *reinterpret_cast<const int64_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline uint64_t load<uint64_t>(const void* mem) {
|
||||
return *reinterpret_cast<const uint64_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline float load<float>(const void* mem) {
|
||||
return *reinterpret_cast<const float*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline double load<double>(const void* mem) {
|
||||
return *reinterpret_cast<const double*>(mem);
|
||||
}
|
||||
template <typename T>
|
||||
inline T load(const void* mem) {
|
||||
if (sizeof(T) == 1) {
|
||||
return static_cast<T>(load<uint8_t>(mem));
|
||||
} else if (sizeof(T) == 2) {
|
||||
return static_cast<T>(load<uint16_t>(mem));
|
||||
} else if (sizeof(T) == 4) {
|
||||
return static_cast<T>(load<uint32_t>(mem));
|
||||
} else if (sizeof(T) == 8) {
|
||||
return static_cast<T>(load<uint64_t>(mem));
|
||||
} else {
|
||||
assert_always("Invalid xe::load size");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T load_and_swap(const void* mem);
|
||||
template <>
|
||||
inline int8_t load_and_swap<int8_t>(const void* mem) {
|
||||
return *reinterpret_cast<const int8_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline uint8_t load_and_swap<uint8_t>(const void* mem) {
|
||||
return *reinterpret_cast<const uint8_t*>(mem);
|
||||
}
|
||||
template <>
|
||||
inline int16_t load_and_swap<int16_t>(const void* mem) {
|
||||
return byte_swap(*reinterpret_cast<const int16_t*>(mem));
|
||||
}
|
||||
template <>
|
||||
inline uint16_t load_and_swap<uint16_t>(const void* mem) {
|
||||
return byte_swap(*reinterpret_cast<const uint16_t*>(mem));
|
||||
}
|
||||
template <>
|
||||
inline int32_t load_and_swap<int32_t>(const void* mem) {
|
||||
return byte_swap(*reinterpret_cast<const int32_t*>(mem));
|
||||
}
|
||||
template <>
|
||||
inline uint32_t load_and_swap<uint32_t>(const void* mem) {
|
||||
return byte_swap(*reinterpret_cast<const uint32_t*>(mem));
|
||||
}
|
||||
template <>
|
||||
inline int64_t load_and_swap<int64_t>(const void* mem) {
|
||||
return byte_swap(*reinterpret_cast<const int64_t*>(mem));
|
||||
}
|
||||
template <>
|
||||
inline uint64_t load_and_swap<uint64_t>(const void* mem) {
|
||||
return byte_swap(*reinterpret_cast<const uint64_t*>(mem));
|
||||
}
|
||||
template <>
|
||||
inline float load_and_swap<float>(const void* mem) {
|
||||
return byte_swap(*reinterpret_cast<const float*>(mem));
|
||||
}
|
||||
template <>
|
||||
inline double load_and_swap<double>(const void* mem) {
|
||||
return byte_swap(*reinterpret_cast<const double*>(mem));
|
||||
}
|
||||
template <>
|
||||
inline std::string load_and_swap<std::string>(const void* mem) {
|
||||
std::string value;
|
||||
for (int i = 0;; ++i) {
|
||||
auto c =
|
||||
xe::load_and_swap<uint8_t>(reinterpret_cast<const uint8_t*>(mem) + i);
|
||||
if (!c) {
|
||||
break;
|
||||
}
|
||||
value.push_back(static_cast<char>(c));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
template <>
|
||||
inline std::wstring load_and_swap<std::wstring>(const void* mem) {
|
||||
std::wstring value;
|
||||
for (int i = 0;; ++i) {
|
||||
auto c =
|
||||
xe::load_and_swap<uint16_t>(reinterpret_cast<const uint16_t*>(mem) + i);
|
||||
if (!c) {
|
||||
break;
|
||||
}
|
||||
value.push_back(static_cast<wchar_t>(c));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void store(void* mem, T value);
|
||||
template <>
|
||||
inline void store<int8_t>(void* mem, int8_t value) {
|
||||
*reinterpret_cast<int8_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store<uint8_t>(void* mem, uint8_t value) {
|
||||
*reinterpret_cast<uint8_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store<int16_t>(void* mem, int16_t value) {
|
||||
*reinterpret_cast<int16_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store<uint16_t>(void* mem, uint16_t value) {
|
||||
*reinterpret_cast<uint16_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store<int32_t>(void* mem, int32_t value) {
|
||||
*reinterpret_cast<int32_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store<uint32_t>(void* mem, uint32_t value) {
|
||||
*reinterpret_cast<uint32_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store<int64_t>(void* mem, int64_t value) {
|
||||
*reinterpret_cast<int64_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store<uint64_t>(void* mem, uint64_t value) {
|
||||
*reinterpret_cast<uint64_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store<float>(void* mem, float value) {
|
||||
*reinterpret_cast<float*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store<double>(void* mem, double value) {
|
||||
*reinterpret_cast<double*>(mem) = value;
|
||||
}
|
||||
template <typename T>
|
||||
inline void store(const void* mem, T value) {
|
||||
if (sizeof(T) == 1) {
|
||||
store<uint8_t>(mem, static_cast<uint8_t>(value));
|
||||
} else if (sizeof(T) == 2) {
|
||||
store<uint8_t>(mem, static_cast<uint16_t>(value));
|
||||
} else if (sizeof(T) == 4) {
|
||||
store<uint8_t>(mem, static_cast<uint32_t>(value));
|
||||
} else if (sizeof(T) == 8) {
|
||||
store<uint8_t>(mem, static_cast<uint64_t>(value));
|
||||
} else {
|
||||
assert_always("Invalid xe::store size");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void store_and_swap(void* mem, T value);
|
||||
template <>
|
||||
inline void store_and_swap<int8_t>(void* mem, int8_t value) {
|
||||
*reinterpret_cast<int8_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<uint8_t>(void* mem, uint8_t value) {
|
||||
*reinterpret_cast<uint8_t*>(mem) = value;
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<int16_t>(void* mem, int16_t value) {
|
||||
*reinterpret_cast<int16_t*>(mem) = byte_swap(value);
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<uint16_t>(void* mem, uint16_t value) {
|
||||
*reinterpret_cast<uint16_t*>(mem) = byte_swap(value);
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<int32_t>(void* mem, int32_t value) {
|
||||
*reinterpret_cast<int32_t*>(mem) = byte_swap(value);
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<uint32_t>(void* mem, uint32_t value) {
|
||||
*reinterpret_cast<uint32_t*>(mem) = byte_swap(value);
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<int64_t>(void* mem, int64_t value) {
|
||||
*reinterpret_cast<int64_t*>(mem) = byte_swap(value);
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<uint64_t>(void* mem, uint64_t value) {
|
||||
*reinterpret_cast<uint64_t*>(mem) = byte_swap(value);
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<float>(void* mem, float value) {
|
||||
*reinterpret_cast<float*>(mem) = byte_swap(value);
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<double>(void* mem, double value) {
|
||||
*reinterpret_cast<double*>(mem) = byte_swap(value);
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<std::string>(void* mem, std::string value) {
|
||||
for (auto i = 0; i < value.size(); ++i) {
|
||||
xe::store_and_swap<uint8_t>(reinterpret_cast<uint8_t*>(mem) + i, value[i]);
|
||||
}
|
||||
}
|
||||
template <>
|
||||
inline void store_and_swap<std::wstring>(void* mem, std::wstring value) {
|
||||
for (auto i = 0; i < value.size(); ++i) {
|
||||
xe::store_and_swap<uint16_t>(reinterpret_cast<uint16_t*>(mem) + i,
|
||||
value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_MEMORY_H_
|
||||
75
src/xenia/base/memory_generic.cc
Normal file
75
src/xenia/base/memory_generic.cc
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/memory.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#if !XE_PLATFORM_WIN32
|
||||
#include <unistd.h>
|
||||
#endif // !XE_PLATFORM_WIN32
|
||||
|
||||
namespace xe {
|
||||
|
||||
size_t page_size() {
|
||||
static size_t value = 0;
|
||||
if (!value) {
|
||||
#if XE_PLATFORM_WIN32
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
value = si.dwPageSize;
|
||||
#else
|
||||
value = getpagesize();
|
||||
#endif // XE_PLATFORM_WIN32
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// TODO(benvanik): fancy AVX versions.
|
||||
// http://gnuradio.org/redmine/projects/gnuradio/repository/revisions/cb32b70b79f430456208a2cd521d028e0ece5d5b/entry/volk/kernels/volk/volk_16u_byteswap.h
|
||||
// http://gnuradio.org/redmine/projects/gnuradio/repository/revisions/f2bc76cc65ffba51a141950f98e75364e49df874/entry/volk/kernels/volk/volk_32u_byteswap.h
|
||||
// http://gnuradio.org/redmine/projects/gnuradio/repository/revisions/2c4c371885c31222362f70a1cd714415d1398021/entry/volk/kernels/volk/volk_64u_byteswap.h
|
||||
|
||||
void copy_and_swap_16_aligned(uint16_t* dest, const uint16_t* src,
|
||||
size_t count) {
|
||||
return copy_and_swap_16_unaligned(dest, src, count);
|
||||
}
|
||||
|
||||
void copy_and_swap_16_unaligned(uint16_t* dest, const uint16_t* src,
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
dest[i] = byte_swap(src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void copy_and_swap_32_aligned(uint32_t* dest, const uint32_t* src,
|
||||
size_t count) {
|
||||
return copy_and_swap_32_unaligned(dest, src, count);
|
||||
}
|
||||
|
||||
void copy_and_swap_32_unaligned(uint32_t* dest, const uint32_t* src,
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
dest[i] = byte_swap(src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void copy_and_swap_64_aligned(uint64_t* dest, const uint64_t* src,
|
||||
size_t count) {
|
||||
return copy_and_swap_64_unaligned(dest, src, count);
|
||||
}
|
||||
|
||||
void copy_and_swap_64_unaligned(uint64_t* dest, const uint64_t* src,
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
dest[i] = byte_swap(src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
76
src/xenia/base/platform.h
Normal file
76
src/xenia/base/platform.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_PLATFORM_H_
|
||||
#define XENIA_BASE_PLATFORM_H_
|
||||
|
||||
// NOTE: ordering matters here as sometimes multiple flags are defined on
|
||||
// certain platforms.
|
||||
|
||||
// Great resource on predefined macros: http://predef.sourceforge.net/preos.html
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
|
||||
#define XE_PLATFORM_MAC 1
|
||||
#elif defined(WIN32) || defined(_WIN32)
|
||||
#define XE_PLATFORM_WIN32 1
|
||||
#else
|
||||
#define XE_PLATFORM_LINUX 1
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#define XE_COMPILER_CLANG 1
|
||||
#elif defined(__GNUC__)
|
||||
#define XE_COMPILER_GNUC 1
|
||||
#elif defined(_MSC_VER)
|
||||
#define XE_COMPILER_MSVC 1
|
||||
#elif defined(__MINGW32)
|
||||
#define XE_COMPILER_MINGW32 1
|
||||
#elif defined(__INTEL_COMPILER)
|
||||
#define XE_COMPILER_INTEL 1
|
||||
#else
|
||||
#define XE_COMPILER_UNKNOWN 1
|
||||
#endif
|
||||
|
||||
#if XE_PLATFORM_WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <SDKDDKVer.h>
|
||||
#include <windows.h>
|
||||
#include <ObjBase.h>
|
||||
#undef min
|
||||
#undef max
|
||||
#define strdup _strdup
|
||||
#define strcasecmp _stricmp
|
||||
#define strncasecmp _strnicmp
|
||||
#endif // XE_PLATFORM_WIN32
|
||||
|
||||
#if XE_COMPILER_MSVC
|
||||
#include <intrin.h>
|
||||
#else
|
||||
#include <x86intrin.h>
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
namespace xe {
|
||||
|
||||
#if XE_PLATFORM_WIN32
|
||||
const char path_separator = '\\';
|
||||
const size_t max_path = _MAX_PATH;
|
||||
#else
|
||||
const char path_separator = '/';
|
||||
const size_t max_path = 1024; // PATH_MAX
|
||||
#endif // XE_PLATFORM_WIN32
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_PLATFORM_H_
|
||||
43
src/xenia/base/reset_scope.h
Normal file
43
src/xenia/base/reset_scope.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_RESET_SCOPE_H_
|
||||
#define XENIA_BASE_RESET_SCOPE_H_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace xe {
|
||||
|
||||
template <typename T>
|
||||
class ResetScope {
|
||||
public:
|
||||
ResetScope(T* value) : value_(value) {}
|
||||
~ResetScope() {
|
||||
if (value_) {
|
||||
value_->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T* value_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline ResetScope<T> make_reset_scope(T* value) {
|
||||
return ResetScope<T>(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline ResetScope<T> make_reset_scope(const std::unique_ptr<T>& value) {
|
||||
return ResetScope<T>(value.get());
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_RESET_SCOPE_H_
|
||||
65
src/xenia/base/sources.gypi
Normal file
65
src/xenia/base/sources.gypi
Normal file
@@ -0,0 +1,65 @@
|
||||
# Copyright 2014 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'arena.cc',
|
||||
'arena.h',
|
||||
'assert.h',
|
||||
'atomic.h',
|
||||
'byte_order.h',
|
||||
'debugging.h',
|
||||
'delegate.h',
|
||||
'cxx_compat.h',
|
||||
'fs.h',
|
||||
'fs.cc',
|
||||
'logging.cc',
|
||||
'logging.h',
|
||||
'main.h',
|
||||
'mapped_memory.h',
|
||||
'math.cc',
|
||||
'math.h',
|
||||
'memory_generic.cc',
|
||||
'memory.h',
|
||||
'platform.h',
|
||||
'reset_scope.h',
|
||||
'string.cc',
|
||||
'string.h',
|
||||
'string_buffer.cc',
|
||||
'string_buffer.h',
|
||||
'threading.cc',
|
||||
'threading.h',
|
||||
'type_pool.h',
|
||||
'vec128.h',
|
||||
],
|
||||
|
||||
'conditions': [
|
||||
['OS == "mac" or OS == "linux"', {
|
||||
'sources': [
|
||||
'main_posix.cc',
|
||||
'mapped_memory_posix.cc',
|
||||
],
|
||||
}],
|
||||
['OS == "linux"', {
|
||||
'sources': [
|
||||
'threading_posix.cc',
|
||||
],
|
||||
}],
|
||||
['OS == "mac"', {
|
||||
'sources': [
|
||||
'debugging_mac.cc',
|
||||
'threading_mac.cc',
|
||||
],
|
||||
}],
|
||||
['OS == "win"', {
|
||||
'sources': [
|
||||
'debugging_win.cc',
|
||||
'fs_win.cc',
|
||||
'main_win.cc',
|
||||
'mapped_memory_win.cc',
|
||||
'threading_win.cc',
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
||||
'includes': [
|
||||
],
|
||||
}
|
||||
169
src/xenia/base/string.cc
Normal file
169
src/xenia/base/string.cc
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/string.h"
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
|
||||
namespace xe {
|
||||
|
||||
std::string to_string(const std::wstring& source) {
|
||||
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
return converter.to_bytes(source);
|
||||
}
|
||||
|
||||
std::wstring to_wstring(const std::string& source) {
|
||||
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
return converter.from_bytes(source);
|
||||
}
|
||||
|
||||
std::string::size_type find_first_of_case(const std::string& target,
|
||||
const std::string& search) {
|
||||
const char* str = target.c_str();
|
||||
while (*str) {
|
||||
if (!strncasecmp(str, search.c_str(), search.size())) {
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
if (*str) {
|
||||
return str - target.c_str();
|
||||
} else {
|
||||
return std::string::npos;
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring to_absolute_path(const std::wstring& path) {
|
||||
#if XE_PLATFORM_WIN32
|
||||
wchar_t buffer[xe::max_path];
|
||||
_wfullpath(buffer, path.c_str(), sizeof(buffer) / sizeof(wchar_t));
|
||||
return buffer;
|
||||
#else
|
||||
char buffer[xe::max_path];
|
||||
realpath(xe::to_string(path).c_str(), buffer);
|
||||
return xe::to_wstring(buffer);
|
||||
#endif // XE_PLATFORM_WIN32
|
||||
}
|
||||
|
||||
std::vector<std::string> split_path(const std::string& path) {
|
||||
std::vector<std::string> parts;
|
||||
size_t n = 0;
|
||||
size_t last = 0;
|
||||
while ((n = path.find_first_of("\\/", last)) != path.npos) {
|
||||
if (last != n) {
|
||||
parts.push_back(path.substr(last, n - last));
|
||||
}
|
||||
last = n + 1;
|
||||
}
|
||||
if (last != path.size()) {
|
||||
parts.push_back(path.substr(last));
|
||||
}
|
||||
return parts;
|
||||
}
|
||||
|
||||
std::wstring join_paths(const std::wstring& left, const std::wstring& right,
|
||||
wchar_t sep) {
|
||||
if (!left.size()) {
|
||||
return right;
|
||||
} else if (!right.size()) {
|
||||
return left;
|
||||
}
|
||||
if (left[left.size() - 1] == sep) {
|
||||
return left + right;
|
||||
} else {
|
||||
return left + sep + right;
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring fix_path_separators(const std::wstring& source, wchar_t new_sep) {
|
||||
// Swap all separators to new_sep.
|
||||
wchar_t old_sep = new_sep == '\\' ? '/' : '\\';
|
||||
std::wstring::size_type pos = 0;
|
||||
std::wstring dest = source;
|
||||
while ((pos = source.find_first_of(old_sep, pos)) != std::wstring::npos) {
|
||||
dest[pos] = new_sep;
|
||||
++pos;
|
||||
}
|
||||
// Replace redundant separators.
|
||||
pos = 0;
|
||||
while ((pos = dest.find_first_of(new_sep, pos)) != std::wstring::npos) {
|
||||
if (pos < dest.size() - 1) {
|
||||
if (dest[pos + 1] == new_sep) {
|
||||
dest.erase(pos + 1, 1);
|
||||
}
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
std::string fix_path_separators(const std::string& source, char new_sep) {
|
||||
// Swap all separators to new_sep.
|
||||
char old_sep = new_sep == '\\' ? '/' : '\\';
|
||||
std::string::size_type pos = 0;
|
||||
std::string dest = source;
|
||||
while ((pos = source.find_first_of(old_sep, pos)) != std::string::npos) {
|
||||
dest[pos] = new_sep;
|
||||
++pos;
|
||||
}
|
||||
// Replace redundant separators.
|
||||
pos = 0;
|
||||
while ((pos = dest.find_first_of(new_sep, pos)) != std::string::npos) {
|
||||
if (pos < dest.size() - 1) {
|
||||
if (dest[pos + 1] == new_sep) {
|
||||
dest.erase(pos + 1, 1);
|
||||
}
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
std::string find_name_from_path(const std::string& path) {
|
||||
std::string name(path);
|
||||
if (!path.empty()) {
|
||||
std::string::size_type from(std::string::npos);
|
||||
if (path.back() == '\\') {
|
||||
from = path.size() - 2;
|
||||
}
|
||||
auto pos(path.find_last_of('\\', from));
|
||||
if (pos != std::string::npos) {
|
||||
if (from == std::string::npos) {
|
||||
name = path.substr(pos + 1);
|
||||
} else {
|
||||
auto len(from - pos);
|
||||
name = path.substr(pos + 1, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
std::wstring find_name_from_path(const std::wstring& path) {
|
||||
std::wstring name(path);
|
||||
if (!path.empty()) {
|
||||
std::wstring::size_type from(std::wstring::npos);
|
||||
if (path.back() == '\\') {
|
||||
from = path.size() - 2;
|
||||
}
|
||||
auto pos(path.find_last_of('\\', from));
|
||||
if (pos != std::wstring::npos) {
|
||||
if (from == std::wstring::npos) {
|
||||
name = path.substr(pos + 1);
|
||||
} else {
|
||||
auto len(from - pos);
|
||||
name = path.substr(pos + 1, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
51
src/xenia/base/string.h
Normal file
51
src/xenia/base/string.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_STRING_H_
|
||||
#define XENIA_BASE_STRING_H_
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
std::string to_string(const std::wstring& source);
|
||||
std::wstring to_wstring(const std::string& source);
|
||||
|
||||
// find_first_of string, case insensitive.
|
||||
std::string::size_type find_first_of_case(const std::string& target,
|
||||
const std::string& search);
|
||||
|
||||
// Converts the given path to an absolute path based on cwd.
|
||||
std::wstring to_absolute_path(const std::wstring& path);
|
||||
|
||||
// Splits the given path on any valid path separator and returns all parts.
|
||||
std::vector<std::string> split_path(const std::string& path);
|
||||
|
||||
// Joins two path segments with the given separator.
|
||||
std::wstring join_paths(const std::wstring& left, const std::wstring& right,
|
||||
wchar_t sep = xe::path_separator);
|
||||
|
||||
// Replaces all path separators with the given value and removes redundant
|
||||
// separators.
|
||||
std::wstring fix_path_separators(const std::wstring& source,
|
||||
wchar_t new_sep = xe::path_separator);
|
||||
std::string fix_path_separators(const std::string& source,
|
||||
char new_sep = xe::path_separator);
|
||||
|
||||
// Find the top directory name or filename from a path
|
||||
std::string find_name_from_path(const std::string& path);
|
||||
std::wstring find_name_from_path(const std::wstring& path);
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_STRING_H_
|
||||
71
src/xenia/base/string_buffer.cc
Normal file
71
src/xenia/base/string_buffer.cc
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/string_buffer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
|
||||
namespace xe {
|
||||
|
||||
StringBuffer::StringBuffer(size_t initial_capacity) {
|
||||
buffer_.reserve(std::max(initial_capacity, static_cast<size_t>(1024)));
|
||||
}
|
||||
|
||||
StringBuffer::~StringBuffer() = default;
|
||||
|
||||
void StringBuffer::Reset() { buffer_.resize(0); }
|
||||
|
||||
void StringBuffer::Grow(size_t additional_length) {
|
||||
size_t old_capacity = buffer_.capacity();
|
||||
if (buffer_.size() + additional_length <= old_capacity) {
|
||||
return;
|
||||
}
|
||||
size_t new_capacity =
|
||||
std::max(buffer_.size() + additional_length, old_capacity * 2);
|
||||
buffer_.reserve(new_capacity);
|
||||
}
|
||||
|
||||
void StringBuffer::Append(const std::string& value) {
|
||||
AppendBytes(reinterpret_cast<const uint8_t*>(value.data()), value.size());
|
||||
}
|
||||
|
||||
void StringBuffer::Append(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
AppendVarargs(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void StringBuffer::AppendVarargs(const char* format, va_list args) {
|
||||
int length = vsnprintf(nullptr, 0, format, args);
|
||||
auto offset = buffer_.size();
|
||||
Grow(length + 1);
|
||||
buffer_.resize(buffer_.size() + length);
|
||||
vsnprintf(buffer_.data() + offset, buffer_.capacity(), format, args);
|
||||
buffer_[buffer_.size()] = 0;
|
||||
}
|
||||
|
||||
void StringBuffer::AppendBytes(const uint8_t* buffer, size_t length) {
|
||||
auto offset = buffer_.size();
|
||||
Grow(length + 1);
|
||||
buffer_.resize(buffer_.size() + length);
|
||||
memcpy(buffer_.data() + offset, buffer, length);
|
||||
buffer_[buffer_.size()] = 0;
|
||||
}
|
||||
|
||||
const char* StringBuffer::GetString() const { return buffer_.data(); }
|
||||
|
||||
std::string StringBuffer::to_string() {
|
||||
return std::string(buffer_.data(), buffer_.size());
|
||||
}
|
||||
|
||||
char* StringBuffer::ToString() { return strdup(buffer_.data()); }
|
||||
|
||||
} // namespace xe
|
||||
46
src/xenia/base/string_buffer.h
Normal file
46
src/xenia/base/string_buffer.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_STRING_BUFFER_H_
|
||||
#define XENIA_BASE_STRING_BUFFER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace xe {
|
||||
|
||||
class StringBuffer {
|
||||
public:
|
||||
StringBuffer(size_t initial_capacity = 0);
|
||||
~StringBuffer();
|
||||
|
||||
size_t length() const { return buffer_.size(); }
|
||||
|
||||
void Reset();
|
||||
|
||||
void Append(const std::string& value);
|
||||
void Append(const char* format, ...);
|
||||
void AppendVarargs(const char* format, va_list args);
|
||||
void AppendBytes(const uint8_t* buffer, size_t length);
|
||||
|
||||
const char* GetString() const;
|
||||
std::string to_string();
|
||||
char* ToString();
|
||||
char* EncodeBase64();
|
||||
|
||||
private:
|
||||
void Grow(size_t additional_length);
|
||||
|
||||
std::vector<char> buffer_;
|
||||
};
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_STRING_BUFFER_H_
|
||||
18
src/xenia/base/threading.cc
Normal file
18
src/xenia/base/threading.cc
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/threading.h"
|
||||
|
||||
namespace xe {
|
||||
namespace threading {
|
||||
|
||||
//
|
||||
|
||||
} // namespace threading
|
||||
} // namespace xe
|
||||
73
src/xenia/base/threading.h
Normal file
73
src/xenia/base/threading.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_THREADING_H_
|
||||
#define XENIA_BASE_THREADING_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
namespace xe {
|
||||
namespace threading {
|
||||
|
||||
class Fence {
|
||||
public:
|
||||
Fence() : signaled_(false) {}
|
||||
void Signal() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
signaled_.store(true);
|
||||
cond_.notify_all();
|
||||
}
|
||||
void Wait() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
while (!signaled_.load()) {
|
||||
cond_.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cond_;
|
||||
std::atomic<bool> signaled_;
|
||||
};
|
||||
|
||||
// Gets the current high-performance tick count.
|
||||
uint64_t ticks();
|
||||
uint64_t ticks_per_second();
|
||||
|
||||
// TODO(benvanik): processor info API.
|
||||
|
||||
// Gets a stable thread-specific ID, but may not be. Use for informative
|
||||
// purposes only.
|
||||
uint32_t current_thread_id();
|
||||
|
||||
// Sets the current thread name.
|
||||
void set_name(const std::string& name);
|
||||
// Sets the target thread name.
|
||||
void set_name(std::thread::native_handle_type handle, const std::string& name);
|
||||
|
||||
// Yields the current thread to the scheduler. Maybe.
|
||||
void MaybeYield();
|
||||
|
||||
// Sleeps the current thread for at least as long as the given duration.
|
||||
void Sleep(std::chrono::microseconds duration);
|
||||
template <typename Rep, typename Period>
|
||||
void Sleep(std::chrono::duration<Rep, Period> duration) {
|
||||
Sleep(std::chrono::duration_cast<std::chrono::microseconds>(duration));
|
||||
}
|
||||
|
||||
} // namespace threading
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_THREADING_H_
|
||||
42
src/xenia/base/threading_mac.cc
Normal file
42
src/xenia/base/threading_mac.cc
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/threading.h"
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace xe {
|
||||
namespace threading {
|
||||
|
||||
uint64_t ticks() { return mach_absolute_time(); }
|
||||
|
||||
uint32_t current_thread_id() {
|
||||
mach_port_t tid = pthread_mach_thread_np(pthread_self());
|
||||
return static_cast<uint32_t>(tid);
|
||||
}
|
||||
|
||||
void set_name(const std::string& name) { pthread_setname_np(name.c_str()); }
|
||||
|
||||
void set_name(std::thread::native_handle_type handle, const std::string& name) {
|
||||
// ?
|
||||
}
|
||||
|
||||
void MaybeYield() { pthread_yield_np(); }
|
||||
|
||||
void Sleep(std::chrono::microseconds duration) {
|
||||
timespec rqtp = {duration.count() / 1000000, duration.count() % 1000};
|
||||
nanosleep(&rqtp, nullptr);
|
||||
// TODO(benvanik): spin while rmtp >0?
|
||||
}
|
||||
|
||||
} // namespace threading
|
||||
} // namespace xe
|
||||
42
src/xenia/base/threading_posix.cc
Normal file
42
src/xenia/base/threading_posix.cc
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/threading.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace xe {
|
||||
namespace threading {
|
||||
|
||||
// uint64_t ticks() { return mach_absolute_time(); }
|
||||
|
||||
// uint32_t current_thread_id() {
|
||||
// mach_port_t tid = pthread_mach_thread_np(pthread_self());
|
||||
// return static_cast<uint32_t>(tid);
|
||||
// }
|
||||
|
||||
void set_name(const std::string& name) {
|
||||
pthread_setname_np(pthread_self(), name.c_str());
|
||||
}
|
||||
|
||||
void set_name(std::thread::native_handle_type handle, const std::string& name) {
|
||||
pthread_setname_np(pthread_self(), name.c_str());
|
||||
}
|
||||
|
||||
void MaybeYield() { pthread_yield_np(); }
|
||||
|
||||
void Sleep(std::chrono::microseconds duration) {
|
||||
timespec rqtp = {duration.count() / 1000000, duration.count() % 1000};
|
||||
nanosleep(&rqtp, nullptr);
|
||||
// TODO(benvanik): spin while rmtp >0?
|
||||
}
|
||||
|
||||
} // namespace threading
|
||||
} // namespace xe
|
||||
83
src/xenia/base/threading_win.cc
Normal file
83
src/xenia/base/threading_win.cc
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/threading.h"
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
namespace xe {
|
||||
namespace threading {
|
||||
|
||||
uint64_t ticks() {
|
||||
LARGE_INTEGER counter;
|
||||
uint64_t time = 0;
|
||||
if (QueryPerformanceCounter(&counter)) {
|
||||
time = counter.QuadPart;
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
uint64_t ticks_per_second() {
|
||||
static LARGE_INTEGER freq = {0};
|
||||
if (!freq.QuadPart) {
|
||||
QueryPerformanceFrequency(&freq);
|
||||
}
|
||||
return freq.QuadPart;
|
||||
}
|
||||
|
||||
uint32_t current_thread_id() {
|
||||
return static_cast<uint32_t>(GetCurrentThreadId());
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||
#pragma pack(push, 8)
|
||||
struct THREADNAME_INFO {
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
void set_name(DWORD thread_id, const std::string& name) {
|
||||
if (!IsDebuggerPresent()) {
|
||||
return;
|
||||
}
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = name.c_str();
|
||||
info.dwThreadID = thread_id;
|
||||
info.dwFlags = 0;
|
||||
__try {
|
||||
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR),
|
||||
reinterpret_cast<ULONG_PTR*>(&info));
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER) {}
|
||||
}
|
||||
|
||||
void set_name(const std::string& name) {
|
||||
set_name(static_cast<DWORD>(-1), name);
|
||||
}
|
||||
|
||||
void set_name(std::thread::native_handle_type handle, const std::string& name) {
|
||||
set_name(GetThreadId(handle), name);
|
||||
}
|
||||
|
||||
void MaybeYield() { SwitchToThread(); }
|
||||
|
||||
void Sleep(std::chrono::microseconds duration) {
|
||||
if (duration.count() < 100) {
|
||||
SwitchToThread();
|
||||
} else {
|
||||
::Sleep(static_cast<DWORD>(duration.count() / 1000));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace threading
|
||||
} // namespace xe
|
||||
59
src/xenia/base/type_pool.h
Normal file
59
src/xenia/base/type_pool.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_TYPE_POOL_H_
|
||||
#define XENIA_BASE_TYPE_POOL_H_
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace xe {
|
||||
|
||||
template <class T, typename A>
|
||||
class TypePool {
|
||||
public:
|
||||
~TypePool() { Reset(); }
|
||||
|
||||
void Reset() {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
for (auto it = list_.begin(); it != list_.end(); ++it) {
|
||||
T* value = *it;
|
||||
delete value;
|
||||
}
|
||||
list_.clear();
|
||||
}
|
||||
|
||||
T* Allocate(A arg0) {
|
||||
T* result = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
if (list_.size()) {
|
||||
result = list_.back();
|
||||
list_.pop_back();
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
result = new T(arg0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Release(T* value) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
list_.push_back(value);
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex lock_;
|
||||
std::vector<T*> list_;
|
||||
};
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_TYPE_POOL_H_
|
||||
199
src/xenia/base/vec128.h
Normal file
199
src/xenia/base/vec128.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BASE_VEC128_H_
|
||||
#define XENIA_BASE_VEC128_H_
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
// The first rule of vector programming is to only rely on exact positions
|
||||
// when absolutely required - prefer dumb loops to exact offsets.
|
||||
// Vectors in memory are laid out as in AVX registers on little endian
|
||||
// machines. Note that little endian is dumb, so the byte at index 0 in
|
||||
// the vector is is really byte 15 (or the high byte of short 7 or int 3).
|
||||
// Because of this, all byte access should be via the accessors instead of
|
||||
// the direct array.
|
||||
|
||||
// Altivec big endian layout: AVX little endian layout:
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 0 | int16 0 | int8 0 | | int32 3 | int16 7 | int8 15 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 1 | | | | int8 14 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 1 | int8 2 | | | int16 6 | int8 13 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 3 | | | | int8 12 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 1 | int16 2 | int8 4 | | int32 2 | int16 5 | int8 11 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 5 | | | | int8 10 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 3 | int8 6 | | | int16 4 | int8 9 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 7 | | | | int8 8 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 2 | int16 4 | int8 8 | | int32 1 | int16 3 | int8 7 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 9 | | | | int8 6 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 5 | int8 10 | | | int16 2 | int8 5 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 11 | | | | int8 4 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 3 | int16 6 | int8 12 | | int32 0 | int16 1 | int8 3 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 13 | | | | int8 2 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 7 | int8 14 | | | int16 0 | int8 1 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 15 | | | | int8 0 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
//
|
||||
// Logical order:
|
||||
// +-----+-----+-----+-----+ +-----+-----+-----+-----+
|
||||
// | X | Y | Z | W | | W | Z | Y | X |
|
||||
// +-----+-----+-----+-----+ +-----+-----+-----+-----+
|
||||
//
|
||||
// Mapping indices is easy:
|
||||
// int32[i ^ 0x3]
|
||||
// int16[i ^ 0x7]
|
||||
// int8[i ^ 0xF]
|
||||
typedef struct alignas(16) vec128_s {
|
||||
union {
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
struct {
|
||||
int32_t ix;
|
||||
int32_t iy;
|
||||
int32_t iz;
|
||||
int32_t iw;
|
||||
};
|
||||
struct {
|
||||
uint32_t ux;
|
||||
uint32_t uy;
|
||||
uint32_t uz;
|
||||
uint32_t uw;
|
||||
};
|
||||
float f32[4];
|
||||
int8_t i8[16];
|
||||
uint8_t u8[16];
|
||||
int16_t i16[8];
|
||||
uint16_t u16[8];
|
||||
int32_t i32[4];
|
||||
uint32_t u32[4];
|
||||
int64_t i64[2];
|
||||
uint64_t u64[2];
|
||||
struct {
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
};
|
||||
};
|
||||
|
||||
bool operator==(const vec128_s& b) const {
|
||||
return low == b.low && high == b.high;
|
||||
}
|
||||
bool operator!=(const vec128_s& b) const {
|
||||
return low != b.low || high != b.high;
|
||||
}
|
||||
} vec128_t;
|
||||
|
||||
static inline vec128_t vec128i(uint32_t src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 4; ++i) {
|
||||
v.u32[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128i(uint32_t x, uint32_t y, uint32_t z, uint32_t w) {
|
||||
vec128_t v;
|
||||
v.u32[0] = x;
|
||||
v.u32[1] = y;
|
||||
v.u32[2] = z;
|
||||
v.u32[3] = w;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128f(float src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 4; ++i) {
|
||||
v.f32[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128f(float x, float y, float z, float w) {
|
||||
vec128_t v;
|
||||
v.f32[0] = x;
|
||||
v.f32[1] = y;
|
||||
v.f32[2] = z;
|
||||
v.f32[3] = w;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128s(uint16_t src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 8; ++i) {
|
||||
v.u16[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128s(uint16_t x0, uint16_t x1, uint16_t y0,
|
||||
uint16_t y1, uint16_t z0, uint16_t z1,
|
||||
uint16_t w0, uint16_t w1) {
|
||||
vec128_t v;
|
||||
v.u16[0] = x1;
|
||||
v.u16[1] = x0;
|
||||
v.u16[2] = y1;
|
||||
v.u16[3] = y0;
|
||||
v.u16[4] = z1;
|
||||
v.u16[5] = z0;
|
||||
v.u16[6] = w1;
|
||||
v.u16[7] = w0;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128b(uint8_t src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 16; ++i) {
|
||||
v.u8[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128b(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3,
|
||||
uint8_t y0, uint8_t y1, uint8_t y2, uint8_t y3,
|
||||
uint8_t z0, uint8_t z1, uint8_t z2, uint8_t z3,
|
||||
uint8_t w0, uint8_t w1, uint8_t w2, uint8_t w3) {
|
||||
vec128_t v;
|
||||
v.u8[0] = x3;
|
||||
v.u8[1] = x2;
|
||||
v.u8[2] = x1;
|
||||
v.u8[3] = x0;
|
||||
v.u8[4] = y3;
|
||||
v.u8[5] = y2;
|
||||
v.u8[6] = y1;
|
||||
v.u8[7] = y0;
|
||||
v.u8[8] = z3;
|
||||
v.u8[9] = z2;
|
||||
v.u8[10] = z1;
|
||||
v.u8[11] = z0;
|
||||
v.u8[12] = w3;
|
||||
v.u8[13] = w2;
|
||||
v.u8[14] = w1;
|
||||
v.u8[15] = w0;
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_VEC128_H_
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
#include "xenia/cpu/backend/x64/x64_assembler.h"
|
||||
|
||||
#include "xenia/base/reset_scope.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
#include "xenia/cpu/backend/x64/x64_function.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/hir/label.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
#include "poly/reset_scope.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace BE {
|
||||
@@ -65,7 +65,7 @@ int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Reset when we leave.
|
||||
poly::make_reset_scope(this);
|
||||
xe::make_reset_scope(this);
|
||||
|
||||
// Lower HIR -> x64.
|
||||
void* machine_code = 0;
|
||||
@@ -95,7 +95,7 @@ int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
}
|
||||
|
||||
void X64Assembler::DumpMachineCode(DebugInfo* debug_info, void* machine_code,
|
||||
size_t code_size, poly::StringBuffer* str) {
|
||||
size_t code_size, StringBuffer* str) {
|
||||
BE::DISASM disasm = {0};
|
||||
disasm.Archi = 64;
|
||||
disasm.Options = BE::Tabulation + BE::MasmSyntax + BE::PrefixedNumeral;
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "xenia/base/string_buffer.h"
|
||||
#include "xenia/cpu/backend/assembler.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -39,14 +39,14 @@ class X64Assembler : public Assembler {
|
||||
|
||||
private:
|
||||
void DumpMachineCode(DebugInfo* debug_info, void* machine_code,
|
||||
size_t code_size, poly::StringBuffer* str);
|
||||
size_t code_size, StringBuffer* str);
|
||||
|
||||
private:
|
||||
X64Backend* x64_backend_;
|
||||
std::unique_ptr<X64Emitter> emitter_;
|
||||
std::unique_ptr<XbyakAllocator> allocator_;
|
||||
|
||||
poly::StringBuffer string_buffer_;
|
||||
StringBuffer string_buffer_;
|
||||
};
|
||||
|
||||
} // namespace x64
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/math.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/math.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -51,7 +51,7 @@ void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||
size_t stack_size) {
|
||||
// Always move the code to land on 16b alignment. We do this by rounding up
|
||||
// to 16b so that all offsets are aligned.
|
||||
code_size = poly::round_up(code_size, 16);
|
||||
code_size = xe::round_up(code_size, 16);
|
||||
|
||||
lock_.lock();
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/math.h"
|
||||
#include "xenia/logging.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -64,11 +64,11 @@ void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||
size_t alloc_size = code_size;
|
||||
|
||||
// Add unwind info into the allocation size. Keep things 16b aligned.
|
||||
alloc_size += poly::round_up(X64CodeChunk::UNWIND_INFO_SIZE, 16);
|
||||
alloc_size += xe::round_up(X64CodeChunk::UNWIND_INFO_SIZE, 16);
|
||||
|
||||
// Always move the code to land on 16b alignment. We do this by rounding up
|
||||
// to 16b so that all offsets are aligned.
|
||||
alloc_size = poly::round_up(alloc_size, 16);
|
||||
alloc_size = xe::round_up(alloc_size, 16);
|
||||
|
||||
lock_.lock();
|
||||
|
||||
@@ -108,7 +108,7 @@ X64CodeChunk::X64CodeChunk(size_t chunk_size)
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
|
||||
fn_table_capacity =
|
||||
static_cast<uint32_t>(poly::round_up(capacity / ESTIMATED_FN_SIZE, 16));
|
||||
static_cast<uint32_t>(xe::round_up(capacity / ESTIMATED_FN_SIZE, 16));
|
||||
size_t table_size = fn_table_capacity * sizeof(RUNTIME_FUNCTION);
|
||||
fn_table = (RUNTIME_FUNCTION*)malloc(table_size);
|
||||
fn_table_count = 0;
|
||||
|
||||
@@ -9,21 +9,21 @@
|
||||
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/math.h"
|
||||
#include "poly/vec128.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/vec128.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||
#include "xenia/cpu/backend/x64/x64_function.h"
|
||||
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
||||
#include "xenia/cpu/backend/x64/x64_thunk_emitter.h"
|
||||
#include "xenia/cpu/cpu-private.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/debug_info.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
#include "xenia/cpu/symbol_info.h"
|
||||
#include "xenia/cpu/thread_state.h"
|
||||
#include "xenia/logging.h"
|
||||
#include "xenia/profiling.h"
|
||||
#include "xdb/protocol.h"
|
||||
|
||||
@@ -36,10 +36,6 @@ namespace x64 {
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu;
|
||||
|
||||
using poly::vec128b;
|
||||
using poly::vec128f;
|
||||
using poly::vec128i;
|
||||
|
||||
using namespace Xbyak;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::Instr;
|
||||
@@ -132,13 +128,13 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||
auto slot = *it;
|
||||
size_t type_size = GetTypeSize(slot->type);
|
||||
// Align to natural size.
|
||||
stack_offset = poly::align(stack_offset, type_size);
|
||||
stack_offset = xe::align(stack_offset, type_size);
|
||||
slot->set_constant((uint32_t)stack_offset);
|
||||
stack_offset += type_size;
|
||||
}
|
||||
// Ensure 16b alignment.
|
||||
stack_offset -= StackLayout::GUEST_STACK_SIZE;
|
||||
stack_offset = poly::align(stack_offset, static_cast<size_t>(16));
|
||||
stack_offset = xe::align(stack_offset, static_cast<size_t>(16));
|
||||
|
||||
// Function prolog.
|
||||
// Must be 16b aligned.
|
||||
@@ -536,8 +532,8 @@ uint64_t ResolveFunctionAddress(void* raw_context, uint32_t target_address) {
|
||||
Asm* table_slot = reinterpret_cast<Asm*>(table_start);
|
||||
bool wrote_ic = false;
|
||||
for (int i = 0; i < kICSlotCount; ++i) {
|
||||
if (poly::atomic_cas(kICSlotInvalidTargetAddress, addr,
|
||||
&table_slot->target_constant)) {
|
||||
if (xe::atomic_cas(kICSlotInvalidTargetAddress, addr,
|
||||
&table_slot->target_constant)) {
|
||||
// Got slot! Just write the compare and we're done.
|
||||
table_slot->address_constant = static_cast<uint32_t>(target_address);
|
||||
wrote_ic = true;
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
#ifndef XENIA_BACKEND_X64_X64_EMITTER_H_
|
||||
#define XENIA_BACKEND_X64_X64_EMITTER_H_
|
||||
|
||||
#include "xenia/cpu/hir/value.h"
|
||||
#include "poly/arena.h"
|
||||
#include "third_party/xbyak/xbyak/xbyak.h"
|
||||
|
||||
#include "xenia/base/arena.h"
|
||||
#include "xenia/cpu/hir/value.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
class DebugInfo;
|
||||
@@ -32,8 +33,6 @@ namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
using vec128_t = poly::vec128_t;
|
||||
|
||||
class X64Backend;
|
||||
class X64CodeCache;
|
||||
|
||||
@@ -196,7 +195,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
||||
hir::Instr* current_instr_;
|
||||
|
||||
size_t source_map_count_;
|
||||
poly::Arena source_map_arena_;
|
||||
Arena source_map_arena_;
|
||||
|
||||
size_t stack_size_;
|
||||
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
|
||||
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/threading.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
#include "xenia/cpu/backend/x64/x64_tracers.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
#include "xenia/logging.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -43,8 +43,6 @@ using namespace Xbyak;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu;
|
||||
|
||||
using poly::vec128b;
|
||||
|
||||
typedef bool (*SequenceSelectFn)(X64Emitter&, const Instr*, const Instr**);
|
||||
std::unordered_multimap<uint32_t, SequenceSelectFn> sequence_table;
|
||||
|
||||
@@ -1022,7 +1020,7 @@ EMITTER(LOAD_VECTOR_SHL_I8, MATCH(I<OPCODE_LOAD_VECTOR_SHL, V128<>, I8<>>)) {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
if (i.src1.is_constant) {
|
||||
auto sh = i.src1.constant();
|
||||
assert_true(sh < poly::countof(lvsl_table));
|
||||
assert_true(sh < xe::countof(lvsl_table));
|
||||
e.mov(e.rax, (uintptr_t)&lvsl_table[sh]);
|
||||
e.vmovaps(i.dest, e.ptr[e.rax]);
|
||||
} else {
|
||||
@@ -1066,7 +1064,7 @@ EMITTER(LOAD_VECTOR_SHR_I8, MATCH(I<OPCODE_LOAD_VECTOR_SHR, V128<>, I8<>>)) {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
if (i.src1.is_constant) {
|
||||
auto sh = i.src1.constant();
|
||||
assert_true(sh < poly::countof(lvsr_table));
|
||||
assert_true(sh < xe::countof(lvsr_table));
|
||||
e.mov(e.rax, (uintptr_t)&lvsr_table[sh]);
|
||||
e.vmovaps(i.dest, e.ptr[e.rax]);
|
||||
} else {
|
||||
@@ -1095,7 +1093,7 @@ EMITTER(LOAD_CLOCK, MATCH(I<OPCODE_LOAD_CLOCK, I64<>>)) {
|
||||
e.mov(i.dest, e.rax);
|
||||
}
|
||||
static uint64_t LoadClock(void* raw_context) {
|
||||
return poly::threading::ticks();
|
||||
return xe::threading::ticks();
|
||||
}
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(
|
||||
@@ -4697,7 +4695,7 @@ EMITTER(VECTOR_ROTATE_LEFT_V128, MATCH(I<OPCODE_VECTOR_ROTATE_LEFT, V128<>, V128
|
||||
_mm_store_si128(reinterpret_cast<__m128i*>(value), src1);
|
||||
_mm_store_si128(reinterpret_cast<__m128i*>(shamt), src2);
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
value[i] = poly::rotate_left<uint8_t>(value[i], shamt[i] & 0x7);
|
||||
value[i] = xe::rotate_left<uint8_t>(value[i], shamt[i] & 0x7);
|
||||
}
|
||||
return _mm_load_si128(reinterpret_cast<__m128i*>(value));
|
||||
}
|
||||
@@ -4707,7 +4705,7 @@ EMITTER(VECTOR_ROTATE_LEFT_V128, MATCH(I<OPCODE_VECTOR_ROTATE_LEFT, V128<>, V128
|
||||
_mm_store_si128(reinterpret_cast<__m128i*>(value), src1);
|
||||
_mm_store_si128(reinterpret_cast<__m128i*>(shamt), src2);
|
||||
for (size_t i = 0; i < 8; ++i) {
|
||||
value[i] = poly::rotate_left<uint16_t>(value[i], shamt[i] & 0xF);
|
||||
value[i] = xe::rotate_left<uint16_t>(value[i], shamt[i] & 0xF);
|
||||
}
|
||||
return _mm_load_si128(reinterpret_cast<__m128i*>(value));
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/backend/x64/x64_tracers.h"
|
||||
|
||||
#include "poly/vec128.h"
|
||||
#include "xenia/base/vec128.h"
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
#include "xenia/cpu/thread_state.h"
|
||||
@@ -71,23 +71,22 @@ void TraceContextLoadI64(void* raw_context, uint64_t offset, uint64_t value) {
|
||||
}
|
||||
void TraceContextLoadF32(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("%e (%X) = ctx f32 +%llu\n", poly::m128_f32<0>(value),
|
||||
poly::m128_i32<0>(value), offset);
|
||||
DPRINT("%e (%X) = ctx f32 +%llu\n", xe::m128_f32<0>(value),
|
||||
xe::m128_i32<0>(value), offset);
|
||||
}
|
||||
void TraceContextLoadF64(void* raw_context, uint64_t offset,
|
||||
const double* value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
auto v = _mm_loadu_pd(value);
|
||||
DPRINT("%le (%llX) = ctx f64 +%llu\n", poly::m128_f64<0>(v),
|
||||
poly::m128_i64<0>(v), offset);
|
||||
DPRINT("%le (%llX) = ctx f64 +%llu\n", xe::m128_f64<0>(v), xe::m128_i64<0>(v),
|
||||
offset);
|
||||
}
|
||||
void TraceContextLoadV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = ctx v128 +%llu\n",
|
||||
poly::m128_f32<0>(value), poly::m128_f32<1>(value),
|
||||
poly::m128_f32<2>(value), poly::m128_f32<3>(value),
|
||||
poly::m128_i32<0>(value), poly::m128_i32<1>(value),
|
||||
poly::m128_i32<2>(value), poly::m128_i32<3>(value), offset);
|
||||
xe::m128_f32<0>(value), xe::m128_f32<1>(value), xe::m128_f32<2>(value),
|
||||
xe::m128_f32<3>(value), xe::m128_i32<0>(value), xe::m128_i32<1>(value),
|
||||
xe::m128_i32<2>(value), xe::m128_i32<3>(value), offset);
|
||||
}
|
||||
|
||||
void TraceContextStoreI8(void* raw_context, uint64_t offset, uint8_t value) {
|
||||
@@ -108,23 +107,22 @@ void TraceContextStoreI64(void* raw_context, uint64_t offset, uint64_t value) {
|
||||
}
|
||||
void TraceContextStoreF32(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("ctx f32 +%llu = %e (%X)\n", offset, poly::m128_f32<0>(value),
|
||||
poly::m128_i32<0>(value));
|
||||
DPRINT("ctx f32 +%llu = %e (%X)\n", offset, xe::m128_f32<0>(value),
|
||||
xe::m128_i32<0>(value));
|
||||
}
|
||||
void TraceContextStoreF64(void* raw_context, uint64_t offset,
|
||||
const double* value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
auto v = _mm_loadu_pd(value);
|
||||
DPRINT("ctx f64 +%llu = %le (%llX)\n", offset, poly::m128_f64<0>(v),
|
||||
poly::m128_i64<0>(v));
|
||||
DPRINT("ctx f64 +%llu = %le (%llX)\n", offset, xe::m128_f64<0>(v),
|
||||
xe::m128_i64<0>(v));
|
||||
}
|
||||
void TraceContextStoreV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("ctx v128 +%llu = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", offset,
|
||||
poly::m128_f32<0>(value), poly::m128_f32<1>(value),
|
||||
poly::m128_f32<2>(value), poly::m128_f32<3>(value),
|
||||
poly::m128_i32<0>(value), poly::m128_i32<1>(value),
|
||||
poly::m128_i32<2>(value), poly::m128_i32<3>(value));
|
||||
xe::m128_f32<0>(value), xe::m128_f32<1>(value), xe::m128_f32<2>(value),
|
||||
xe::m128_f32<3>(value), xe::m128_i32<0>(value), xe::m128_i32<1>(value),
|
||||
xe::m128_i32<2>(value), xe::m128_i32<3>(value));
|
||||
}
|
||||
|
||||
void TraceMemoryLoadI8(void* raw_context, uint32_t address, uint8_t value) {
|
||||
@@ -145,21 +143,20 @@ void TraceMemoryLoadI64(void* raw_context, uint32_t address, uint64_t value) {
|
||||
}
|
||||
void TraceMemoryLoadF32(void* raw_context, uint32_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("%e (%X) = load.f32 %.8X\n", poly::m128_f32<0>(value),
|
||||
poly::m128_i32<0>(value), address);
|
||||
DPRINT("%e (%X) = load.f32 %.8X\n", xe::m128_f32<0>(value),
|
||||
xe::m128_i32<0>(value), address);
|
||||
}
|
||||
void TraceMemoryLoadF64(void* raw_context, uint32_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("%le (%llX) = load.f64 %.8X\n", poly::m128_f64<0>(value),
|
||||
poly::m128_i64<0>(value), address);
|
||||
DPRINT("%le (%llX) = load.f64 %.8X\n", xe::m128_f64<0>(value),
|
||||
xe::m128_i64<0>(value), address);
|
||||
}
|
||||
void TraceMemoryLoadV128(void* raw_context, uint32_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = load.v128 %.8X\n",
|
||||
poly::m128_f32<0>(value), poly::m128_f32<1>(value),
|
||||
poly::m128_f32<2>(value), poly::m128_f32<3>(value),
|
||||
poly::m128_i32<0>(value), poly::m128_i32<1>(value),
|
||||
poly::m128_i32<2>(value), poly::m128_i32<3>(value), address);
|
||||
xe::m128_f32<0>(value), xe::m128_f32<1>(value), xe::m128_f32<2>(value),
|
||||
xe::m128_f32<3>(value), xe::m128_i32<0>(value), xe::m128_i32<1>(value),
|
||||
xe::m128_i32<2>(value), xe::m128_i32<3>(value), address);
|
||||
}
|
||||
|
||||
void TraceMemoryStoreI8(void* raw_context, uint32_t address, uint8_t value) {
|
||||
@@ -180,21 +177,21 @@ void TraceMemoryStoreI64(void* raw_context, uint32_t address, uint64_t value) {
|
||||
}
|
||||
void TraceMemoryStoreF32(void* raw_context, uint32_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("store.f32 %.8X = %e (%X)\n", address, poly::m128_f32<0>(value),
|
||||
poly::m128_i32<0>(value));
|
||||
DPRINT("store.f32 %.8X = %e (%X)\n", address, xe::m128_f32<0>(value),
|
||||
xe::m128_i32<0>(value));
|
||||
}
|
||||
void TraceMemoryStoreF64(void* raw_context, uint32_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("store.f64 %.8X = %le (%llX)\n", address, poly::m128_f64<0>(value),
|
||||
poly::m128_i64<0>(value));
|
||||
DPRINT("store.f64 %.8X = %le (%llX)\n", address, xe::m128_f64<0>(value),
|
||||
xe::m128_i64<0>(value));
|
||||
}
|
||||
void TraceMemoryStoreV128(void* raw_context, uint32_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("store.v128 %.8X = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n",
|
||||
address, poly::m128_f32<0>(value), poly::m128_f32<1>(value),
|
||||
poly::m128_f32<2>(value), poly::m128_f32<3>(value),
|
||||
poly::m128_i32<0>(value), poly::m128_i32<1>(value),
|
||||
poly::m128_i32<2>(value), poly::m128_i32<3>(value));
|
||||
address, xe::m128_f32<0>(value), xe::m128_f32<1>(value),
|
||||
xe::m128_f32<2>(value), xe::m128_f32<3>(value), xe::m128_i32<0>(value),
|
||||
xe::m128_i32<1>(value), xe::m128_i32<2>(value),
|
||||
xe::m128_i32<3>(value));
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/arena.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "poly/arena.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -34,7 +34,7 @@ class Compiler {
|
||||
~Compiler();
|
||||
|
||||
Runtime* runtime() const { return runtime_; }
|
||||
poly::Arena* scratch_arena() { return &scratch_arena_; }
|
||||
Arena* scratch_arena() { return &scratch_arena_; }
|
||||
|
||||
void AddPass(std::unique_ptr<CompilerPass> pass);
|
||||
|
||||
@@ -44,7 +44,7 @@ class Compiler {
|
||||
|
||||
private:
|
||||
Runtime* runtime_;
|
||||
poly::Arena scratch_arena_;
|
||||
Arena scratch_arena_;
|
||||
|
||||
std::vector<std::unique_ptr<CompilerPass>> passes_;
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@ int CompilerPass::Initialize(Compiler* compiler) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
poly::Arena* CompilerPass::scratch_arena() const {
|
||||
Arena* CompilerPass::scratch_arena() const {
|
||||
return compiler_->scratch_arena();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
#ifndef XENIA_COMPILER_COMPILER_PASS_H_
|
||||
#define XENIA_COMPILER_COMPILER_PASS_H_
|
||||
|
||||
#include "xenia/base/arena.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "poly/arena.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -35,7 +35,7 @@ class CompilerPass {
|
||||
virtual int Run(hir::HIRBuilder* builder) = 0;
|
||||
|
||||
protected:
|
||||
poly::Arena* scratch_arena() const;
|
||||
Arena* scratch_arena() const;
|
||||
|
||||
protected:
|
||||
Runtime* runtime_;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/compiler/passes/constant_propagation_pass.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/function.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef XENIA_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||
|
||||
#include "poly/platform.h"
|
||||
#include "xenia/base/platform.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
#if XE_COMPILER_MSVC
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
#include "xenia/cpu/compiler/passes/data_flow_analysis_pass.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/platform.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/platform.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/math.h"
|
||||
#include "xenia/logging.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -61,7 +61,7 @@ RegisterAllocationPass::RegisterAllocationPass(const MachineInfo* machine_info)
|
||||
}
|
||||
|
||||
RegisterAllocationPass::~RegisterAllocationPass() {
|
||||
for (size_t n = 0; n < poly::countof(usage_sets_.all_sets); n++) {
|
||||
for (size_t n = 0; n < xe::countof(usage_sets_.all_sets); n++) {
|
||||
if (!usage_sets_.all_sets[n]) {
|
||||
break;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ int RegisterAllocationPass::Run(HIRBuilder* builder) {
|
||||
void RegisterAllocationPass::DumpUsage(const char* name) {
|
||||
#if 0
|
||||
fprintf(stdout, "\n%s:\n", name);
|
||||
for (size_t i = 0; i < poly::countof(usage_sets_.all_sets); ++i) {
|
||||
for (size_t i = 0; i < xe::countof(usage_sets_.all_sets); ++i) {
|
||||
auto usage_set = usage_sets_.all_sets[i];
|
||||
if (usage_set) {
|
||||
fprintf(stdout, "set %s:\n", usage_set->set->name);
|
||||
@@ -194,7 +194,7 @@ void RegisterAllocationPass::DumpUsage(const char* name) {
|
||||
}
|
||||
|
||||
void RegisterAllocationPass::PrepareBlockState() {
|
||||
for (size_t i = 0; i < poly::countof(usage_sets_.all_sets); ++i) {
|
||||
for (size_t i = 0; i < xe::countof(usage_sets_.all_sets); ++i) {
|
||||
auto usage_set = usage_sets_.all_sets[i];
|
||||
if (usage_set) {
|
||||
usage_set->availability.set();
|
||||
@@ -205,7 +205,7 @@ void RegisterAllocationPass::PrepareBlockState() {
|
||||
}
|
||||
|
||||
void RegisterAllocationPass::AdvanceUses(Instr* instr) {
|
||||
for (size_t i = 0; i < poly::countof(usage_sets_.all_sets); ++i) {
|
||||
for (size_t i = 0; i < xe::countof(usage_sets_.all_sets); ++i) {
|
||||
auto usage_set = usage_sets_.all_sets[i];
|
||||
if (!usage_set) {
|
||||
break;
|
||||
@@ -310,7 +310,7 @@ bool RegisterAllocationPass::TryAllocateRegister(Value* value) {
|
||||
// Find the first free register, if any.
|
||||
// We have to ensure it's a valid one (in our count).
|
||||
uint32_t first_unused = 0;
|
||||
bool none_used = poly::bit_scan_forward(
|
||||
bool none_used = xe::bit_scan_forward(
|
||||
static_cast<uint32_t>(usage_set->availability.to_ulong()), &first_unused);
|
||||
if (none_used && first_unused < usage_set->count) {
|
||||
// Available! Use it!
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/compiler/passes/validation_pass.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/compiler/passes/value_reduction_pass.h"
|
||||
|
||||
#include "poly/platform.h"
|
||||
#include "xenia/base/platform.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "poly/delegate.h"
|
||||
#include "xenia/base/delegate.h"
|
||||
#include "xenia/cpu/thread_state.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -104,7 +104,7 @@ class Debugger {
|
||||
void OnBreakpointHit(ThreadState* thread_state, Breakpoint* breakpoint);
|
||||
|
||||
public:
|
||||
poly::Delegate<BreakpointHitEvent> breakpoint_hit;
|
||||
Delegate<BreakpointHitEvent> breakpoint_hit;
|
||||
|
||||
private:
|
||||
Runtime* runtime_;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/entry_table.h"
|
||||
|
||||
#include "poly/threading.h"
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -53,7 +53,7 @@ Entry::Status EntryTable::GetOrCreate(uint32_t address, Entry** out_entry) {
|
||||
do {
|
||||
lock_.unlock();
|
||||
// TODO(benvanik): sleep for less time?
|
||||
poly::threading::Sleep(std::chrono::microseconds(10));
|
||||
xe::threading::Sleep(std::chrono::microseconds(10));
|
||||
lock_.lock();
|
||||
} while (entry->status == Entry::STATUS_COMPILING);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
#include "xenia/cpu/export_resolver.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/math.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/math.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "poly/vec128.h"
|
||||
#include "xenia/base/vec128.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -25,8 +25,6 @@ namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
|
||||
using vec128_t = poly::vec128_t;
|
||||
|
||||
// Map:
|
||||
// 0-31: GPR
|
||||
// 32-63: FPR
|
||||
|
||||
@@ -9,63 +9,63 @@
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_disasm.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/math.h"
|
||||
#include "poly/string_buffer.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/string_buffer.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
|
||||
void Disasm_0(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_0(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s ???", i.type->name);
|
||||
}
|
||||
|
||||
void Disasm__(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm__(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s", i.type->name);
|
||||
}
|
||||
|
||||
void Disasm_X_FRT_FRB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_X_FRT_FRB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, f%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RT, i.X.RB);
|
||||
}
|
||||
void Disasm_A_FRT_FRB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_A_FRT_FRB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||
i.A.Rc ? "." : "", i.A.FRT, i.A.FRB);
|
||||
}
|
||||
void Disasm_A_FRT_FRA_FRB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_A_FRT_FRA_FRB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||
i.A.Rc ? "." : "", i.A.FRT, i.A.FRA, i.A.FRB);
|
||||
}
|
||||
void Disasm_A_FRT_FRA_FRB_FRC(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_A_FRT_FRA_FRB_FRC(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||
i.A.Rc ? "." : "", i.A.FRT, i.A.FRA, i.A.FRB, i.A.FRC);
|
||||
}
|
||||
void Disasm_X_RT_RA_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_X_RT_RA_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
}
|
||||
void Disasm_X_RT_RA0_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_X_RT_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||
if (i.X.RA) {
|
||||
str->Append("%-8s r%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
} else {
|
||||
str->Append("%-8s r%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||
}
|
||||
}
|
||||
void Disasm_X_FRT_RA_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_X_FRT_RA_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s f%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
}
|
||||
void Disasm_X_FRT_RA0_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_X_FRT_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||
if (i.X.RA) {
|
||||
str->Append("%-8s f%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
} else {
|
||||
str->Append("%-8s f%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||
}
|
||||
}
|
||||
void Disasm_D_RT_RA_I(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_D_RT_RA_I(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
void Disasm_D_RT_RA0_I(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_D_RT_RA0_I(InstrData& i, StringBuffer* str) {
|
||||
if (i.D.RA) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
@@ -74,11 +74,11 @@ void Disasm_D_RT_RA0_I(InstrData& i, poly::StringBuffer* str) {
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
}
|
||||
void Disasm_D_FRT_RA_I(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_D_FRT_RA_I(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
void Disasm_D_FRT_RA0_I(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_D_FRT_RA0_I(InstrData& i, StringBuffer* str) {
|
||||
if (i.D.RA) {
|
||||
str->Append("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
@@ -87,11 +87,11 @@ void Disasm_D_FRT_RA0_I(InstrData& i, poly::StringBuffer* str) {
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
}
|
||||
void Disasm_DS_RT_RA_I(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_DS_RT_RA_I(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
}
|
||||
void Disasm_DS_RT_RA0_I(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_DS_RT_RA0_I(InstrData& i, StringBuffer* str) {
|
||||
if (i.DS.RA) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
@@ -100,29 +100,29 @@ void Disasm_DS_RT_RA0_I(InstrData& i, poly::StringBuffer* str) {
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
}
|
||||
}
|
||||
void Disasm_D_RA(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_D_RA(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d", i.type->name, i.D.RA);
|
||||
}
|
||||
void Disasm_X_RA_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_X_RA_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d", i.type->name, i.X.RA, i.X.RB);
|
||||
}
|
||||
void Disasm_XO_RT_RA_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_XO_RT_RA_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s%s r%d, r%d, r%d", i.XO.Rc ? -7 : -8, i.type->name,
|
||||
i.XO.OE ? "o" : "", i.XO.Rc ? "." : "", i.XO.RT, i.XO.RA,
|
||||
i.XO.RB);
|
||||
}
|
||||
void Disasm_XO_RT_RA(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_XO_RT_RA(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s%s r%d, r%d", i.XO.Rc ? -7 : -8, i.type->name,
|
||||
i.XO.OE ? "o" : "", i.XO.Rc ? "." : "", i.XO.RT, i.XO.RA);
|
||||
}
|
||||
void Disasm_X_RA_RT_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_X_RA_RT_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, r%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RA, i.X.RT, i.X.RB);
|
||||
}
|
||||
void Disasm_D_RA_RT_I(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_D_RA_RT_I(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-7s. r%d, r%d, %.4Xh", i.type->name, i.D.RA, i.D.RT, i.D.DS);
|
||||
}
|
||||
void Disasm_X_RA_RT(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_X_RA_RT(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RA, i.X.RT);
|
||||
}
|
||||
@@ -161,14 +161,14 @@ void Disasm_X_RA_RT(InstrData& i, poly::StringBuffer* str) {
|
||||
(i.VX128_R.VA128l | (i.VX128_R.VA128h << 5) | (i.VX128_R.VA128H << 6))
|
||||
#define VX128_R_VB128 (i.VX128_R.VB128l | (i.VX128_R.VB128h << 5))
|
||||
|
||||
void Disasm_X_VX_RA0_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_X_VX_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||
if (i.X.RA) {
|
||||
str->Append("%-8s v%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
} else {
|
||||
str->Append("%-8s v%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||
}
|
||||
}
|
||||
void Disasm_VX1281_VD_RA0_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_VX1281_VD_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_1_VD128;
|
||||
if (i.VX128_1.RA) {
|
||||
str->Append("%-8s v%d, r%d, r%d", i.type->name, vd, i.VX128_1.RA,
|
||||
@@ -177,45 +177,45 @@ void Disasm_VX1281_VD_RA0_RB(InstrData& i, poly::StringBuffer* str) {
|
||||
str->Append("%-8s v%d, 0, r%d", i.type->name, vd, i.VX128_1.RB);
|
||||
}
|
||||
}
|
||||
void Disasm_VX1283_VD_VB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_VX1283_VD_VB(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_3_VD128;
|
||||
const uint32_t vb = VX128_3_VB128;
|
||||
str->Append("%-8s v%d, v%d", i.type->name, vd, vb);
|
||||
}
|
||||
void Disasm_VX1283_VD_VB_I(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_VX1283_VD_VB_I(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_VD128;
|
||||
const uint32_t va = VX128_VA128;
|
||||
const uint32_t uimm = i.VX128_3.IMM;
|
||||
str->Append("%-8s v%d, v%d, %.2Xh", i.type->name, vd, va, uimm);
|
||||
}
|
||||
void Disasm_VX_VD_VA_VB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_VX_VD_VA_VB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, v%d", i.type->name, i.VX.VD, i.VX.VA, i.VX.VB);
|
||||
}
|
||||
void Disasm_VX128_VD_VA_VB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_VX128_VD_VA_VB(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_VD128;
|
||||
const uint32_t va = VX128_VA128;
|
||||
const uint32_t vb = VX128_VB128;
|
||||
str->Append("%-8s v%d, v%d, v%d", i.type->name, vd, va, vb);
|
||||
}
|
||||
void Disasm_VX128_VD_VA_VD_VB(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_VX128_VD_VA_VD_VB(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_VD128;
|
||||
const uint32_t va = VX128_VA128;
|
||||
const uint32_t vb = VX128_VB128;
|
||||
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name, vd, va, vd, vb);
|
||||
}
|
||||
void Disasm_VX1282_VD_VA_VB_VC(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_VX1282_VD_VA_VB_VC(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_2_VD128;
|
||||
const uint32_t va = VX128_2_VA128;
|
||||
const uint32_t vb = VX128_2_VB128;
|
||||
const uint32_t vc = i.VX128_2.VC;
|
||||
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name, vd, va, vb, vc);
|
||||
}
|
||||
void Disasm_VXA_VD_VA_VB_VC(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_VXA_VD_VA_VB_VC(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name, i.VXA.VD, i.VXA.VA,
|
||||
i.VXA.VB, i.VXA.VC);
|
||||
}
|
||||
|
||||
void Disasm_sync(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_sync(InstrData& i, StringBuffer* str) {
|
||||
const char* name;
|
||||
int L = i.X.RT & 3;
|
||||
switch (L) {
|
||||
@@ -234,7 +234,7 @@ void Disasm_sync(InstrData& i, poly::StringBuffer* str) {
|
||||
str->Append("%-8s %.2X", name, L);
|
||||
}
|
||||
|
||||
void Disasm_dcbf(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_dcbf(InstrData& i, StringBuffer* str) {
|
||||
const char* name;
|
||||
switch (i.X.RT & 3) {
|
||||
case 0:
|
||||
@@ -256,7 +256,7 @@ void Disasm_dcbf(InstrData& i, poly::StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d", name, i.X.RA, i.X.RB);
|
||||
}
|
||||
|
||||
void Disasm_dcbz(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_dcbz(InstrData& i, StringBuffer* str) {
|
||||
// or dcbz128 0x7C2007EC
|
||||
if (i.X.RA) {
|
||||
str->Append("%-8s r%d, r%d", i.type->name, i.X.RA, i.X.RB);
|
||||
@@ -265,16 +265,16 @@ void Disasm_dcbz(InstrData& i, poly::StringBuffer* str) {
|
||||
}
|
||||
}
|
||||
|
||||
void Disasm_fcmp(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_fcmp(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s cr%d, f%d, f%d", i.type->name, i.X.RT >> 2, i.X.RA, i.X.RB);
|
||||
}
|
||||
|
||||
void Disasm_mffsx(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_mffsx(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, FPSCR", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RT);
|
||||
}
|
||||
|
||||
void Disasm_bx(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_bx(InstrData& i, StringBuffer* str) {
|
||||
const char* name = i.I.LK ? "bl" : "b";
|
||||
uint32_t nia;
|
||||
if (i.I.AA) {
|
||||
@@ -285,7 +285,7 @@ void Disasm_bx(InstrData& i, poly::StringBuffer* str) {
|
||||
str->Append("%-8s %.8X", name, nia);
|
||||
// TODO(benvanik): resolve target name?
|
||||
}
|
||||
void Disasm_bcx(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_bcx(InstrData& i, StringBuffer* str) {
|
||||
const char* s0 = i.B.LK ? "lr, " : "";
|
||||
const char* s1;
|
||||
if (!select_bits(i.B.BO, 2, 2)) {
|
||||
@@ -295,7 +295,7 @@ void Disasm_bcx(InstrData& i, poly::StringBuffer* str) {
|
||||
}
|
||||
char s2[8] = {0};
|
||||
if (!select_bits(i.B.BO, 4, 4)) {
|
||||
snprintf(s2, poly::countof(s2), "cr%d, ", i.B.BI >> 2);
|
||||
snprintf(s2, xe::countof(s2), "cr%d, ", i.B.BI >> 2);
|
||||
}
|
||||
uint32_t nia;
|
||||
if (i.B.AA) {
|
||||
@@ -306,17 +306,17 @@ void Disasm_bcx(InstrData& i, poly::StringBuffer* str) {
|
||||
str->Append("%-8s %s%s%s%.8X", i.type->name, s0, s1, s2, nia);
|
||||
// TODO(benvanik): resolve target name?
|
||||
}
|
||||
void Disasm_bcctrx(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_bcctrx(InstrData& i, StringBuffer* str) {
|
||||
// TODO(benvanik): mnemonics
|
||||
const char* s0 = i.XL.LK ? "lr, " : "";
|
||||
char s2[8] = {0};
|
||||
if (!select_bits(i.XL.BO, 4, 4)) {
|
||||
snprintf(s2, poly::countof(s2), "cr%d, ", i.XL.BI >> 2);
|
||||
snprintf(s2, xe::countof(s2), "cr%d, ", i.XL.BI >> 2);
|
||||
}
|
||||
str->Append("%-8s %s%sctr", i.type->name, s0, s2);
|
||||
// TODO(benvanik): resolve target name?
|
||||
}
|
||||
void Disasm_bclrx(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_bclrx(InstrData& i, StringBuffer* str) {
|
||||
const char* name = "bclr";
|
||||
if (i.code == 0x4E800020) {
|
||||
name = "blr";
|
||||
@@ -329,12 +329,12 @@ void Disasm_bclrx(InstrData& i, poly::StringBuffer* str) {
|
||||
}
|
||||
char s2[8] = {0};
|
||||
if (!select_bits(i.XL.BO, 4, 4)) {
|
||||
snprintf(s2, poly::countof(s2), "cr%d, ", i.XL.BI >> 2);
|
||||
snprintf(s2, xe::countof(s2), "cr%d, ", i.XL.BI >> 2);
|
||||
}
|
||||
str->Append("%-8s %s%s", name, s1, s2);
|
||||
}
|
||||
|
||||
void Disasm_mfcr(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_mfcr(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, cr", i.type->name, i.X.RT);
|
||||
}
|
||||
const char* Disasm_spr_name(uint32_t n) {
|
||||
@@ -352,40 +352,40 @@ const char* Disasm_spr_name(uint32_t n) {
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
void Disasm_mfspr(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_mfspr(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
||||
const char* reg = Disasm_spr_name(n);
|
||||
str->Append("%-8s r%d, %s", i.type->name, i.XFX.RT, reg);
|
||||
}
|
||||
void Disasm_mtspr(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_mtspr(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
||||
const char* reg = Disasm_spr_name(n);
|
||||
str->Append("%-8s %s, r%d", i.type->name, reg, i.XFX.RT);
|
||||
}
|
||||
void Disasm_mftb(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_mftb(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, tb", i.type->name, i.XFX.RT);
|
||||
}
|
||||
void Disasm_mfmsr(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_mfmsr(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d", i.type->name, i.X.RT);
|
||||
}
|
||||
void Disasm_mtmsr(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_mtmsr(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, %d", i.type->name, i.X.RT, (i.X.RA & 16) ? 1 : 0);
|
||||
}
|
||||
|
||||
void Disasm_cmp(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_cmp(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s cr%d, %.2X, r%d, r%d", i.type->name, i.X.RT >> 2,
|
||||
i.X.RT & 1, i.X.RA, i.X.RB);
|
||||
}
|
||||
void Disasm_cmpi(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_cmpi(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s cr%d, %.2X, r%d, %d", i.type->name, i.D.RT >> 2, i.D.RT & 1,
|
||||
i.D.RA, XEEXTS16(i.D.DS));
|
||||
}
|
||||
void Disasm_cmpli(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_cmpli(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s cr%d, %.2X, r%d, %.2X", i.type->name, i.D.RT >> 2,
|
||||
i.D.RT & 1, i.D.RA, XEEXTS16(i.D.DS));
|
||||
}
|
||||
|
||||
void Disasm_rld(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_rld(InstrData& i, StringBuffer* str) {
|
||||
if (i.MD.idx == 0) {
|
||||
// XEDISASMR(rldiclx, 0x78000000, MD )
|
||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicl",
|
||||
@@ -422,75 +422,75 @@ void Disasm_rld(InstrData& i, poly::StringBuffer* str) {
|
||||
assert_always();
|
||||
}
|
||||
}
|
||||
void Disasm_rlwim(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_rlwim(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, %d, %d, %d", i.M.Rc ? -7 : -8, i.type->name,
|
||||
i.M.Rc ? "." : "", i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
|
||||
}
|
||||
void Disasm_rlwnmx(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_rlwnmx(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, r%d, %d, %d", i.M.Rc ? -7 : -8, i.type->name,
|
||||
i.M.Rc ? "." : "", i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
|
||||
}
|
||||
void Disasm_srawix(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_srawix(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, %d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RA, i.X.RT, i.X.RB);
|
||||
}
|
||||
void Disasm_sradix(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_sradix(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, %d", i.XS.Rc ? -7 : -8, i.type->name,
|
||||
i.XS.Rc ? "." : "", i.XS.RA, i.XS.RT, (i.XS.SH5 << 5) | i.XS.SH);
|
||||
}
|
||||
|
||||
void Disasm_vpermwi128(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vpermwi128(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = i.VX128_P.VD128l | (i.VX128_P.VD128h << 5);
|
||||
const uint32_t vb = i.VX128_P.VB128l | (i.VX128_P.VB128h << 5);
|
||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name, vd, vb,
|
||||
i.VX128_P.PERMl | (i.VX128_P.PERMh << 5));
|
||||
}
|
||||
void Disasm_vrfin128(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vrfin128(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_3_VD128;
|
||||
const uint32_t vb = VX128_3_VB128;
|
||||
str->Append("%-8s v%d, v%d", i.type->name, vd, vb);
|
||||
}
|
||||
void Disasm_vrlimi128(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vrlimi128(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_4_VD128;
|
||||
const uint32_t vb = VX128_4_VB128;
|
||||
str->Append("%-8s v%d, v%d, %.2X, %.2X", i.type->name, vd, vb, i.VX128_4.IMM,
|
||||
i.VX128_4.z);
|
||||
}
|
||||
void Disasm_vsldoi128(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vsldoi128(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_5_VD128;
|
||||
const uint32_t va = VX128_5_VA128;
|
||||
const uint32_t vb = VX128_5_VB128;
|
||||
const uint32_t sh = i.VX128_5.SH;
|
||||
str->Append("%-8s v%d, v%d, v%d, %.2X", i.type->name, vd, va, vb, sh);
|
||||
}
|
||||
void Disasm_vspltb(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vspltb(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB,
|
||||
i.VX.VA & 0xF);
|
||||
}
|
||||
void Disasm_vsplth(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vsplth(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB,
|
||||
i.VX.VA & 0x7);
|
||||
}
|
||||
void Disasm_vspltw(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vspltw(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB, i.VX.VA);
|
||||
}
|
||||
void Disasm_vspltisb(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vspltisb(InstrData& i, StringBuffer* str) {
|
||||
// 5bit -> 8bit sign extend
|
||||
int8_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xF0) : i.VX.VA;
|
||||
str->Append("%-8s v%d, %.2X", i.type->name, i.VX.VD, simm);
|
||||
}
|
||||
void Disasm_vspltish(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vspltish(InstrData& i, StringBuffer* str) {
|
||||
// 5bit -> 16bit sign extend
|
||||
int16_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFF0) : i.VX.VA;
|
||||
str->Append("%-8s v%d, %.4X", i.type->name, i.VX.VD, simm);
|
||||
}
|
||||
void Disasm_vspltisw(InstrData& i, poly::StringBuffer* str) {
|
||||
void Disasm_vspltisw(InstrData& i, StringBuffer* str) {
|
||||
// 5bit -> 32bit sign extend
|
||||
int32_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFFFFFF0) : i.VX.VA;
|
||||
str->Append("%-8s v%d, %.8X", i.type->name, i.VX.VD, simm);
|
||||
}
|
||||
|
||||
int DisasmPPC(InstrData& i, poly::StringBuffer* str) {
|
||||
int DisasmPPC(InstrData& i, StringBuffer* str) {
|
||||
if (!i.type) {
|
||||
str->Append("???");
|
||||
} else {
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
#ifndef XENIA_FRONTEND_PPC_DISASM_H_
|
||||
#define XENIA_FRONTEND_PPC_DISASM_H_
|
||||
|
||||
#include "xenia/base/string_buffer.h"
|
||||
#include "xenia/cpu/frontend/ppc_instr.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
|
||||
int DisasmPPC(InstrData& i, poly::StringBuffer* str);
|
||||
int DisasmPPC(InstrData& i, StringBuffer* str);
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace cpu
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_emit-private.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc_hir_builder.h"
|
||||
|
||||
@@ -19,10 +19,6 @@ namespace frontend {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace xe::cpu::hir;
|
||||
using poly::vec128b;
|
||||
using poly::vec128f;
|
||||
using poly::vec128i;
|
||||
using poly::vec128s;
|
||||
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_emit-private.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc_hir_builder.h"
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_emit-private.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc_hir_builder.h"
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_emit-private.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc_hir_builder.h"
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_emit-private.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc_hir_builder.h"
|
||||
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "poly/type_pool.h"
|
||||
#include "xenia/base/type_pool.h"
|
||||
#include "xenia/cpu/frontend/context_info.h"
|
||||
#include "xenia/memory.h"
|
||||
#include "xenia/cpu/function.h"
|
||||
#include "xenia/cpu/symbol_info.h"
|
||||
#include "xenia/memory.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -58,7 +58,7 @@ class PPCFrontend {
|
||||
Runtime* runtime_;
|
||||
std::unique_ptr<ContextInfo> context_info_;
|
||||
PPCBuiltins builtins_;
|
||||
poly::TypePool<PPCTranslator, PPCFrontend*> translator_pool_;
|
||||
TypePool<PPCTranslator, PPCFrontend*> translator_pool_;
|
||||
};
|
||||
|
||||
} // namespace frontend
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_hir_builder.h"
|
||||
|
||||
#include "poly/byte_order.h"
|
||||
#include "poly/memory.h"
|
||||
#include "xenia/base/byte_order.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/memory.h"
|
||||
#include "xenia/cpu/cpu-private.h"
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc_disasm.h"
|
||||
@@ -18,7 +19,6 @@
|
||||
#include "xenia/cpu/frontend/ppc_instr.h"
|
||||
#include "xenia/cpu/hir/label.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
#include "xenia/logging.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -82,7 +82,7 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
|
||||
for (uint32_t address = start_address, offset = 0; address <= end_address;
|
||||
address += 4, offset++) {
|
||||
i.address = address;
|
||||
i.code = poly::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
|
||||
i.code = xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
|
||||
// TODO(benvanik): find a way to avoid using the opcode tables.
|
||||
i.type = GetInstrType(i.code);
|
||||
trace_info_.dest_count = 0;
|
||||
@@ -170,7 +170,7 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
|
||||
|
||||
void PPCHIRBuilder::AnnotateLabel(uint32_t address, Label* label) {
|
||||
char name_buffer[13];
|
||||
snprintf(name_buffer, poly::countof(name_buffer), "loc_%.8X", address);
|
||||
snprintf(name_buffer, xe::countof(name_buffer), "loc_%.8X", address);
|
||||
label->name = (char*)arena_->Alloc(sizeof(name_buffer));
|
||||
memcpy(label->name, name_buffer, sizeof(name_buffer));
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
#ifndef XENIA_FRONTEND_PPC_HIR_BUILDER_H_
|
||||
#define XENIA_FRONTEND_PPC_HIR_BUILDER_H_
|
||||
|
||||
#include "xenia/base/string_buffer.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/function.h"
|
||||
#include "xenia/cpu/symbol_info.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -91,7 +91,7 @@ class PPCHIRBuilder : public hir::HIRBuilder {
|
||||
PPCFrontend* frontend_;
|
||||
|
||||
// Reset whenever needed:
|
||||
poly::StringBuffer comment_buffer_;
|
||||
StringBuffer comment_buffer_;
|
||||
|
||||
// Reset each Emit:
|
||||
bool with_debug_info_;
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/math.h"
|
||||
#include "poly/string_buffer.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/string_buffer.h"
|
||||
#include "xenia/cpu/frontend/ppc_instr_tables.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -24,7 +24,7 @@ namespace frontend {
|
||||
std::vector<InstrType*> all_instrs_;
|
||||
|
||||
void DumpAllInstrCounts() {
|
||||
poly::StringBuffer sb;
|
||||
StringBuffer sb;
|
||||
sb.Append("Instruction translation counts:\n");
|
||||
for (auto instr_type : all_instrs_) {
|
||||
if (instr_type->translation_count) {
|
||||
@@ -42,7 +42,7 @@ void InstrOperand::Dump(std::string& out_str) {
|
||||
}
|
||||
|
||||
char buffer[32];
|
||||
const size_t max_count = poly::countof(buffer);
|
||||
const size_t max_count = xe::countof(buffer);
|
||||
switch (type) {
|
||||
case InstrOperand::kRegister:
|
||||
switch (reg.set) {
|
||||
@@ -380,7 +380,7 @@ InstrType* GetInstrType(uint32_t code) {
|
||||
|
||||
// Slow lookup via linear scan.
|
||||
// This is primarily due to laziness. It could be made fast like the others.
|
||||
for (size_t n = 0; n < poly::countof(tables::instr_table_scan); n++) {
|
||||
for (size_t n = 0; n < xe::countof(tables::instr_table_scan); n++) {
|
||||
slot = &(tables::instr_table_scan[n]);
|
||||
if (slot->opcode == (code & slot->opcode_mask)) {
|
||||
return slot;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "poly/string_buffer.h"
|
||||
#include "xenia/base/string_buffer.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -547,7 +547,7 @@ class InstrDisasm {
|
||||
void Dump(std::string& out_str, size_t pad = 13);
|
||||
};
|
||||
|
||||
typedef void (*InstrDisasmFn)(InstrData& i, poly::StringBuffer* str);
|
||||
typedef void (*InstrDisasmFn)(InstrData& i, StringBuffer* str);
|
||||
typedef void* InstrEmitFn;
|
||||
|
||||
class InstrType {
|
||||
|
||||
@@ -12,84 +12,84 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "poly/math.h"
|
||||
#include "poly/string_buffer.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/string_buffer.h"
|
||||
#include "xenia/cpu/frontend/ppc_instr.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
|
||||
void Disasm_0(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm__(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_X_FRT_FRB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_A_FRT_FRB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_A_FRT_FRA_FRB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_A_FRT_FRA_FRB_FRC(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_X_RT_RA_RB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_X_RT_RA0_RB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_X_FRT_RA_RB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_X_FRT_RA0_RB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_D_RT_RA_I(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_D_RT_RA0_I(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_D_FRT_RA_I(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_D_FRT_RA0_I(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_DS_RT_RA_I(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_DS_RT_RA0_I(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_D_RA(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_X_RA_RB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_XO_RT_RA_RB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_XO_RT_RA(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_X_RA_RT_RB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_D_RA_RT_I(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_X_RA_RT(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_X_VX_RA0_RB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_VX1281_VD_RA0_RB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_VX1283_VD_VB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_VX1283_VD_VB_I(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_VX_VD_VA_VB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_VX128_VD_VA_VB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_VX128_VD_VA_VD_VB(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_VX1282_VD_VA_VB_VC(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_VXA_VD_VA_VB_VC(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_0(InstrData& i, StringBuffer* str);
|
||||
void Disasm__(InstrData& i, StringBuffer* str);
|
||||
void Disasm_X_FRT_FRB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_A_FRT_FRB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_A_FRT_FRA_FRB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_A_FRT_FRA_FRB_FRC(InstrData& i, StringBuffer* str);
|
||||
void Disasm_X_RT_RA_RB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_X_RT_RA0_RB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_X_FRT_RA_RB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_X_FRT_RA0_RB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_D_RT_RA_I(InstrData& i, StringBuffer* str);
|
||||
void Disasm_D_RT_RA0_I(InstrData& i, StringBuffer* str);
|
||||
void Disasm_D_FRT_RA_I(InstrData& i, StringBuffer* str);
|
||||
void Disasm_D_FRT_RA0_I(InstrData& i, StringBuffer* str);
|
||||
void Disasm_DS_RT_RA_I(InstrData& i, StringBuffer* str);
|
||||
void Disasm_DS_RT_RA0_I(InstrData& i, StringBuffer* str);
|
||||
void Disasm_D_RA(InstrData& i, StringBuffer* str);
|
||||
void Disasm_X_RA_RB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_XO_RT_RA_RB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_XO_RT_RA(InstrData& i, StringBuffer* str);
|
||||
void Disasm_X_RA_RT_RB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_D_RA_RT_I(InstrData& i, StringBuffer* str);
|
||||
void Disasm_X_RA_RT(InstrData& i, StringBuffer* str);
|
||||
void Disasm_X_VX_RA0_RB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_VX1281_VD_RA0_RB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_VX1283_VD_VB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_VX1283_VD_VB_I(InstrData& i, StringBuffer* str);
|
||||
void Disasm_VX_VD_VA_VB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_VX128_VD_VA_VB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_VX128_VD_VA_VD_VB(InstrData& i, StringBuffer* str);
|
||||
void Disasm_VX1282_VD_VA_VB_VC(InstrData& i, StringBuffer* str);
|
||||
void Disasm_VXA_VD_VA_VB_VC(InstrData& i, StringBuffer* str);
|
||||
|
||||
void Disasm_sync(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_dcbf(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_dcbz(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_fcmp(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_sync(InstrData& i, StringBuffer* str);
|
||||
void Disasm_dcbf(InstrData& i, StringBuffer* str);
|
||||
void Disasm_dcbz(InstrData& i, StringBuffer* str);
|
||||
void Disasm_fcmp(InstrData& i, StringBuffer* str);
|
||||
|
||||
void Disasm_bx(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_bcx(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_bcctrx(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_bclrx(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_bx(InstrData& i, StringBuffer* str);
|
||||
void Disasm_bcx(InstrData& i, StringBuffer* str);
|
||||
void Disasm_bcctrx(InstrData& i, StringBuffer* str);
|
||||
void Disasm_bclrx(InstrData& i, StringBuffer* str);
|
||||
|
||||
void Disasm_mfcr(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_mfspr(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_mtspr(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_mftb(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_mfmsr(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_mtmsr(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_mfcr(InstrData& i, StringBuffer* str);
|
||||
void Disasm_mfspr(InstrData& i, StringBuffer* str);
|
||||
void Disasm_mtspr(InstrData& i, StringBuffer* str);
|
||||
void Disasm_mftb(InstrData& i, StringBuffer* str);
|
||||
void Disasm_mfmsr(InstrData& i, StringBuffer* str);
|
||||
void Disasm_mtmsr(InstrData& i, StringBuffer* str);
|
||||
|
||||
void Disasm_cmp(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_cmpi(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_cmpli(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_cmp(InstrData& i, StringBuffer* str);
|
||||
void Disasm_cmpi(InstrData& i, StringBuffer* str);
|
||||
void Disasm_cmpli(InstrData& i, StringBuffer* str);
|
||||
|
||||
void Disasm_rld(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_rlwim(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_rlwnmx(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_srawix(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_sradix(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_rld(InstrData& i, StringBuffer* str);
|
||||
void Disasm_rlwim(InstrData& i, StringBuffer* str);
|
||||
void Disasm_rlwnmx(InstrData& i, StringBuffer* str);
|
||||
void Disasm_srawix(InstrData& i, StringBuffer* str);
|
||||
void Disasm_sradix(InstrData& i, StringBuffer* str);
|
||||
|
||||
void Disasm_vpermwi128(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vrfin128(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vrlimi128(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vsldoi128(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vspltb(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vsplth(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vspltw(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vspltisb(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vspltish(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vspltisw(InstrData& i, poly::StringBuffer* str);
|
||||
void Disasm_vpermwi128(InstrData& i, StringBuffer* str);
|
||||
void Disasm_vrfin128(InstrData& i, StringBuffer* str);
|
||||
void Disasm_vrlimi128(InstrData& i, StringBuffer* str);
|
||||
void Disasm_vsldoi128(InstrData& i, StringBuffer* str);
|
||||
void Disasm_vspltb(InstrData& i, StringBuffer* str);
|
||||
void Disasm_vsplth(InstrData& i, StringBuffer* str);
|
||||
void Disasm_vspltw(InstrData& i, StringBuffer* str);
|
||||
void Disasm_vspltisb(InstrData& i, StringBuffer* str);
|
||||
void Disasm_vspltish(InstrData& i, StringBuffer* str);
|
||||
void Disasm_vspltisw(InstrData& i, StringBuffer* str);
|
||||
|
||||
namespace tables {
|
||||
|
||||
@@ -364,7 +364,7 @@ static InstrType instr_table_4_unprep[] = {
|
||||
"Vector Logical XOR"),
|
||||
};
|
||||
static InstrType** instr_table_4 = instr_table_prep(
|
||||
instr_table_4_unprep, poly::countof(instr_table_4_unprep), 0, 11);
|
||||
instr_table_4_unprep, xe::countof(instr_table_4_unprep), 0, 11);
|
||||
|
||||
// Opcode = 19, index = bits 10-1 (10)
|
||||
static InstrType instr_table_19_unprep[] = {
|
||||
@@ -384,7 +384,7 @@ static InstrType instr_table_19_unprep[] = {
|
||||
"Branch Conditional to Count Register"),
|
||||
};
|
||||
static InstrType** instr_table_19 = instr_table_prep(
|
||||
instr_table_19_unprep, poly::countof(instr_table_19_unprep), 1, 10);
|
||||
instr_table_19_unprep, xe::countof(instr_table_19_unprep), 1, 10);
|
||||
|
||||
// Opcode = 30, index = bits 4-1 (4)
|
||||
static InstrType instr_table_30_unprep[] = {
|
||||
@@ -400,7 +400,7 @@ static InstrType instr_table_30_unprep[] = {
|
||||
// INSTRUCTION(rldcrx, 0x78000012, MDS, General , 0),
|
||||
};
|
||||
static InstrType** instr_table_30 = instr_table_prep(
|
||||
instr_table_30_unprep, poly::countof(instr_table_30_unprep), 0, 0);
|
||||
instr_table_30_unprep, xe::countof(instr_table_30_unprep), 0, 0);
|
||||
|
||||
// Opcode = 31, index = bits 10-1 (10)
|
||||
static InstrType instr_table_31_unprep[] = {
|
||||
@@ -651,7 +651,7 @@ static InstrType instr_table_31_unprep[] = {
|
||||
"Store Vector Right Indexed LRU"),
|
||||
};
|
||||
static InstrType** instr_table_31 = instr_table_prep(
|
||||
instr_table_31_unprep, poly::countof(instr_table_31_unprep), 1, 10);
|
||||
instr_table_31_unprep, xe::countof(instr_table_31_unprep), 1, 10);
|
||||
|
||||
// Opcode = 58, index = bits 1-0 (2)
|
||||
static InstrType instr_table_58_unprep[] = {
|
||||
@@ -662,7 +662,7 @@ static InstrType instr_table_58_unprep[] = {
|
||||
"Load Word Algebraic"),
|
||||
};
|
||||
static InstrType** instr_table_58 = instr_table_prep(
|
||||
instr_table_58_unprep, poly::countof(instr_table_58_unprep), 0, 1);
|
||||
instr_table_58_unprep, xe::countof(instr_table_58_unprep), 0, 1);
|
||||
|
||||
// Opcode = 59, index = bits 5-1 (5)
|
||||
static InstrType instr_table_59_unprep[] = {
|
||||
@@ -688,7 +688,7 @@ static InstrType instr_table_59_unprep[] = {
|
||||
"Floating Negative Multiply-Add [Single]"),
|
||||
};
|
||||
static InstrType** instr_table_59 = instr_table_prep(
|
||||
instr_table_59_unprep, poly::countof(instr_table_59_unprep), 1, 5);
|
||||
instr_table_59_unprep, xe::countof(instr_table_59_unprep), 1, 5);
|
||||
|
||||
// Opcode = 62, index = bits 1-0 (2)
|
||||
static InstrType instr_table_62_unprep[] = {
|
||||
@@ -697,7 +697,7 @@ static InstrType instr_table_62_unprep[] = {
|
||||
"Store Doubleword with Update"),
|
||||
};
|
||||
static InstrType** instr_table_62 = instr_table_prep(
|
||||
instr_table_62_unprep, poly::countof(instr_table_62_unprep), 0, 1);
|
||||
instr_table_62_unprep, xe::countof(instr_table_62_unprep), 0, 1);
|
||||
|
||||
// Opcode = 63, index = bits 10-1 (10)
|
||||
// NOTE: the A format instructions need some special handling because
|
||||
@@ -757,7 +757,7 @@ static InstrType instr_table_63_unprep[] = {
|
||||
"Floating Convert From Integer Doubleword"),
|
||||
};
|
||||
static InstrType** instr_table_63 = instr_table_prep_63(
|
||||
instr_table_63_unprep, poly::countof(instr_table_63_unprep), 1, 10);
|
||||
instr_table_63_unprep, xe::countof(instr_table_63_unprep), 1, 10);
|
||||
|
||||
// Main table, index = bits 31-26 (6) : (code >> 26)
|
||||
static InstrType instr_table_unprep[64] = {
|
||||
@@ -837,7 +837,7 @@ static InstrType instr_table_unprep[64] = {
|
||||
"Store Floating-Point Double with Update"),
|
||||
};
|
||||
static InstrType** instr_table = instr_table_prep(
|
||||
instr_table_unprep, poly::countof(instr_table_unprep), 26, 31);
|
||||
instr_table_unprep, xe::countof(instr_table_unprep), 26, 31);
|
||||
|
||||
// Altivec instructions.
|
||||
// TODO(benvanik): build a table like the other instructions.
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include "poly/memory.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/memory.h"
|
||||
#include "xenia/cpu/frontend/ppc_frontend.h"
|
||||
#include "xenia/cpu/frontend/ppc_instr.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
#include "xenia/logging.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
#if 0
|
||||
@@ -63,7 +63,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||
InstrData i;
|
||||
while (true) {
|
||||
i.address = address;
|
||||
i.code = poly::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
|
||||
i.code = xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
|
||||
|
||||
// If we fetched 0 assume that we somehow hit one of the awesome
|
||||
// 'no really we meant to end after that bl' functions.
|
||||
@@ -290,7 +290,7 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
||||
InstrData i;
|
||||
for (uint32_t address = start_address; address <= end_address; address += 4) {
|
||||
i.address = address;
|
||||
i.code = poly::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
|
||||
i.code = xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
|
||||
if (!i.code) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_translator.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/byte_order.h"
|
||||
#include "poly/memory.h"
|
||||
#include "poly/reset_scope.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/byte_order.h"
|
||||
#include "xenia/base/memory.h"
|
||||
#include "xenia/base/reset_scope.h"
|
||||
#include "xenia/cpu/compiler/compiler_passes.h"
|
||||
#include "xenia/cpu/cpu-private.h"
|
||||
#include "xenia/cpu/frontend/ppc_disasm.h"
|
||||
@@ -92,10 +92,10 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Reset() all caching when we leave.
|
||||
poly::make_reset_scope(builder_);
|
||||
poly::make_reset_scope(compiler_);
|
||||
poly::make_reset_scope(assembler_);
|
||||
poly::make_reset_scope(&string_buffer_);
|
||||
xe::make_reset_scope(builder_);
|
||||
xe::make_reset_scope(compiler_);
|
||||
xe::make_reset_scope(assembler_);
|
||||
xe::make_reset_scope(&string_buffer_);
|
||||
|
||||
// Scan the function to find its extents. We only need to do this if we
|
||||
// haven't already been provided with them from some other source.
|
||||
@@ -176,7 +176,7 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
||||
};
|
||||
|
||||
void PPCTranslator::DumpSource(FunctionInfo* symbol_info,
|
||||
poly::StringBuffer* string_buffer) {
|
||||
StringBuffer* string_buffer) {
|
||||
Memory* memory = frontend_->memory();
|
||||
|
||||
string_buffer->Append("%s fn %.8X-%.8X %s\n",
|
||||
@@ -193,7 +193,7 @@ void PPCTranslator::DumpSource(FunctionInfo* symbol_info,
|
||||
for (uint32_t address = start_address, offset = 0; address <= end_address;
|
||||
address += 4, offset++) {
|
||||
i.address = address;
|
||||
i.code = poly::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
|
||||
i.code = xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
|
||||
// TODO(benvanik): find a way to avoid using the opcode tables.
|
||||
i.type = GetInstrType(i.code);
|
||||
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "xenia/base/string_buffer.h"
|
||||
#include "xenia/cpu/backend/assembler.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/symbol_info.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -34,7 +34,7 @@ class PPCTranslator {
|
||||
uint32_t trace_flags, Function** out_function);
|
||||
|
||||
private:
|
||||
void DumpSource(FunctionInfo* symbol_info, poly::StringBuffer* string_buffer);
|
||||
void DumpSource(FunctionInfo* symbol_info, StringBuffer* string_buffer);
|
||||
|
||||
private:
|
||||
PPCFrontend* frontend_;
|
||||
@@ -43,7 +43,7 @@ class PPCTranslator {
|
||||
std::unique_ptr<compiler::Compiler> compiler_;
|
||||
std::unique_ptr<backend::Assembler> assembler_;
|
||||
|
||||
poly::StringBuffer string_buffer_;
|
||||
StringBuffer string_buffer_;
|
||||
};
|
||||
|
||||
} // namespace frontend
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "poly/main.h"
|
||||
#include "poly/math.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/main.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/cpu/cpu.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc_frontend.h"
|
||||
#include "xenia/cpu/raw_module.h"
|
||||
#include "xenia/logging.h"
|
||||
|
||||
#if !XE_PLATFORM_WIN32
|
||||
#include <dirent.h>
|
||||
@@ -48,11 +48,11 @@ struct TestCase {
|
||||
class TestSuite {
|
||||
public:
|
||||
TestSuite(const std::wstring& src_file_path) : src_file_path(src_file_path) {
|
||||
name = src_file_path.substr(
|
||||
src_file_path.find_last_of(poly::path_separator) + 1);
|
||||
name = src_file_path.substr(src_file_path.find_last_of(xe::path_separator) +
|
||||
1);
|
||||
name = ReplaceExtension(name, L"");
|
||||
map_file_path = poly::to_wstring(FLAGS_test_bin_path) + name + L".map";
|
||||
bin_file_path = poly::to_wstring(FLAGS_test_bin_path) + name + L".bin";
|
||||
map_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".map";
|
||||
bin_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".bin";
|
||||
}
|
||||
|
||||
bool Load() {
|
||||
@@ -92,7 +92,7 @@ class TestSuite {
|
||||
}
|
||||
|
||||
bool ReadMap(const std::wstring& map_file_path) {
|
||||
FILE* f = fopen(poly::to_string(map_file_path).c_str(), "r");
|
||||
FILE* f = fopen(xe::to_string(map_file_path).c_str(), "r");
|
||||
if (!f) {
|
||||
return false;
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class TestSuite {
|
||||
|
||||
bool ReadAnnotations(const std::wstring& src_file_path) {
|
||||
TestCase* current_test_case = nullptr;
|
||||
FILE* f = fopen(poly::to_string(src_file_path).c_str(), "r");
|
||||
FILE* f = fopen(xe::to_string(src_file_path).c_str(), "r");
|
||||
if (!f) {
|
||||
return false;
|
||||
}
|
||||
@@ -273,7 +273,7 @@ class TestRunner {
|
||||
auto reg_value = it.second.substr(space_pos + 1);
|
||||
if (!ppc_state->CompareRegWithString(reg_name.c_str(),
|
||||
reg_value.c_str(), actual_value,
|
||||
poly::countof(actual_value))) {
|
||||
xe::countof(actual_value))) {
|
||||
any_failed = true;
|
||||
printf("Register %s assert failed:\n", reg_name.c_str());
|
||||
printf(" Expected: %s == %s\n", reg_name.c_str(), reg_value.c_str());
|
||||
@@ -373,7 +373,7 @@ bool RunTests(const std::wstring& test_name) {
|
||||
int passed_count = 0;
|
||||
|
||||
auto test_path_root =
|
||||
poly::fix_path_separators(poly::to_wstring(FLAGS_test_path));
|
||||
xe::fix_path_separators(xe::to_wstring(FLAGS_test_path));
|
||||
std::vector<std::wstring> test_files;
|
||||
if (!DiscoverTests(test_path_root, test_files)) {
|
||||
return false;
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
#include "xenia/cpu/function.h"
|
||||
|
||||
#include "xdb/protocol.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/cpu/debugger.h"
|
||||
#include "xenia/cpu/symbol_info.h"
|
||||
#include "xenia/cpu/thread_state.h"
|
||||
#include "xenia/logging.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/hir/block.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/hir/instr.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef XENIA_HIR_BLOCK_H_
|
||||
#define XENIA_HIR_BLOCK_H_
|
||||
|
||||
#include "poly/arena.h"
|
||||
#include "xenia/base/arena.h"
|
||||
|
||||
namespace llvm {
|
||||
class BitVector;
|
||||
@@ -46,7 +46,7 @@ class Edge {
|
||||
|
||||
class Block {
|
||||
public:
|
||||
poly::Arena* arena;
|
||||
Arena* arena;
|
||||
|
||||
Block* next;
|
||||
Block* prev;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/hir/block.h"
|
||||
#include "xenia/cpu/hir/instr.h"
|
||||
#include "xenia/cpu/hir/label.h"
|
||||
@@ -29,7 +29,7 @@ namespace hir {
|
||||
assert_true((value1->type) == (value2->type))
|
||||
|
||||
HIRBuilder::HIRBuilder() {
|
||||
arena_ = new poly::Arena();
|
||||
arena_ = new Arena();
|
||||
Reset();
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ int HIRBuilder::Finalize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HIRBuilder::DumpValue(poly::StringBuffer* str, Value* value) {
|
||||
void HIRBuilder::DumpValue(StringBuffer* str, Value* value) {
|
||||
if (value->IsConstant()) {
|
||||
switch (value->type) {
|
||||
case INT8_TYPE:
|
||||
@@ -128,7 +128,7 @@ void HIRBuilder::DumpValue(poly::StringBuffer* str, Value* value) {
|
||||
}
|
||||
}
|
||||
|
||||
void HIRBuilder::DumpOp(poly::StringBuffer* str, OpcodeSignatureType sig_type,
|
||||
void HIRBuilder::DumpOp(StringBuffer* str, OpcodeSignatureType sig_type,
|
||||
Instr::Op* op) {
|
||||
switch (sig_type) {
|
||||
case OPCODE_SIG_TYPE_X:
|
||||
@@ -155,7 +155,7 @@ void HIRBuilder::DumpOp(poly::StringBuffer* str, OpcodeSignatureType sig_type,
|
||||
}
|
||||
}
|
||||
|
||||
void HIRBuilder::Dump(poly::StringBuffer* str) {
|
||||
void HIRBuilder::Dump(StringBuffer* str) {
|
||||
if (attributes_) {
|
||||
str->Append("; attributes = %.8X\n", attributes_);
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/arena.h"
|
||||
#include "xenia/base/string_buffer.h"
|
||||
#include "xenia/cpu/hir/block.h"
|
||||
#include "xenia/cpu/hir/instr.h"
|
||||
#include "xenia/cpu/hir/label.h"
|
||||
#include "xenia/cpu/hir/opcodes.h"
|
||||
#include "xenia/cpu/hir/value.h"
|
||||
#include "poly/arena.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -36,10 +36,10 @@ class HIRBuilder {
|
||||
virtual void Reset();
|
||||
virtual int Finalize();
|
||||
|
||||
void Dump(poly::StringBuffer* str);
|
||||
void Dump(StringBuffer* str);
|
||||
void AssertNoCycles();
|
||||
|
||||
poly::Arena* arena() const { return arena_; }
|
||||
Arena* arena() const { return arena_; }
|
||||
|
||||
uint32_t attributes() const { return attributes_; }
|
||||
void set_attributes(uint32_t value) { attributes_ = value; }
|
||||
@@ -229,9 +229,8 @@ class HIRBuilder {
|
||||
Value* AtomicSub(Value* address, Value* value);
|
||||
|
||||
protected:
|
||||
void DumpValue(poly::StringBuffer* str, Value* value);
|
||||
void DumpOp(poly::StringBuffer* str, OpcodeSignatureType sig_type,
|
||||
Instr::Op* op);
|
||||
void DumpValue(StringBuffer* str, Value* value);
|
||||
void DumpOp(StringBuffer* str, OpcodeSignatureType sig_type, Instr::Op* op);
|
||||
|
||||
Value* AllocValue(TypeName type = INT64_TYPE);
|
||||
Value* CloneValue(Value* source);
|
||||
@@ -246,7 +245,7 @@ class HIRBuilder {
|
||||
TypeName part_type);
|
||||
|
||||
protected:
|
||||
poly::Arena* arena_;
|
||||
Arena* arena_;
|
||||
|
||||
uint32_t attributes_;
|
||||
|
||||
|
||||
@@ -11,15 +11,15 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/byte_order.h"
|
||||
#include "poly/math.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/byte_order.h"
|
||||
#include "xenia/base/math.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace hir {
|
||||
|
||||
Value::Use* Value::AddUse(poly::Arena* arena, Instr* instr) {
|
||||
Value::Use* Value::AddUse(Arena* arena, Instr* instr) {
|
||||
Use* use = arena->Alloc<Use>();
|
||||
use->instr = instr;
|
||||
use->prev = NULL;
|
||||
@@ -587,17 +587,17 @@ void Value::ByteSwap() {
|
||||
constant.i8 = constant.i8;
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
constant.i16 = poly::byte_swap(constant.i16);
|
||||
constant.i16 = xe::byte_swap(constant.i16);
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
constant.i32 = poly::byte_swap(constant.i32);
|
||||
constant.i32 = xe::byte_swap(constant.i32);
|
||||
break;
|
||||
case INT64_TYPE:
|
||||
constant.i64 = poly::byte_swap(constant.i64);
|
||||
constant.i64 = xe::byte_swap(constant.i64);
|
||||
break;
|
||||
case VEC128_TYPE:
|
||||
for (int n = 0; n < 4; n++) {
|
||||
constant.v128.u32[n] = poly::byte_swap(constant.v128.u32[n]);
|
||||
constant.v128.u32[n] = xe::byte_swap(constant.v128.u32[n]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -609,16 +609,16 @@ void Value::ByteSwap() {
|
||||
void Value::CountLeadingZeros(const Value* other) {
|
||||
switch (other->type) {
|
||||
case INT8_TYPE:
|
||||
constant.i8 = poly::lzcnt(constant.i8);
|
||||
constant.i8 = xe::lzcnt(constant.i8);
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
constant.i8 = poly::lzcnt(constant.i16);
|
||||
constant.i8 = xe::lzcnt(constant.i16);
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
constant.i8 = poly::lzcnt(constant.i32);
|
||||
constant.i8 = xe::lzcnt(constant.i32);
|
||||
break;
|
||||
case INT64_TYPE:
|
||||
constant.i8 = poly::lzcnt(constant.i64);
|
||||
constant.i8 = xe::lzcnt(constant.i64);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(type);
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
#ifndef XENIA_HIR_VALUE_H_
|
||||
#define XENIA_HIR_VALUE_H_
|
||||
|
||||
#include "poly/arena.h"
|
||||
#include "poly/assert.h"
|
||||
#include "poly/vec128.h"
|
||||
#include "xenia/base/arena.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/vec128.h"
|
||||
#include "xenia/cpu/backend/machine_info.h"
|
||||
#include "xenia/cpu/hir/opcodes.h"
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace hir {
|
||||
|
||||
class Instr;
|
||||
|
||||
using vec128_t = poly::vec128_t;
|
||||
using vec128_t = xe::vec128_t;
|
||||
|
||||
enum TypeName {
|
||||
// Many tables rely on this ordering.
|
||||
@@ -102,7 +102,7 @@ class Value {
|
||||
// TODO(benvanik): remove to shrink size.
|
||||
void* tag;
|
||||
|
||||
Use* AddUse(poly::Arena* arena, Instr* instr);
|
||||
Use* AddUse(Arena* arena, Instr* instr);
|
||||
void RemoveUse(Use* use);
|
||||
|
||||
int8_t get_constant(int8_t) const { return constant.i8; }
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
#include "xenia/cpu/mmio_handler.h"
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "poly/byte_order.h"
|
||||
#include "poly/math.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/byte_order.h"
|
||||
#include "xenia/base/math.h"
|
||||
|
||||
namespace BE {
|
||||
#include <beaengine/BeaEngine.h>
|
||||
@@ -230,7 +230,7 @@ bool MMIOHandler::HandleAccessFault(void* thread_state,
|
||||
// register.
|
||||
uint64_t value = range->read(range->context, fault_address & 0xFFFFFFFF);
|
||||
uint32_t be_reg_index;
|
||||
if (!poly::bit_scan_forward(arg1_type & 0xFFFF, &be_reg_index)) {
|
||||
if (!xe::bit_scan_forward(arg1_type & 0xFFFF, &be_reg_index)) {
|
||||
be_reg_index = 0;
|
||||
}
|
||||
uint64_t* reg_ptr = GetThreadStateRegPtr(thread_state, be_reg_index);
|
||||
@@ -239,13 +239,13 @@ bool MMIOHandler::HandleAccessFault(void* thread_state,
|
||||
*reg_ptr = static_cast<uint8_t>(value);
|
||||
break;
|
||||
case 16:
|
||||
*reg_ptr = poly::byte_swap(static_cast<uint16_t>(value));
|
||||
*reg_ptr = xe::byte_swap(static_cast<uint16_t>(value));
|
||||
break;
|
||||
case 32:
|
||||
*reg_ptr = poly::byte_swap(static_cast<uint32_t>(value));
|
||||
*reg_ptr = xe::byte_swap(static_cast<uint32_t>(value));
|
||||
break;
|
||||
case 64:
|
||||
*reg_ptr = poly::byte_swap(static_cast<uint64_t>(value));
|
||||
*reg_ptr = xe::byte_swap(static_cast<uint64_t>(value));
|
||||
break;
|
||||
}
|
||||
} else if (is_store) {
|
||||
@@ -253,7 +253,7 @@ bool MMIOHandler::HandleAccessFault(void* thread_state,
|
||||
uint64_t value;
|
||||
if ((arg2_type & BE::REGISTER_TYPE) == BE::REGISTER_TYPE) {
|
||||
uint32_t be_reg_index;
|
||||
if (!poly::bit_scan_forward(arg2_type & 0xFFFF, &be_reg_index)) {
|
||||
if (!xe::bit_scan_forward(arg2_type & 0xFFFF, &be_reg_index)) {
|
||||
be_reg_index = 0;
|
||||
}
|
||||
uint64_t* reg_ptr = GetThreadStateRegPtr(thread_state, be_reg_index);
|
||||
@@ -269,13 +269,13 @@ bool MMIOHandler::HandleAccessFault(void* thread_state,
|
||||
value = static_cast<uint8_t>(value);
|
||||
break;
|
||||
case 16:
|
||||
value = poly::byte_swap(static_cast<uint16_t>(value));
|
||||
value = xe::byte_swap(static_cast<uint16_t>(value));
|
||||
break;
|
||||
case 32:
|
||||
value = poly::byte_swap(static_cast<uint32_t>(value));
|
||||
value = xe::byte_swap(static_cast<uint32_t>(value));
|
||||
break;
|
||||
case 64:
|
||||
value = poly::byte_swap(static_cast<uint64_t>(value));
|
||||
value = xe::byte_swap(static_cast<uint64_t>(value));
|
||||
break;
|
||||
}
|
||||
range->write(range->context, fault_address & 0xFFFFFFFF, value);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "xenia/logging.h"
|
||||
#include "xenia/base/logging.h"
|
||||
|
||||
// Mach internal function, not defined in any header.
|
||||
// http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/exc_server.html
|
||||
@@ -117,7 +117,7 @@ void MachMMIOHandler::ThreadEntry() {
|
||||
listen_port_, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
if (ret != MACH_MSG_SUCCESS) {
|
||||
XELOGE("mach_msg receive failed with %d %s", ret, mach_error_string(ret));
|
||||
poly::debugging::Break();
|
||||
xe::debugging::Break();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ void MachMMIOHandler::ThreadEntry() {
|
||||
MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL) != MACH_MSG_SUCCESS) {
|
||||
XELOGE("mach_msg reply send failed");
|
||||
poly::debugging::Break();
|
||||
xe::debugging::Break();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -168,7 +168,7 @@ kern_return_t CatchExceptionRaise(mach_port_t thread) {
|
||||
XELOGE("MMIO unhandled bad access for %llx, bubbling", fault_address);
|
||||
// TODO(benvanik): manipulate stack so that we can rip = break_handler or
|
||||
// something and have the stack trace be valid.
|
||||
poly::debugging::Break();
|
||||
xe::debugging::Break();
|
||||
|
||||
// When the thread resumes, kill it.
|
||||
thread_state.__rip = reinterpret_cast<uint64_t>(FailBadAccess);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "poly/threading.h"
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
@@ -37,7 +37,7 @@ SymbolInfo* Module::LookupSymbol(uint32_t address, bool wait) {
|
||||
do {
|
||||
lock_.unlock();
|
||||
// TODO(benvanik): sleep for less time?
|
||||
poly::threading::Sleep(std::chrono::microseconds(100));
|
||||
xe::threading::Sleep(std::chrono::microseconds(100));
|
||||
lock_.lock();
|
||||
} while (symbol_info->status() == SymbolInfo::STATUS_DECLARING);
|
||||
} else {
|
||||
@@ -70,7 +70,7 @@ SymbolInfo::Status Module::DeclareSymbol(SymbolInfo::Type type,
|
||||
do {
|
||||
lock_.unlock();
|
||||
// TODO(benvanik): sleep for less time?
|
||||
poly::threading::Sleep(std::chrono::microseconds(100));
|
||||
xe::threading::Sleep(std::chrono::microseconds(100));
|
||||
lock_.lock();
|
||||
} while (symbol_info->status() == SymbolInfo::STATUS_DECLARING);
|
||||
}
|
||||
@@ -130,7 +130,7 @@ SymbolInfo::Status Module::DefineSymbol(SymbolInfo* symbol_info) {
|
||||
do {
|
||||
lock_.unlock();
|
||||
// TODO(benvanik): sleep for less time?
|
||||
poly::threading::Sleep(std::chrono::microseconds(100));
|
||||
xe::threading::Sleep(std::chrono::microseconds(100));
|
||||
lock_.lock();
|
||||
} while (symbol_info->status() == SymbolInfo::STATUS_DEFINING);
|
||||
status = symbol_info->status();
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
|
||||
#include "xenia/cpu/processor.h"
|
||||
|
||||
#include "poly/atomic.h"
|
||||
#include "poly/byte_order.h"
|
||||
#include "poly/memory.h"
|
||||
#include "xenia/base/atomic.h"
|
||||
#include "xenia/base/byte_order.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/memory.h"
|
||||
#include "xenia/cpu/cpu-private.h"
|
||||
#include "xenia/cpu/export_resolver.h"
|
||||
#include "xenia/cpu/runtime.h"
|
||||
#include "xenia/cpu/xex_module.h"
|
||||
#include "xenia/logging.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -151,13 +151,13 @@ uint64_t Processor::Execute(ThreadState* thread_state, uint32_t address,
|
||||
|
||||
Irql Processor::RaiseIrql(Irql new_value) {
|
||||
return static_cast<Irql>(
|
||||
poly::atomic_exchange(static_cast<uint32_t>(new_value),
|
||||
reinterpret_cast<volatile uint32_t*>(&irql_)));
|
||||
xe::atomic_exchange(static_cast<uint32_t>(new_value),
|
||||
reinterpret_cast<volatile uint32_t*>(&irql_)));
|
||||
}
|
||||
|
||||
void Processor::LowerIrql(Irql old_value) {
|
||||
poly::atomic_exchange(static_cast<uint32_t>(old_value),
|
||||
reinterpret_cast<volatile uint32_t*>(&irql_));
|
||||
xe::atomic_exchange(static_cast<uint32_t>(old_value),
|
||||
reinterpret_cast<volatile uint32_t*>(&irql_));
|
||||
}
|
||||
|
||||
uint64_t Processor::ExecuteInterrupt(uint32_t cpu, uint32_t address,
|
||||
@@ -168,7 +168,7 @@ uint64_t Processor::ExecuteInterrupt(uint32_t cpu, uint32_t address,
|
||||
std::lock_guard<std::mutex> lock(interrupt_thread_lock_);
|
||||
|
||||
// Set 0x10C(r13) to the current CPU ID.
|
||||
poly::store_and_swap<uint8_t>(
|
||||
xe::store_and_swap<uint8_t>(
|
||||
memory_->TranslateVirtual(interrupt_thread_block_ + 0x10C), cpu);
|
||||
|
||||
// Execute interrupt.
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
#include "xenia/cpu/raw_module.h"
|
||||
|
||||
#include "poly/platform.h"
|
||||
#include "poly/string.h"
|
||||
#include "xenia/base/platform.h"
|
||||
#include "xenia/base/string.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -21,7 +21,7 @@ RawModule::RawModule(Runtime* runtime)
|
||||
RawModule::~RawModule() {}
|
||||
|
||||
int RawModule::LoadFile(uint32_t base_address, const std::wstring& path) {
|
||||
auto fixed_path = poly::to_string(poly::fix_path_separators(path));
|
||||
auto fixed_path = xe::to_string(xe::fix_path_separators(path));
|
||||
FILE* file = fopen(fixed_path.c_str(), "rb");
|
||||
fseek(file, 0, SEEK_END);
|
||||
uint32_t file_length = static_cast<uint32_t>(ftell(file));
|
||||
@@ -39,7 +39,7 @@ int RawModule::LoadFile(uint32_t base_address, const std::wstring& path) {
|
||||
fclose(file);
|
||||
|
||||
// Setup debug info.
|
||||
auto last_slash = fixed_path.find_last_of(poly::path_separator);
|
||||
auto last_slash = fixed_path.find_last_of(xe::path_separator);
|
||||
if (last_slash != std::string::npos) {
|
||||
name_ = fixed_path.substr(last_slash + 1);
|
||||
} else {
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include "poly/assert.h"
|
||||
#include "xdb/protocol.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/cpu/frontend/ppc_frontend.h"
|
||||
#include "xenia/cpu/module.h"
|
||||
#include "xenia/cpu/thread_state.h"
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
#include "xenia/cpu/test/util.h"
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::test;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
using namespace poly;
|
||||
|
||||
TEST_CASE("BYTE_SWAP_V128", "[instr]") {
|
||||
TestFunction([](HIRBuilder& b) {
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::test;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
using namespace poly;
|
||||
|
||||
TEST_CASE("EXTRACT_INT8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::test;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
using namespace poly;
|
||||
|
||||
TEST_CASE("INSERT_INT8", "[instr]") {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
#include "xenia/cpu/test/util.h"
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::test;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
using namespace poly;
|
||||
|
||||
TEST_CASE("LOAD_VECTOR_SHL", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
#include "xenia/cpu/test/util.h"
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::test;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
using namespace poly;
|
||||
|
||||
TEST_CASE("PACK_D3DCOLOR", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
#include "xenia/cpu/test/util.h"
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::test;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
using namespace poly;
|
||||
|
||||
TEST_CASE("PERMUTE_V128_BY_INT32_CONSTANT", "[instr]") {
|
||||
{
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
#include "xenia/cpu/test/util.h"
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::test;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
using namespace poly;
|
||||
|
||||
TEST_CASE("SHR_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user