Place all XMM constants in memory so we can avoid clobbering rax.
This commit is contained in:
parent
329a03e7c4
commit
0ffd8bbedd
|
@ -13,6 +13,7 @@
|
|||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
||||
#include "xenia/cpu/backend/x64/x64_thunk_emitter.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
@ -20,9 +21,15 @@ namespace backend {
|
|||
namespace x64 {
|
||||
|
||||
X64Backend::X64Backend(Processor* processor)
|
||||
: Backend(processor), code_cache_(nullptr) {}
|
||||
: Backend(processor), code_cache_(nullptr), emitter_data_(0) {}
|
||||
|
||||
X64Backend::~X64Backend() { delete code_cache_; }
|
||||
X64Backend::~X64Backend() {
|
||||
if (emitter_data_) {
|
||||
processor()->memory()->SystemHeapFree(emitter_data_);
|
||||
emitter_data_ = 0;
|
||||
}
|
||||
delete code_cache_;
|
||||
}
|
||||
|
||||
bool X64Backend::Initialize() {
|
||||
if (!Backend::Initialize()) {
|
||||
|
@ -61,6 +68,9 @@ bool X64Backend::Initialize() {
|
|||
// Allocate some special indirections.
|
||||
code_cache_->CommitExecutableRange(0x9FFF0000, 0x9FFFFFFF);
|
||||
|
||||
// Allocate emitter constant data.
|
||||
emitter_data_ = X64Emitter::PlaceData(processor()->memory());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ class X64Backend : public Backend {
|
|||
~X64Backend() override;
|
||||
|
||||
X64CodeCache* code_cache() const { return code_cache_; }
|
||||
uint32_t emitter_data() const { return emitter_data_; }
|
||||
HostToGuestThunk host_to_guest_thunk() const { return host_to_guest_thunk_; }
|
||||
GuestToHostThunk guest_to_host_thunk() const { return guest_to_host_thunk_; }
|
||||
ResolveFunctionThunk resolve_function_thunk() const {
|
||||
|
@ -48,6 +49,8 @@ class X64Backend : public Backend {
|
|||
private:
|
||||
X64CodeCache* code_cache_;
|
||||
|
||||
uint32_t emitter_data_;
|
||||
|
||||
HostToGuestThunk host_to_guest_thunk_;
|
||||
GuestToHostThunk guest_to_host_thunk_;
|
||||
ResolveFunctionThunk resolve_function_thunk_;
|
||||
|
|
|
@ -300,6 +300,40 @@ void X64CodeCache::InitializeUnwindEntry(uint8_t* unwind_entry_address,
|
|||
fn_entry.UnwindData = (DWORD)(unwind_entry_address - generated_code_base_);
|
||||
}
|
||||
|
||||
uint32_t X64CodeCache::PlaceData(const void* data, size_t length) {
|
||||
// Hold a lock while we bump the pointers up.
|
||||
size_t high_mark;
|
||||
uint8_t* data_address = nullptr;
|
||||
size_t unwind_table_slot = 0;
|
||||
{
|
||||
std::lock_guard<xe::mutex> allocation_lock(allocation_mutex_);
|
||||
|
||||
// Reserve code.
|
||||
// Always move the code to land on 16b alignment.
|
||||
data_address = generated_code_base_ + generated_code_offset_;
|
||||
generated_code_offset_ += xe::round_up(length, 16);
|
||||
|
||||
high_mark = generated_code_offset_;
|
||||
}
|
||||
|
||||
// If we are going above the high water mark of committed memory, commit some
|
||||
// more. It's ok if multiple threads do this, as redundant commits aren't
|
||||
// harmful.
|
||||
size_t old_commit_mark = generated_code_commit_mark_;
|
||||
if (high_mark > old_commit_mark) {
|
||||
size_t new_commit_mark = old_commit_mark + 16 * 1024 * 1024;
|
||||
VirtualAlloc(generated_code_base_, new_commit_mark, MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
generated_code_commit_mark_.compare_exchange_strong(old_commit_mark,
|
||||
new_commit_mark);
|
||||
}
|
||||
|
||||
// Copy code.
|
||||
std::memcpy(data_address, data, length);
|
||||
|
||||
return uint32_t(uintptr_t(data_address));
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace cpu
|
||||
|
|
|
@ -36,7 +36,6 @@ class X64CodeCache {
|
|||
// TODO(benvanik): padding/guards/etc
|
||||
|
||||
void set_indirection_default(uint32_t default_value);
|
||||
|
||||
void AddIndirection(uint32_t guest_address, uint32_t host_address);
|
||||
|
||||
void CommitExecutableRange(uint32_t guest_low, uint32_t guest_high);
|
||||
|
@ -44,6 +43,8 @@ class X64CodeCache {
|
|||
void* PlaceCode(uint32_t guest_address, void* machine_code, size_t code_size,
|
||||
size_t stack_size);
|
||||
|
||||
uint32_t PlaceData(const void* data, size_t length);
|
||||
|
||||
private:
|
||||
const static uint64_t kIndirectionTableBase = 0x80000000;
|
||||
const static uint64_t kIndirectionTableSize = 0x1FFFFFFF;
|
||||
|
|
|
@ -583,7 +583,7 @@ void X64Emitter::MovMem64(const RegExp& addr, uint64_t v) {
|
|||
}
|
||||
}
|
||||
|
||||
Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
||||
uint32_t X64Emitter::PlaceData(Memory* memory) {
|
||||
static const vec128_t xmm_consts[] = {
|
||||
/* XMMZero */ vec128f(0.0f),
|
||||
/* XMMOne */ vec128f(1.0f),
|
||||
|
@ -659,12 +659,14 @@ Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
|||
/* XMMShortMinPS */ vec128f(SHRT_MIN),
|
||||
/* XMMShortMaxPS */ vec128f(SHRT_MAX),
|
||||
};
|
||||
// TODO(benvanik): cache base pointer somewhere? stack? It'd be nice to
|
||||
// prevent this move.
|
||||
// TODO(benvanik): move to predictable location in PPCContext? could then
|
||||
// just do rcx relative addression with no rax overwriting.
|
||||
mov(rax, (uint64_t)&xmm_consts[id]);
|
||||
return ptr[rax];
|
||||
uint32_t ptr = memory->SystemHeapAlloc(sizeof(xmm_consts));
|
||||
std::memcpy(memory->TranslateVirtual(ptr), xmm_consts, sizeof(xmm_consts));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
||||
// Load through fixed constant table setup by PlaceData.
|
||||
return ptr[rdx + backend_->emitter_data() + sizeof(vec128_t) * id];
|
||||
}
|
||||
|
||||
void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, const vec128_t& v) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "xenia/base/arena.h"
|
||||
#include "xenia/cpu/hir/value.h"
|
||||
#include "xenia/debug/function_trace_data.h"
|
||||
#include "xenia/memory.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
@ -117,6 +118,8 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
|||
uint32_t debug_info_flags, DebugInfo* debug_info,
|
||||
void*& out_code_address, size_t& out_code_size);
|
||||
|
||||
static uint32_t PlaceData(Memory* memory);
|
||||
|
||||
public:
|
||||
// Reserved: rsp
|
||||
// Scratch: rax/rcx/rdx
|
||||
|
|
Loading…
Reference in New Issue