Removing IVM.
This commit is contained in:
parent
056d4ed9b0
commit
b8bb338564
|
@ -26,5 +26,4 @@ A backend takes optimized IR and assembles an implementation-specific result.
|
|||
The backend is also responsible for executing the code it generates and supporting
|
||||
debugging features (such as breakpoints).
|
||||
|
||||
* IVM: bytecode interpreter
|
||||
* x64: IA-64 with AVX2 code generator
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <alloy/backend/ivm/ivm_assembler.h>
|
||||
|
||||
#include <alloy/reset_scope.h>
|
||||
#include <alloy/backend/backend.h>
|
||||
#include <alloy/backend/ivm/ivm_intcode.h>
|
||||
#include <alloy/backend/ivm/ivm_function.h>
|
||||
#include <alloy/hir/hir_builder.h>
|
||||
#include <alloy/hir/label.h>
|
||||
#include <alloy/runtime/runtime.h>
|
||||
#include <xenia/profiling.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::runtime::DebugInfo;
|
||||
using alloy::runtime::Function;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
|
||||
IVMAssembler::IVMAssembler(Backend* backend)
|
||||
: Assembler(backend), source_map_arena_(128 * 1024) {}
|
||||
|
||||
IVMAssembler::~IVMAssembler() = default;
|
||||
|
||||
int IVMAssembler::Initialize() {
|
||||
int result = Assembler::Initialize();
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void IVMAssembler::Reset() {
|
||||
intcode_arena_.Reset();
|
||||
source_map_arena_.Reset();
|
||||
scratch_arena_.Reset();
|
||||
Assembler::Reset();
|
||||
}
|
||||
|
||||
int IVMAssembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<DebugInfo> debug_info,
|
||||
uint32_t trace_flags, Function** out_function) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Reset when we leave.
|
||||
make_reset_scope(this);
|
||||
|
||||
IVMFunction* fn = new IVMFunction(symbol_info);
|
||||
fn->set_debug_info(std::move(debug_info));
|
||||
|
||||
TranslationContext ctx;
|
||||
ctx.register_count = 0;
|
||||
ctx.intcode_count = 0;
|
||||
ctx.intcode_arena = &intcode_arena_;
|
||||
ctx.source_map_count = 0;
|
||||
ctx.source_map_arena = &source_map_arena_;
|
||||
ctx.scratch_arena = &scratch_arena_;
|
||||
ctx.label_ref_head = NULL;
|
||||
|
||||
// Reset label tags as we use them.
|
||||
builder->ResetLabelTags();
|
||||
|
||||
// Function prologue.
|
||||
size_t stack_offset = 0;
|
||||
auto locals = builder->locals();
|
||||
for (auto it = locals.begin(); it != locals.end(); ++it) {
|
||||
auto slot = *it;
|
||||
size_t type_size = GetTypeSize(slot->type);
|
||||
// Align to natural size.
|
||||
stack_offset = poly::align(stack_offset, type_size);
|
||||
slot->set_constant((uint32_t)stack_offset);
|
||||
stack_offset += type_size;
|
||||
}
|
||||
// Ensure 16b alignment.
|
||||
stack_offset = poly::align(stack_offset, static_cast<size_t>(16));
|
||||
ctx.stack_size = stack_offset;
|
||||
|
||||
auto block = builder->first_block();
|
||||
while (block) {
|
||||
auto label = block->label_head;
|
||||
while (label) {
|
||||
label->tag = (void*)(0x80000000 | ctx.intcode_count);
|
||||
label = label->next;
|
||||
}
|
||||
|
||||
auto i = block->instr_head;
|
||||
while (i) {
|
||||
TranslateIntCodes(ctx, i);
|
||||
i = i->next;
|
||||
}
|
||||
block = block->next;
|
||||
}
|
||||
|
||||
// Function epilogue.
|
||||
|
||||
// Fixup label references.
|
||||
LabelRef* label_ref = ctx.label_ref_head;
|
||||
while (label_ref) {
|
||||
label_ref->instr->src1_reg =
|
||||
(uint32_t)(intptr_t)label_ref->label->tag & ~0x80000000;
|
||||
label_ref = label_ref->next;
|
||||
}
|
||||
|
||||
fn->Setup(ctx);
|
||||
|
||||
*out_function = fn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
|
@ -1,44 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 ALLOY_BACKEND_IVM_IVM_ASSEMBLER_H_
|
||||
#define ALLOY_BACKEND_IVM_IVM_ASSEMBLER_H_
|
||||
|
||||
#include <alloy/arena.h>
|
||||
#include <alloy/backend/assembler.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
class IVMAssembler : public Assembler {
|
||||
public:
|
||||
IVMAssembler(Backend* backend);
|
||||
~IVMAssembler() override;
|
||||
|
||||
int Initialize() override;
|
||||
|
||||
void Reset() override;
|
||||
|
||||
int Assemble(runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<runtime::DebugInfo> debug_info,
|
||||
uint32_t trace_flags, runtime::Function** out_function) override;
|
||||
|
||||
private:
|
||||
Arena intcode_arena_;
|
||||
Arena source_map_arena_;
|
||||
Arena scratch_arena_;
|
||||
};
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
#endif // ALLOY_BACKEND_IVM_IVM_ASSEMBLER_H_
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <alloy/backend/ivm/ivm_backend.h>
|
||||
|
||||
#include <alloy/backend/ivm/ivm_assembler.h>
|
||||
#include <alloy/backend/ivm/ivm_stack.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
using alloy::runtime::Runtime;
|
||||
|
||||
IVMBackend::IVMBackend(Runtime* runtime) : Backend(runtime) {}
|
||||
|
||||
IVMBackend::~IVMBackend() = default;
|
||||
|
||||
int IVMBackend::Initialize() {
|
||||
int result = Backend::Initialize();
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
machine_info_.register_sets[0] = {
|
||||
0, "gpr", MachineInfo::RegisterSet::INT_TYPES, 16,
|
||||
};
|
||||
machine_info_.register_sets[1] = {
|
||||
1, "vec", MachineInfo::RegisterSet::FLOAT_TYPES |
|
||||
MachineInfo::RegisterSet::VEC_TYPES,
|
||||
16,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void* IVMBackend::AllocThreadData() { return new IVMStack(); }
|
||||
|
||||
void IVMBackend::FreeThreadData(void* thread_data) {
|
||||
auto stack = (IVMStack*)thread_data;
|
||||
delete stack;
|
||||
}
|
||||
|
||||
std::unique_ptr<Assembler> IVMBackend::CreateAssembler() {
|
||||
return std::make_unique<IVMAssembler>(this);
|
||||
}
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 ALLOY_BACKEND_IVM_IVM_BACKEND_H_
|
||||
#define ALLOY_BACKEND_IVM_IVM_BACKEND_H_
|
||||
|
||||
#include <alloy/backend/backend.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
#define ALLOY_HAS_IVM_BACKEND 1
|
||||
|
||||
class IVMBackend : public Backend {
|
||||
public:
|
||||
IVMBackend(runtime::Runtime* runtime);
|
||||
~IVMBackend() override;
|
||||
|
||||
int Initialize() override;
|
||||
|
||||
void* AllocThreadData() override;
|
||||
void FreeThreadData(void* thread_data) override;
|
||||
|
||||
std::unique_ptr<Assembler> CreateAssembler() override;
|
||||
};
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
#endif // ALLOY_BACKEND_IVM_IVM_BACKEND_H_
|
|
@ -1,176 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <alloy/backend/ivm/ivm_function.h>
|
||||
|
||||
#include <alloy/backend/ivm/ivm_stack.h>
|
||||
#include <alloy/runtime/runtime.h>
|
||||
#include <alloy/runtime/thread_state.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
using alloy::runtime::Breakpoint;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
using alloy::runtime::ThreadState;
|
||||
|
||||
IVMFunction::IVMFunction(FunctionInfo* symbol_info)
|
||||
: Function(symbol_info),
|
||||
register_count_(0),
|
||||
intcode_count_(0),
|
||||
intcodes_(nullptr),
|
||||
source_map_count_(0),
|
||||
source_map_(nullptr) {}
|
||||
|
||||
IVMFunction::~IVMFunction() {
|
||||
free(intcodes_);
|
||||
free(source_map_);
|
||||
}
|
||||
|
||||
void IVMFunction::Setup(TranslationContext& ctx) {
|
||||
register_count_ = ctx.register_count;
|
||||
stack_size_ = ctx.stack_size;
|
||||
intcode_count_ = ctx.intcode_count;
|
||||
intcodes_ = (IntCode*)ctx.intcode_arena->CloneContents();
|
||||
source_map_count_ = ctx.source_map_count;
|
||||
source_map_ = (SourceMapEntry*)ctx.source_map_arena->CloneContents();
|
||||
}
|
||||
|
||||
IntCode* IVMFunction::GetIntCodeAtSourceOffset(uint64_t offset) {
|
||||
for (size_t n = 0; n < source_map_count_; n++) {
|
||||
auto entry = &source_map_[n];
|
||||
if (entry->source_offset == offset) {
|
||||
return &intcodes_[entry->intcode_index];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int IVMFunction::AddBreakpointImpl(Breakpoint* breakpoint) {
|
||||
auto i = GetIntCodeAtSourceOffset(breakpoint->address());
|
||||
if (!i) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TEMP breakpoints always overwrite normal ones.
|
||||
if (!i->debug_flags || breakpoint->type() == Breakpoint::TEMP_TYPE) {
|
||||
uint64_t breakpoint_ptr = (uint64_t)breakpoint;
|
||||
i->src2_reg = (uint32_t)breakpoint_ptr;
|
||||
i->src3_reg = (uint32_t)(breakpoint_ptr >> 32);
|
||||
}
|
||||
|
||||
// Increment breakpoint counter.
|
||||
++i->debug_flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IVMFunction::RemoveBreakpointImpl(Breakpoint* breakpoint) {
|
||||
auto i = GetIntCodeAtSourceOffset(breakpoint->address());
|
||||
if (!i) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Decrement breakpoint counter.
|
||||
--i->debug_flags;
|
||||
i->src2_reg = i->src3_reg = 0;
|
||||
|
||||
// If there were other breakpoints, see what they were.
|
||||
if (i->debug_flags) {
|
||||
auto old_breakpoint = FindBreakpoint(breakpoint->address());
|
||||
if (old_breakpoint) {
|
||||
uint64_t breakpoint_ptr = (uint64_t)old_breakpoint;
|
||||
i->src2_reg = (uint32_t)breakpoint_ptr;
|
||||
i->src3_reg = (uint32_t)(breakpoint_ptr >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IVMFunction::OnBreakpointHit(ThreadState* thread_state, IntCode* i) {
|
||||
uint64_t breakpoint_ptr = i->src2_reg | (uint64_t(i->src3_reg) << 32);
|
||||
Breakpoint* breakpoint = (Breakpoint*)breakpoint_ptr;
|
||||
|
||||
// Notify debugger.
|
||||
// The debugger may choose to wait (blocking us).
|
||||
auto debugger = thread_state->runtime()->debugger();
|
||||
debugger->OnBreakpointHit(thread_state, breakpoint);
|
||||
}
|
||||
|
||||
#undef TRACE_SOURCE_OFFSET
|
||||
|
||||
int IVMFunction::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
||||
// Setup register file on stack.
|
||||
auto stack = (IVMStack*)thread_state->backend_data();
|
||||
auto register_file = (Register*)stack->Alloc(register_count_);
|
||||
auto local_stack = (uint8_t*)alloca(stack_size_);
|
||||
|
||||
Memory* memory = thread_state->memory();
|
||||
|
||||
IntCodeState ics;
|
||||
ics.rf = register_file;
|
||||
ics.locals = local_stack;
|
||||
ics.context = (uint8_t*)thread_state->raw_context();
|
||||
ics.membase = memory->membase();
|
||||
ics.did_carry = 0;
|
||||
ics.did_saturate = 0;
|
||||
ics.thread_state = thread_state;
|
||||
ics.return_address = return_address;
|
||||
ics.call_return_address = 0;
|
||||
|
||||
// TODO(benvanik): DID_CARRY -- need HIR to set a OPCODE_FLAG_SET_CARRY
|
||||
// or something so the fns can set an ics flag.
|
||||
|
||||
#ifdef TRACE_SOURCE_OFFSET
|
||||
size_t source_index = 0;
|
||||
#endif
|
||||
|
||||
uint32_t ia = 0;
|
||||
while (true) {
|
||||
#ifdef TRACE_SOURCE_OFFSET
|
||||
uint64_t source_offset = -1;
|
||||
if (source_index < this->source_map_count_ &&
|
||||
this->source_map_[source_index].intcode_index <= ia) {
|
||||
while (source_index + 1 < this->source_map_count_ &&
|
||||
this->source_map_[source_index + 1].intcode_index <= ia) {
|
||||
source_index++;
|
||||
}
|
||||
source_offset = this->source_map_[source_index].source_offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
IntCode* i = &intcodes_[ia];
|
||||
|
||||
if (i->debug_flags) {
|
||||
OnBreakpointHit(thread_state, i);
|
||||
}
|
||||
|
||||
uint32_t new_ia = i->intcode_fn(ics, i);
|
||||
if (new_ia == IA_NEXT) {
|
||||
ia++;
|
||||
} else if (new_ia == IA_RETURN) {
|
||||
break;
|
||||
} else {
|
||||
ia = new_ia;
|
||||
#ifdef TRACE_SOURCE_OFFSET
|
||||
source_index = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
stack->Free(register_count_);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
|
@ -1,51 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 ALLOY_BACKEND_IVM_IVM_FUNCTION_H_
|
||||
#define ALLOY_BACKEND_IVM_IVM_FUNCTION_H_
|
||||
|
||||
#include <alloy/backend/ivm/ivm_intcode.h>
|
||||
#include <alloy/runtime/function.h>
|
||||
#include <alloy/runtime/symbol_info.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
class IVMFunction : public runtime::Function {
|
||||
public:
|
||||
IVMFunction(runtime::FunctionInfo* symbol_info);
|
||||
virtual ~IVMFunction();
|
||||
|
||||
void Setup(TranslationContext& ctx);
|
||||
|
||||
protected:
|
||||
virtual int AddBreakpointImpl(runtime::Breakpoint* breakpoint);
|
||||
virtual int RemoveBreakpointImpl(runtime::Breakpoint* breakpoint);
|
||||
virtual int CallImpl(runtime::ThreadState* thread_state,
|
||||
uint64_t return_address);
|
||||
|
||||
private:
|
||||
IntCode* GetIntCodeAtSourceOffset(uint64_t offset);
|
||||
void OnBreakpointHit(runtime::ThreadState* thread_state, IntCode* i);
|
||||
|
||||
private:
|
||||
size_t register_count_;
|
||||
size_t stack_size_;
|
||||
size_t intcode_count_;
|
||||
IntCode* intcodes_;
|
||||
size_t source_map_count_;
|
||||
SourceMapEntry* source_map_;
|
||||
};
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
#endif // ALLOY_BACKEND_IVM_IVM_FUNCTION_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -1,107 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 ALLOY_BACKEND_IVM_INTCODE_H_
|
||||
#define ALLOY_BACKEND_IVM_INTCODE_H_
|
||||
|
||||
#include <alloy/hir/instr.h>
|
||||
#include <alloy/hir/opcodes.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace runtime {
|
||||
class ThreadState;
|
||||
} // namespace runtime
|
||||
} // namespace alloy
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
typedef union {
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
int16_t i16;
|
||||
uint16_t u16;
|
||||
int32_t i32;
|
||||
uint32_t u32;
|
||||
int64_t i64;
|
||||
uint64_t u64;
|
||||
float f32;
|
||||
double f64;
|
||||
vec128_t v128;
|
||||
} Register;
|
||||
|
||||
typedef struct {
|
||||
Register* rf;
|
||||
uint8_t* locals;
|
||||
uint8_t* context;
|
||||
uint8_t* membase;
|
||||
int8_t did_carry;
|
||||
int8_t did_saturate;
|
||||
runtime::ThreadState* thread_state;
|
||||
uint64_t return_address;
|
||||
uint64_t call_return_address;
|
||||
} IntCodeState;
|
||||
|
||||
struct IntCode_s;
|
||||
typedef uint32_t (*IntCodeFn)(IntCodeState& ics, const struct IntCode_s* i);
|
||||
|
||||
#define IA_RETURN 0xA0000000
|
||||
#define IA_NEXT 0xB0000000
|
||||
|
||||
typedef struct IntCode_s {
|
||||
IntCodeFn intcode_fn;
|
||||
uint16_t flags;
|
||||
uint16_t debug_flags;
|
||||
|
||||
uint32_t dest_reg;
|
||||
union {
|
||||
struct {
|
||||
uint32_t src1_reg;
|
||||
uint32_t src2_reg;
|
||||
uint32_t src3_reg;
|
||||
// <4 bytes available>
|
||||
};
|
||||
struct {
|
||||
Register constant;
|
||||
};
|
||||
};
|
||||
|
||||
// debugging info/etc
|
||||
} IntCode;
|
||||
|
||||
typedef struct LabelRef_s {
|
||||
hir::Label* label;
|
||||
IntCode* instr;
|
||||
LabelRef_s* next;
|
||||
} LabelRef;
|
||||
|
||||
typedef struct SourceMapEntry_s {
|
||||
uint64_t source_offset;
|
||||
uint64_t intcode_index;
|
||||
} SourceMapEntry;
|
||||
|
||||
typedef struct {
|
||||
uint32_t register_count;
|
||||
size_t intcode_count;
|
||||
Arena* intcode_arena;
|
||||
size_t source_map_count;
|
||||
Arena* source_map_arena;
|
||||
Arena* scratch_arena;
|
||||
LabelRef* label_ref_head;
|
||||
size_t stack_size;
|
||||
} TranslationContext;
|
||||
|
||||
int TranslateIntCodes(TranslationContext& ctx, hir::Instr* i);
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
#endif // ALLOY_BACKEND_IVM_INTCODE_H_
|
|
@ -1,79 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <alloy/backend/ivm/ivm_stack.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
IVMStack::IVMStack()
|
||||
: chunk_size_(2 * 1024 * 1024), head_chunk_(NULL), active_chunk_(NULL) {}
|
||||
|
||||
IVMStack::~IVMStack() {
|
||||
Chunk* chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
Chunk* next = chunk->next;
|
||||
delete chunk;
|
||||
chunk = next;
|
||||
}
|
||||
head_chunk_ = NULL;
|
||||
}
|
||||
|
||||
Register* IVMStack::Alloc(size_t register_count) {
|
||||
size_t size = register_count * sizeof(Register);
|
||||
if (active_chunk_) {
|
||||
if (active_chunk_->capacity - active_chunk_->offset < size) {
|
||||
Chunk* next = active_chunk_->next;
|
||||
if (!next) {
|
||||
assert_true(size < chunk_size_, "need to support larger chunks");
|
||||
next = new Chunk(chunk_size_);
|
||||
next->prev = active_chunk_;
|
||||
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 (Register*)p;
|
||||
}
|
||||
|
||||
void IVMStack::Free(size_t register_count) {
|
||||
size_t size = register_count * sizeof(Register);
|
||||
if (active_chunk_->offset == size) {
|
||||
// Moving back a chunk.
|
||||
active_chunk_->offset = 0;
|
||||
if (active_chunk_->prev) {
|
||||
active_chunk_ = active_chunk_->prev;
|
||||
}
|
||||
} else {
|
||||
// Still in same chunk.
|
||||
active_chunk_->offset -= size;
|
||||
}
|
||||
}
|
||||
|
||||
IVMStack::Chunk::Chunk(size_t chunk_size)
|
||||
: prev(NULL), next(NULL), capacity(chunk_size), buffer(0), offset(0) {
|
||||
buffer = reinterpret_cast<uint8_t*>(malloc(capacity));
|
||||
}
|
||||
|
||||
IVMStack::Chunk::~Chunk() {
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
|
@ -1,51 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 ALLOY_BACKEND_IVM_IVM_STACK_H_
|
||||
#define ALLOY_BACKEND_IVM_IVM_STACK_H_
|
||||
|
||||
#include <alloy/backend/ivm/ivm_intcode.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
class IVMStack {
|
||||
public:
|
||||
IVMStack();
|
||||
~IVMStack();
|
||||
|
||||
Register* Alloc(size_t register_count);
|
||||
void Free(size_t register_count);
|
||||
|
||||
private:
|
||||
class Chunk {
|
||||
public:
|
||||
Chunk(size_t chunk_size);
|
||||
~Chunk();
|
||||
|
||||
Chunk* prev;
|
||||
Chunk* next;
|
||||
|
||||
size_t capacity;
|
||||
uint8_t* buffer;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
private:
|
||||
size_t chunk_size_;
|
||||
Chunk* head_chunk_;
|
||||
Chunk* active_chunk_;
|
||||
};
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
#endif // ALLOY_BACKEND_IVM_IVM_STACK_H_
|
|
@ -1,15 +0,0 @@
|
|||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'ivm_intcode.cc',
|
||||
'ivm_intcode.h',
|
||||
'ivm_assembler.cc',
|
||||
'ivm_assembler.h',
|
||||
'ivm_backend.cc',
|
||||
'ivm_backend.h',
|
||||
'ivm_function.cc',
|
||||
'ivm_function.h',
|
||||
'ivm_stack.cc',
|
||||
'ivm_stack.h',
|
||||
],
|
||||
}
|
|
@ -9,7 +9,6 @@
|
|||
],
|
||||
|
||||
'includes': [
|
||||
'ivm/sources.gypi',
|
||||
'x64/sources.gypi',
|
||||
],
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
|
||||
#include <alloy/alloy.h>
|
||||
#include <alloy/backend/ivm/ivm_backend.h>
|
||||
#include <alloy/backend/x64/x64_backend.h>
|
||||
#include <alloy/frontend/ppc/ppc_context.h>
|
||||
#include <alloy/frontend/ppc/ppc_frontend.h>
|
||||
|
|
|
@ -73,36 +73,4 @@ SimpleMemory::SimpleMemory(size_t capacity) : memory_(capacity) {
|
|||
|
||||
SimpleMemory::~SimpleMemory() = default;
|
||||
|
||||
uint8_t SimpleMemory::LoadI8(uint64_t address) {
|
||||
return poly::load<uint8_t>(membase_ + address);
|
||||
}
|
||||
|
||||
uint16_t SimpleMemory::LoadI16(uint64_t address) {
|
||||
return poly::load<uint16_t>(membase_ + address);
|
||||
}
|
||||
|
||||
uint32_t SimpleMemory::LoadI32(uint64_t address) {
|
||||
return poly::load<uint32_t>(membase_ + address);
|
||||
}
|
||||
|
||||
uint64_t SimpleMemory::LoadI64(uint64_t address) {
|
||||
return poly::load<uint64_t>(membase_ + address);
|
||||
}
|
||||
|
||||
void SimpleMemory::StoreI8(uint64_t address, uint8_t value) {
|
||||
poly::store<uint8_t>(membase_ + address, value);
|
||||
}
|
||||
|
||||
void SimpleMemory::StoreI16(uint64_t address, uint16_t value) {
|
||||
poly::store<uint16_t>(membase_ + address, value);
|
||||
}
|
||||
|
||||
void SimpleMemory::StoreI32(uint64_t address, uint32_t value) {
|
||||
poly::store<uint32_t>(membase_ + address, value);
|
||||
}
|
||||
|
||||
void SimpleMemory::StoreI64(uint64_t address, uint64_t value) {
|
||||
poly::store<uint64_t>(membase_ + address, value);
|
||||
}
|
||||
|
||||
} // namespace alloy
|
||||
|
|
|
@ -40,16 +40,6 @@ class Memory {
|
|||
uint64_t SearchAligned(uint64_t start, uint64_t end, const uint32_t* values,
|
||||
size_t value_count);
|
||||
|
||||
// TODO(benvanik): remove with IVM.
|
||||
virtual uint8_t LoadI8(uint64_t address) = 0;
|
||||
virtual uint16_t LoadI16(uint64_t address) = 0;
|
||||
virtual uint32_t LoadI32(uint64_t address) = 0;
|
||||
virtual uint64_t LoadI64(uint64_t address) = 0;
|
||||
virtual void StoreI8(uint64_t address, uint8_t value) = 0;
|
||||
virtual void StoreI16(uint64_t address, uint16_t value) = 0;
|
||||
virtual void StoreI32(uint64_t address, uint32_t value) = 0;
|
||||
virtual void StoreI64(uint64_t address, uint64_t value) = 0;
|
||||
|
||||
protected:
|
||||
size_t system_page_size_;
|
||||
uint8_t* membase_;
|
||||
|
@ -63,16 +53,6 @@ class SimpleMemory : public Memory {
|
|||
SimpleMemory(size_t capacity);
|
||||
~SimpleMemory() override;
|
||||
|
||||
// TODO(benvanik): remove with IVM.
|
||||
uint8_t LoadI8(uint64_t address) override;
|
||||
uint16_t LoadI16(uint64_t address) override;
|
||||
uint32_t LoadI32(uint64_t address) override;
|
||||
uint64_t LoadI64(uint64_t address) override;
|
||||
void StoreI8(uint64_t address, uint8_t value) override;
|
||||
void StoreI16(uint64_t address, uint16_t value) override;
|
||||
void StoreI32(uint64_t address, uint32_t value) override;
|
||||
void StoreI64(uint64_t address, uint64_t value) override;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> memory_;
|
||||
};
|
||||
|
|
|
@ -53,7 +53,6 @@ bool FunctionInstrument::Attach() {
|
|||
|
||||
// Function impl attach:
|
||||
// - add instrument to list
|
||||
// IVM: handle in Call()
|
||||
// JIT: transition to instrumented state
|
||||
// - rewrite enter/exit to jump to instrumentation thunk
|
||||
// - some sort of locking required?
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
#include <xenia/profiling.h>
|
||||
|
||||
// TODO(benvanik): based on compiler support
|
||||
#include <alloy/backend/ivm/ivm_backend.h>
|
||||
#include <alloy/backend/x64/x64_backend.h>
|
||||
|
||||
DEFINE_string(runtime_backend, "any", "Runtime backend [any, ivm, x64].");
|
||||
DEFINE_string(runtime_backend, "any", "Runtime backend [any, x64].");
|
||||
|
||||
namespace alloy {
|
||||
namespace runtime {
|
||||
|
@ -81,22 +80,12 @@ int Runtime::Initialize(std::unique_ptr<Frontend> frontend,
|
|||
backend.reset(new alloy::backend::x64::X64Backend(this));
|
||||
}
|
||||
#endif // ALLOY_HAS_X64_BACKEND
|
||||
#if defined(ALLOY_HAS_IVM_BACKEND) && ALLOY_HAS_IVM_BACKEND
|
||||
if (FLAGS_runtime_backend == "ivm") {
|
||||
backend.reset(new alloy::backend::ivm::IVMBackend(this));
|
||||
}
|
||||
#endif // ALLOY_HAS_IVM_BACKEND
|
||||
if (FLAGS_runtime_backend == "any") {
|
||||
#if defined(ALLOY_HAS_X64_BACKEND) && ALLOY_HAS_X64_BACKEND
|
||||
if (!backend) {
|
||||
backend.reset(new alloy::backend::x64::X64Backend(this));
|
||||
}
|
||||
#endif // ALLOY_HAS_X64_BACKEND
|
||||
#if defined(ALLOY_HAS_IVM_BACKEND) && ALLOY_HAS_IVM_BACKEND
|
||||
if (!backend) {
|
||||
backend.reset(new alloy::backend::ivm::IVMBackend(this));
|
||||
}
|
||||
#endif // ALLOY_HAS_IVM_BACKEND
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
|
||||
#include <alloy/alloy.h>
|
||||
#include <alloy/backend/ivm/ivm_backend.h>
|
||||
#include <alloy/backend/x64/x64_backend.h>
|
||||
#include <alloy/frontend/ppc/ppc_context.h>
|
||||
#include <alloy/frontend/ppc/ppc_frontend.h>
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define ALLOY_TEST_UTIL_H_
|
||||
|
||||
#include <alloy/alloy.h>
|
||||
#include <alloy/backend/ivm/ivm_backend.h>
|
||||
#include <alloy/backend/x64/x64_backend.h>
|
||||
#include <alloy/frontend/ppc/ppc_context.h>
|
||||
#include <alloy/frontend/ppc/ppc_frontend.h>
|
||||
|
@ -22,7 +21,6 @@
|
|||
|
||||
#include <third_party/catch/single_include/catch.hpp>
|
||||
|
||||
#define ALLOY_TEST_IVM 1
|
||||
#define ALLOY_TEST_X64 1
|
||||
|
||||
namespace alloy {
|
||||
|
@ -86,17 +84,6 @@ class TestFunction {
|
|||
memory_size = 16 * 1024 * 1024;
|
||||
memory.reset(new SimpleMemory(memory_size));
|
||||
|
||||
#if ALLOY_TEST_IVM
|
||||
{
|
||||
auto runtime = std::make_unique<Runtime>(memory.get());
|
||||
auto frontend =
|
||||
std::make_unique<alloy::frontend::ppc::PPCFrontend>(runtime.get());
|
||||
auto backend =
|
||||
std::make_unique<alloy::backend::ivm::IVMBackend>(runtime.get());
|
||||
runtime->Initialize(std::move(frontend), std::move(backend));
|
||||
runtimes.emplace_back(std::move(runtime));
|
||||
}
|
||||
#endif // ALLOY_TEST_IVM
|
||||
#if ALLOY_TEST_X64
|
||||
{
|
||||
auto runtime = std::make_unique<Runtime>(memory.get());
|
||||
|
|
|
@ -90,7 +90,6 @@ int Processor::Setup() {
|
|||
}
|
||||
|
||||
std::unique_ptr<Backend> backend;
|
||||
// backend.reset(new alloy::backend::ivm::IVMBackend(runtime));
|
||||
// backend.reset(new alloy::backend::x64::X64Backend(runtime));
|
||||
int result = runtime_->Initialize(std::move(backend));
|
||||
if (result) {
|
||||
|
|
|
@ -203,8 +203,8 @@ int Memory::Initialize() {
|
|||
|
||||
// I have no idea what this is, but games try to read/write there.
|
||||
VirtualAlloc(Translate(0x40000000), 0x00010000, MEM_COMMIT, PAGE_READWRITE);
|
||||
StoreI32(0x40000000, 0x00C40000);
|
||||
StoreI32(0x40000004, 0x00010000);
|
||||
poly::store_and_swap<uint32_t>(Translate(0x40000000), 0x00C40000);
|
||||
poly::store_and_swap<uint32_t>(Translate(0x40000004), 0x00010000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -286,62 +286,6 @@ void Memory::CancelWriteWatch(uintptr_t watch_handle) {
|
|||
mmio_handler_->CancelWriteWatch(watch_handle);
|
||||
}
|
||||
|
||||
uint8_t Memory::LoadI8(uint64_t address) {
|
||||
uint64_t value;
|
||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||
value = *reinterpret_cast<uint8_t*>(Translate(address));
|
||||
}
|
||||
return static_cast<uint8_t>(value);
|
||||
}
|
||||
|
||||
uint16_t Memory::LoadI16(uint64_t address) {
|
||||
uint64_t value;
|
||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||
value = *reinterpret_cast<uint16_t*>(Translate(address));
|
||||
}
|
||||
return static_cast<uint16_t>(value);
|
||||
}
|
||||
|
||||
uint32_t Memory::LoadI32(uint64_t address) {
|
||||
uint64_t value;
|
||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||
value = *reinterpret_cast<uint32_t*>(Translate(address));
|
||||
}
|
||||
return static_cast<uint32_t>(value);
|
||||
}
|
||||
|
||||
uint64_t Memory::LoadI64(uint64_t address) {
|
||||
uint64_t value;
|
||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||
value = *reinterpret_cast<uint64_t*>(Translate(address));
|
||||
}
|
||||
return static_cast<uint64_t>(value);
|
||||
}
|
||||
|
||||
void Memory::StoreI8(uint64_t address, uint8_t value) {
|
||||
if (!mmio_handler_->CheckStore(address, value)) {
|
||||
*reinterpret_cast<uint8_t*>(Translate(address)) = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Memory::StoreI16(uint64_t address, uint16_t value) {
|
||||
if (!mmio_handler_->CheckStore(address, value)) {
|
||||
*reinterpret_cast<uint16_t*>(Translate(address)) = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Memory::StoreI32(uint64_t address, uint32_t value) {
|
||||
if (!mmio_handler_->CheckStore(address, value)) {
|
||||
*reinterpret_cast<uint32_t*>(Translate(address)) = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Memory::StoreI64(uint64_t address, uint64_t value) {
|
||||
if (!mmio_handler_->CheckStore(address, value)) {
|
||||
*reinterpret_cast<uint64_t*>(Translate(address)) = value;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Memory::HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||
uint32_t alignment) {
|
||||
// If we were given a base address we are outside of the normal heap and
|
||||
|
|
|
@ -58,15 +58,6 @@ class Memory : public alloy::Memory {
|
|||
void* callback_context, void* callback_data);
|
||||
void CancelWriteWatch(uintptr_t watch_handle);
|
||||
|
||||
uint8_t LoadI8(uint64_t address) override;
|
||||
uint16_t LoadI16(uint64_t address) override;
|
||||
uint32_t LoadI32(uint64_t address) override;
|
||||
uint64_t LoadI64(uint64_t address) override;
|
||||
void StoreI8(uint64_t address, uint8_t value) override;
|
||||
void StoreI16(uint64_t address, uint16_t value) override;
|
||||
void StoreI32(uint64_t address, uint32_t value) override;
|
||||
void StoreI64(uint64_t address, uint64_t value) override;
|
||||
|
||||
uint64_t HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||
uint32_t alignment = 0x20);
|
||||
int HeapFree(uint64_t address, size_t size);
|
||||
|
|
Loading…
Reference in New Issue