Code cleanup: moving poly/ into xenia/base/

This commit is contained in:
Ben Vanik
2015-05-02 03:42:51 -07:00
parent 99816056be
commit e3220f7ae6
223 changed files with 1758 additions and 1881 deletions

View File

@@ -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;

View File

@@ -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
View 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
View 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
View 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
View 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
View 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_

View 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_

View 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_

View 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_

View 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

View 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
View 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
View 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
View 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
View 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

View File

@@ -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);
}

View File

@@ -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
View 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_

View 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
View 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

View 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_

View 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

View 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
View 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
View 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
View 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_

View 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
View 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_

View 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_

View 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
View 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
View 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_

View 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

View 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_

View 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

View 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_

View 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

View 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

View 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

View 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
View 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_

View File

@@ -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;

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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_;

View File

@@ -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));
}

View File

@@ -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

View File

@@ -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_;
};

View File

@@ -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();
}

View File

@@ -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_;

View File

@@ -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"

View File

@@ -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

View File

@@ -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"

View File

@@ -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!

View File

@@ -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"

View File

@@ -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"

View File

@@ -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_;

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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;

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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_;

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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_);
}

View File

@@ -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_;

View File

@@ -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);

View File

@@ -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; }

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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.

View File

@@ -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 {

View File

@@ -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"

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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]") {
{

View File

@@ -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