Running clang-format on alloy.
All except x64_sequences, which needs work.
This commit is contained in:
parent
0158380cfc
commit
7daa85179c
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
|
||||||
DECLARE_bool(debug);
|
DECLARE_bool(debug);
|
||||||
DECLARE_bool(always_disasm);
|
DECLARE_bool(always_disasm);
|
||||||
|
|
||||||
|
@ -23,10 +22,4 @@ DECLARE_bool(validate_hir);
|
||||||
DECLARE_uint64(break_on_instruction);
|
DECLARE_uint64(break_on_instruction);
|
||||||
DECLARE_uint64(break_on_memory);
|
DECLARE_uint64(break_on_memory);
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
|
||||||
|
|
||||||
} // namespace alloy
|
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_ALLOY_PRIVATE_H_
|
#endif // ALLOY_ALLOY_PRIVATE_H_
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
using namespace alloy;
|
using namespace alloy;
|
||||||
|
|
||||||
|
|
||||||
#if 0 && DEBUG
|
#if 0 && DEBUG
|
||||||
#define DEFAULT_DEBUG_FLAG true
|
#define DEFAULT_DEBUG_FLAG true
|
||||||
#else
|
#else
|
||||||
|
@ -20,15 +19,16 @@ using namespace alloy;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEFINE_bool(debug, DEFAULT_DEBUG_FLAG,
|
DEFINE_bool(debug, DEFAULT_DEBUG_FLAG,
|
||||||
"Allow debugging and retain debug information.");
|
"Allow debugging and retain debug information.");
|
||||||
DEFINE_bool(always_disasm, false,
|
DEFINE_bool(
|
||||||
|
always_disasm, false,
|
||||||
"Always add debug info to functions, even when no debugger is attached.");
|
"Always add debug info to functions, even when no debugger is attached.");
|
||||||
|
|
||||||
DEFINE_bool(validate_hir, false,
|
DEFINE_bool(validate_hir, false,
|
||||||
"Perform validation checks on the HIR during compilation.");
|
"Perform validation checks on the HIR during compilation.");
|
||||||
|
|
||||||
// Breakpoints:
|
// Breakpoints:
|
||||||
DEFINE_uint64(break_on_instruction, 0,
|
DEFINE_uint64(break_on_instruction, 0,
|
||||||
"int3 before the given guest address is executed.");
|
"int3 before the given guest address is executed.");
|
||||||
DEFINE_uint64(break_on_memory, 0,
|
DEFINE_uint64(break_on_memory, 0,
|
||||||
"int3 on read/write to the given memory address.");
|
"int3 on read/write to the given memory address.");
|
||||||
|
|
|
@ -18,10 +18,4 @@
|
||||||
#include <alloy/runtime/thread_state.h>
|
#include <alloy/runtime/thread_state.h>
|
||||||
#include <alloy/tracing/tracing.h>
|
#include <alloy/tracing/tracing.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
|
||||||
|
|
||||||
} // namespace alloy
|
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_ALLOY_H_
|
#endif // ALLOY_ALLOY_H_
|
||||||
|
|
|
@ -9,13 +9,10 @@
|
||||||
|
|
||||||
#include <alloy/arena.h>
|
#include <alloy/arena.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
|
|
||||||
|
Arena::Arena(size_t chunk_size)
|
||||||
Arena::Arena(size_t chunk_size) :
|
: chunk_size_(chunk_size), head_chunk_(NULL), active_chunk_(NULL) {}
|
||||||
chunk_size_(chunk_size),
|
|
||||||
head_chunk_(NULL), active_chunk_(NULL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Arena::~Arena() {
|
Arena::~Arena() {
|
||||||
Reset();
|
Reset();
|
||||||
|
@ -48,7 +45,7 @@ void* Arena::Alloc(size_t size) {
|
||||||
if (active_chunk_->capacity - active_chunk_->offset < size + 4096) {
|
if (active_chunk_->capacity - active_chunk_->offset < size + 4096) {
|
||||||
Chunk* next = active_chunk_->next;
|
Chunk* next = active_chunk_->next;
|
||||||
if (!next) {
|
if (!next) {
|
||||||
XEASSERT(size < chunk_size_); // need to support larger chunks
|
XEASSERT(size < chunk_size_); // need to support larger chunks
|
||||||
next = new Chunk(chunk_size_);
|
next = new Chunk(chunk_size_);
|
||||||
active_chunk_->next = next;
|
active_chunk_->next = next;
|
||||||
}
|
}
|
||||||
|
@ -88,9 +85,8 @@ void* Arena::CloneContents() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arena::Chunk::Chunk(size_t chunk_size) :
|
Arena::Chunk::Chunk(size_t chunk_size)
|
||||||
next(NULL),
|
: next(NULL), capacity(chunk_size), buffer(0), offset(0) {
|
||||||
capacity(chunk_size), buffer(0), offset(0) {
|
|
||||||
buffer = (uint8_t*)xe_malloc(capacity);
|
buffer = (uint8_t*)xe_malloc(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,3 +95,5 @@ Arena::Chunk::~Chunk() {
|
||||||
xe_free(buffer);
|
xe_free(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -12,12 +12,10 @@
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
|
|
||||||
|
|
||||||
class Arena {
|
class Arena {
|
||||||
public:
|
public:
|
||||||
Arena(size_t chunk_size = 4 * 1024 * 1024);
|
Arena(size_t chunk_size = 4 * 1024 * 1024);
|
||||||
~Arena();
|
~Arena();
|
||||||
|
|
||||||
|
@ -25,33 +23,32 @@ public:
|
||||||
void DebugFill();
|
void DebugFill();
|
||||||
|
|
||||||
void* Alloc(size_t size);
|
void* Alloc(size_t size);
|
||||||
template<typename T> T* Alloc() {
|
template <typename T>
|
||||||
|
T* Alloc() {
|
||||||
return (T*)Alloc(sizeof(T));
|
return (T*)Alloc(sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* CloneContents();
|
void* CloneContents();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Chunk {
|
class Chunk {
|
||||||
public:
|
public:
|
||||||
Chunk(size_t chunk_size);
|
Chunk(size_t chunk_size);
|
||||||
~Chunk();
|
~Chunk();
|
||||||
|
|
||||||
Chunk* next;
|
Chunk* next;
|
||||||
|
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
uint8_t* buffer;
|
uint8_t* buffer;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t chunk_size_;
|
size_t chunk_size_;
|
||||||
Chunk* head_chunk_;
|
Chunk* head_chunk_;
|
||||||
Chunk* active_chunk_;
|
Chunk* active_chunk_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_ARENA_H_
|
#endif // ALLOY_ARENA_H_
|
||||||
|
|
|
@ -11,22 +11,16 @@
|
||||||
|
|
||||||
#include <alloy/backend/tracing.h>
|
#include <alloy/backend/tracing.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
Assembler::Assembler(Backend* backend) : backend_(backend) {}
|
||||||
|
|
||||||
Assembler::Assembler(Backend* backend) :
|
Assembler::~Assembler() { Reset(); }
|
||||||
backend_(backend) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Assembler::~Assembler() {
|
int Assembler::Initialize() { return 0; }
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
int Assembler::Initialize() {
|
void Assembler::Reset() {}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Assembler::Reset() {
|
} // namespace backend
|
||||||
}
|
} // namespace alloy
|
||||||
|
|
|
@ -12,27 +12,25 @@
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace hir {
|
namespace hir {
|
||||||
class HIRBuilder;
|
class HIRBuilder;
|
||||||
}
|
} // namespace hir
|
||||||
namespace runtime {
|
namespace runtime {
|
||||||
class DebugInfo;
|
class DebugInfo;
|
||||||
class Function;
|
class Function;
|
||||||
class FunctionInfo;
|
class FunctionInfo;
|
||||||
class Runtime;
|
class Runtime;
|
||||||
}
|
} // namespace runtime
|
||||||
}
|
} // namespace alloy
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
class Backend;
|
class Backend;
|
||||||
|
|
||||||
|
|
||||||
class Assembler {
|
class Assembler {
|
||||||
public:
|
public:
|
||||||
Assembler(Backend* backend);
|
Assembler(Backend* backend);
|
||||||
virtual ~Assembler();
|
virtual ~Assembler();
|
||||||
|
|
||||||
|
@ -40,18 +38,16 @@ public:
|
||||||
|
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
|
||||||
virtual int Assemble(
|
virtual int Assemble(runtime::FunctionInfo* symbol_info,
|
||||||
runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||||
uint32_t debug_info_flags, runtime::DebugInfo* debug_info,
|
runtime::DebugInfo* debug_info,
|
||||||
runtime::Function** out_function) = 0;
|
runtime::Function** out_function) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Backend* backend_;
|
Backend* backend_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_ASSEMBLER_H_
|
#endif // ALLOY_BACKEND_ASSEMBLER_H_
|
||||||
|
|
|
@ -11,26 +11,22 @@
|
||||||
|
|
||||||
#include <alloy/backend/tracing.h>
|
#include <alloy/backend/tracing.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::runtime::Runtime;
|
||||||
|
|
||||||
Backend::Backend(Runtime* runtime) :
|
Backend::Backend(Runtime* runtime) : runtime_(runtime) {
|
||||||
runtime_(runtime) {
|
|
||||||
xe_zero_struct(&machine_info_, sizeof(machine_info_));
|
xe_zero_struct(&machine_info_, sizeof(machine_info_));
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend::~Backend() {
|
Backend::~Backend() {}
|
||||||
}
|
|
||||||
|
|
||||||
int Backend::Initialize() {
|
int Backend::Initialize() { return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* Backend::AllocThreadData() {
|
void* Backend::AllocThreadData() { return NULL; }
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Backend::FreeThreadData(void* thread_data) {
|
void Backend::FreeThreadData(void* thread_data) {}
|
||||||
}
|
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -13,17 +13,19 @@
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
#include <alloy/backend/machine_info.h>
|
#include <alloy/backend/machine_info.h>
|
||||||
|
|
||||||
|
namespace alloy {
|
||||||
namespace alloy { namespace runtime { class Runtime; } }
|
namespace runtime {
|
||||||
|
class Runtime;
|
||||||
|
} // namespace runtime
|
||||||
|
} // namespace alloy
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
class Assembler;
|
class Assembler;
|
||||||
|
|
||||||
|
|
||||||
class Backend {
|
class Backend {
|
||||||
public:
|
public:
|
||||||
Backend(runtime::Runtime* runtime);
|
Backend(runtime::Runtime* runtime);
|
||||||
virtual ~Backend();
|
virtual ~Backend();
|
||||||
|
|
||||||
|
@ -37,14 +39,12 @@ public:
|
||||||
|
|
||||||
virtual Assembler* CreateAssembler() = 0;
|
virtual Assembler* CreateAssembler() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
runtime::Runtime* runtime_;
|
runtime::Runtime* runtime_;
|
||||||
MachineInfo machine_info_;
|
MachineInfo machine_info_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_BACKEND_H_
|
#endif // ALLOY_BACKEND_BACKEND_H_
|
||||||
|
|
|
@ -17,21 +17,19 @@
|
||||||
#include <alloy/hir/label.h>
|
#include <alloy/hir/label.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::backend::ivm;
|
namespace ivm {
|
||||||
using namespace alloy::hir;
|
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::runtime::Function;
|
||||||
|
using alloy::runtime::FunctionInfo;
|
||||||
|
|
||||||
IVMAssembler::IVMAssembler(Backend* backend) :
|
IVMAssembler::IVMAssembler(Backend* backend)
|
||||||
source_map_arena_(128 * 1024),
|
: source_map_arena_(128 * 1024), Assembler(backend) {}
|
||||||
Assembler(backend) {
|
|
||||||
}
|
|
||||||
|
|
||||||
IVMAssembler::~IVMAssembler() {
|
IVMAssembler::~IVMAssembler() {
|
||||||
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({
|
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({}));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int IVMAssembler::Initialize() {
|
int IVMAssembler::Initialize() {
|
||||||
|
@ -40,8 +38,7 @@ int IVMAssembler::Initialize() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::AssemblerInit({
|
alloy::tracing::WriteEvent(EventType::AssemblerInit({}));
|
||||||
}));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -53,10 +50,10 @@ void IVMAssembler::Reset() {
|
||||||
Assembler::Reset();
|
Assembler::Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
int IVMAssembler::Assemble(
|
int IVMAssembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||||
FunctionInfo* symbol_info, HIRBuilder* builder,
|
uint32_t debug_info_flags,
|
||||||
uint32_t debug_info_flags, runtime::DebugInfo* debug_info,
|
runtime::DebugInfo* debug_info,
|
||||||
Function** out_function) {
|
Function** out_function) {
|
||||||
IVMFunction* fn = new IVMFunction(symbol_info);
|
IVMFunction* fn = new IVMFunction(symbol_info);
|
||||||
fn->set_debug_info(debug_info);
|
fn->set_debug_info(debug_info);
|
||||||
|
|
||||||
|
@ -89,13 +86,13 @@ int IVMAssembler::Assemble(
|
||||||
|
|
||||||
auto block = builder->first_block();
|
auto block = builder->first_block();
|
||||||
while (block) {
|
while (block) {
|
||||||
Label* label = block->label_head;
|
auto label = block->label_head;
|
||||||
while (label) {
|
while (label) {
|
||||||
label->tag = (void*)(0x80000000 | ctx.intcode_count);
|
label->tag = (void*)(0x80000000 | ctx.intcode_count);
|
||||||
label = label->next;
|
label = label->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instr* i = block->instr_head;
|
auto i = block->instr_head;
|
||||||
while (i) {
|
while (i) {
|
||||||
int result = TranslateIntCodes(ctx, i);
|
int result = TranslateIntCodes(ctx, i);
|
||||||
i = i->next;
|
i = i->next;
|
||||||
|
@ -108,7 +105,8 @@ int IVMAssembler::Assemble(
|
||||||
// Fixup label references.
|
// Fixup label references.
|
||||||
LabelRef* label_ref = ctx.label_ref_head;
|
LabelRef* label_ref = ctx.label_ref_head;
|
||||||
while (label_ref) {
|
while (label_ref) {
|
||||||
label_ref->instr->src1_reg = (uint32_t)(intptr_t)label_ref->label->tag & ~0x80000000;
|
label_ref->instr->src1_reg =
|
||||||
|
(uint32_t)(intptr_t)label_ref->label->tag & ~0x80000000;
|
||||||
label_ref = label_ref->next;
|
label_ref = label_ref->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,3 +115,7 @@ int IVMAssembler::Assemble(
|
||||||
*out_function = fn;
|
*out_function = fn;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ivm
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,14 +14,12 @@
|
||||||
|
|
||||||
#include <alloy/backend/assembler.h>
|
#include <alloy/backend/assembler.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace ivm {
|
namespace ivm {
|
||||||
|
|
||||||
|
|
||||||
class IVMAssembler : public Assembler {
|
class IVMAssembler : public Assembler {
|
||||||
public:
|
public:
|
||||||
IVMAssembler(Backend* backend);
|
IVMAssembler(Backend* backend);
|
||||||
virtual ~IVMAssembler();
|
virtual ~IVMAssembler();
|
||||||
|
|
||||||
|
@ -29,21 +27,19 @@ public:
|
||||||
|
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
|
||||||
virtual int Assemble(
|
virtual int Assemble(runtime::FunctionInfo* symbol_info,
|
||||||
runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||||
uint32_t debug_info_flags, runtime::DebugInfo* debug_info,
|
runtime::DebugInfo* debug_info,
|
||||||
runtime::Function** out_function);
|
runtime::Function** out_function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Arena intcode_arena_;
|
Arena intcode_arena_;
|
||||||
Arena source_map_arena_;
|
Arena source_map_arena_;
|
||||||
Arena scratch_arena_;
|
Arena scratch_arena_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace ivm
|
} // namespace ivm
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_IVM_IVM_ASSEMBLER_H_
|
#endif // ALLOY_BACKEND_IVM_IVM_ASSEMBLER_H_
|
||||||
|
|
|
@ -13,20 +13,15 @@
|
||||||
#include <alloy/backend/ivm/ivm_stack.h>
|
#include <alloy/backend/ivm/ivm_stack.h>
|
||||||
#include <alloy/backend/ivm/tracing.h>
|
#include <alloy/backend/ivm/tracing.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::backend::ivm;
|
namespace ivm {
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::runtime::Runtime;
|
||||||
|
|
||||||
IVMBackend::IVMBackend(Runtime* runtime) :
|
IVMBackend::IVMBackend(Runtime* runtime) : Backend(runtime) {}
|
||||||
Backend(runtime) {
|
|
||||||
}
|
|
||||||
|
|
||||||
IVMBackend::~IVMBackend() {
|
IVMBackend::~IVMBackend() { alloy::tracing::WriteEvent(EventType::Deinit({})); }
|
||||||
alloy::tracing::WriteEvent(EventType::Deinit({
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
int IVMBackend::Initialize() {
|
int IVMBackend::Initialize() {
|
||||||
int result = Backend::Initialize();
|
int result = Backend::Initialize();
|
||||||
|
@ -35,34 +30,28 @@ int IVMBackend::Initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_info_.register_sets[0] = {
|
machine_info_.register_sets[0] = {
|
||||||
0,
|
0, "gpr", MachineInfo::RegisterSet::INT_TYPES, 16,
|
||||||
"gpr",
|
|
||||||
MachineInfo::RegisterSet::INT_TYPES,
|
|
||||||
16,
|
|
||||||
};
|
};
|
||||||
machine_info_.register_sets[1] = {
|
machine_info_.register_sets[1] = {
|
||||||
1,
|
1, "vec", MachineInfo::RegisterSet::FLOAT_TYPES |
|
||||||
"vec",
|
MachineInfo::RegisterSet::VEC_TYPES,
|
||||||
MachineInfo::RegisterSet::FLOAT_TYPES |
|
16,
|
||||||
MachineInfo::RegisterSet::VEC_TYPES,
|
|
||||||
16,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::Init({
|
alloy::tracing::WriteEvent(EventType::Init({}));
|
||||||
}));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* IVMBackend::AllocThreadData() {
|
void* IVMBackend::AllocThreadData() { return new IVMStack(); }
|
||||||
return new IVMStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVMBackend::FreeThreadData(void* thread_data) {
|
void IVMBackend::FreeThreadData(void* thread_data) {
|
||||||
auto stack = (IVMStack*)thread_data;
|
auto stack = (IVMStack*)thread_data;
|
||||||
delete stack;
|
delete stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assembler* IVMBackend::CreateAssembler() {
|
Assembler* IVMBackend::CreateAssembler() { return new IVMAssembler(this); }
|
||||||
return new IVMAssembler(this);
|
|
||||||
}
|
} // namespace ivm
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,17 +14,14 @@
|
||||||
|
|
||||||
#include <alloy/backend/backend.h>
|
#include <alloy/backend/backend.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace ivm {
|
namespace ivm {
|
||||||
|
|
||||||
|
|
||||||
#define ALLOY_HAS_IVM_BACKEND 1
|
#define ALLOY_HAS_IVM_BACKEND 1
|
||||||
|
|
||||||
|
|
||||||
class IVMBackend : public Backend {
|
class IVMBackend : public Backend {
|
||||||
public:
|
public:
|
||||||
IVMBackend(runtime::Runtime* runtime);
|
IVMBackend(runtime::Runtime* runtime);
|
||||||
virtual ~IVMBackend();
|
virtual ~IVMBackend();
|
||||||
|
|
||||||
|
@ -36,10 +33,8 @@ public:
|
||||||
virtual Assembler* CreateAssembler();
|
virtual Assembler* CreateAssembler();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace ivm
|
} // namespace ivm
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_IVM_IVM_BACKEND_H_
|
#endif // ALLOY_BACKEND_IVM_IVM_BACKEND_H_
|
||||||
|
|
|
@ -14,17 +14,21 @@
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
#include <alloy/runtime/thread_state.h>
|
#include <alloy/runtime/thread_state.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::backend::ivm;
|
namespace ivm {
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::runtime::Breakpoint;
|
||||||
|
using alloy::runtime::FunctionInfo;
|
||||||
|
using alloy::runtime::ThreadState;
|
||||||
|
|
||||||
IVMFunction::IVMFunction(FunctionInfo* symbol_info) :
|
IVMFunction::IVMFunction(FunctionInfo* symbol_info)
|
||||||
register_count_(0), intcode_count_(0), intcodes_(0),
|
: register_count_(0),
|
||||||
source_map_count_(0), source_map_(0),
|
intcode_count_(0),
|
||||||
Function(symbol_info) {
|
intcodes_(0),
|
||||||
}
|
source_map_count_(0),
|
||||||
|
source_map_(0),
|
||||||
|
Function(symbol_info) {}
|
||||||
|
|
||||||
IVMFunction::~IVMFunction() {
|
IVMFunction::~IVMFunction() {
|
||||||
xe_free(intcodes_);
|
xe_free(intcodes_);
|
||||||
|
@ -57,8 +61,7 @@ int IVMFunction::AddBreakpointImpl(Breakpoint* breakpoint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEMP breakpoints always overwrite normal ones.
|
// TEMP breakpoints always overwrite normal ones.
|
||||||
if (!i->debug_flags ||
|
if (!i->debug_flags || breakpoint->type() == Breakpoint::TEMP_TYPE) {
|
||||||
breakpoint->type() == Breakpoint::TEMP_TYPE) {
|
|
||||||
uint64_t breakpoint_ptr = (uint64_t)breakpoint;
|
uint64_t breakpoint_ptr = (uint64_t)breakpoint;
|
||||||
i->src2_reg = (uint32_t)breakpoint_ptr;
|
i->src2_reg = (uint32_t)breakpoint_ptr;
|
||||||
i->src3_reg = (uint32_t)(breakpoint_ptr >> 32);
|
i->src3_reg = (uint32_t)(breakpoint_ptr >> 32);
|
||||||
|
@ -127,8 +130,8 @@ int IVMFunction::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
||||||
|
|
||||||
volatile int* suspend_flag_address = thread_state->suspend_flag_address();
|
volatile int* suspend_flag_address = thread_state->suspend_flag_address();
|
||||||
|
|
||||||
// TODO(benvanik): DID_CARRY -- need HIR to set a OPCODE_FLAG_SET_CARRY
|
// TODO(benvanik): DID_CARRY -- need HIR to set a OPCODE_FLAG_SET_CARRY
|
||||||
// or something so the fns can set an ics flag.
|
// or something so the fns can set an ics flag.
|
||||||
|
|
||||||
#ifdef TRACE_SOURCE_OFFSET
|
#ifdef TRACE_SOURCE_OFFSET
|
||||||
size_t source_index = 0;
|
size_t source_index = 0;
|
||||||
|
@ -177,3 +180,7 @@ int IVMFunction::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ivm
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,104 +15,96 @@
|
||||||
#include <alloy/hir/instr.h>
|
#include <alloy/hir/instr.h>
|
||||||
#include <alloy/hir/opcodes.h>
|
#include <alloy/hir/opcodes.h>
|
||||||
|
|
||||||
namespace alloy { namespace runtime { class ThreadState; } }
|
namespace alloy {
|
||||||
|
namespace runtime {
|
||||||
|
class ThreadState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace ivm {
|
namespace ivm {
|
||||||
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
int8_t i8;
|
int8_t i8;
|
||||||
uint8_t u8;
|
uint8_t u8;
|
||||||
int16_t i16;
|
int16_t i16;
|
||||||
uint16_t u16;
|
uint16_t u16;
|
||||||
int32_t i32;
|
int32_t i32;
|
||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
int64_t i64;
|
int64_t i64;
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
float f32;
|
float f32;
|
||||||
double f64;
|
double f64;
|
||||||
vec128_t v128;
|
vec128_t v128;
|
||||||
} Register;
|
} Register;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Register* rf;
|
Register* rf;
|
||||||
uint8_t* locals;
|
uint8_t* locals;
|
||||||
uint8_t* context;
|
uint8_t* context;
|
||||||
uint8_t* membase;
|
uint8_t* membase;
|
||||||
uint8_t* page_table;
|
uint8_t* page_table;
|
||||||
int8_t did_carry;
|
int8_t did_carry;
|
||||||
int8_t did_saturate;
|
int8_t did_saturate;
|
||||||
runtime::ThreadState* thread_state;
|
runtime::ThreadState* thread_state;
|
||||||
uint64_t return_address;
|
uint64_t return_address;
|
||||||
uint64_t call_return_address;
|
uint64_t call_return_address;
|
||||||
} IntCodeState;
|
} IntCodeState;
|
||||||
|
|
||||||
|
|
||||||
struct IntCode_s;
|
struct IntCode_s;
|
||||||
typedef uint32_t (*IntCodeFn)(
|
typedef uint32_t (*IntCodeFn)(IntCodeState& ics, const struct IntCode_s* i);
|
||||||
IntCodeState& ics, const struct IntCode_s* i);
|
|
||||||
|
|
||||||
#define IA_RETURN 0xA0000000
|
#define IA_RETURN 0xA0000000
|
||||||
#define IA_NEXT 0xB0000000
|
#define IA_NEXT 0xB0000000
|
||||||
|
|
||||||
|
|
||||||
typedef struct IntCode_s {
|
typedef struct IntCode_s {
|
||||||
IntCodeFn intcode_fn;
|
IntCodeFn intcode_fn;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
uint16_t debug_flags;
|
uint16_t debug_flags;
|
||||||
|
|
||||||
uint32_t dest_reg;
|
uint32_t dest_reg;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t src1_reg;
|
uint32_t src1_reg;
|
||||||
uint32_t src2_reg;
|
uint32_t src2_reg;
|
||||||
uint32_t src3_reg;
|
uint32_t src3_reg;
|
||||||
// <4 bytes available>
|
// <4 bytes available>
|
||||||
};
|
};
|
||||||
struct {
|
struct {
|
||||||
Register constant;
|
Register constant;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// debugging info/etc
|
// debugging info/etc
|
||||||
} IntCode;
|
} IntCode;
|
||||||
|
|
||||||
|
|
||||||
typedef struct LabelRef_s {
|
typedef struct LabelRef_s {
|
||||||
hir::Label* label;
|
hir::Label* label;
|
||||||
IntCode* instr;
|
IntCode* instr;
|
||||||
LabelRef_s* next;
|
LabelRef_s* next;
|
||||||
} LabelRef;
|
} LabelRef;
|
||||||
|
|
||||||
|
|
||||||
typedef struct SourceMapEntry_s {
|
typedef struct SourceMapEntry_s {
|
||||||
uint64_t source_offset;
|
uint64_t source_offset;
|
||||||
uint64_t intcode_index;
|
uint64_t intcode_index;
|
||||||
} SourceMapEntry;
|
} SourceMapEntry;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t register_count;
|
uint32_t register_count;
|
||||||
size_t intcode_count;
|
size_t intcode_count;
|
||||||
Arena* intcode_arena;
|
Arena* intcode_arena;
|
||||||
size_t source_map_count;
|
size_t source_map_count;
|
||||||
Arena* source_map_arena;
|
Arena* source_map_arena;
|
||||||
Arena* scratch_arena;
|
Arena* scratch_arena;
|
||||||
LabelRef* label_ref_head;
|
LabelRef* label_ref_head;
|
||||||
size_t stack_size;
|
size_t stack_size;
|
||||||
} TranslationContext;
|
} TranslationContext;
|
||||||
|
|
||||||
|
|
||||||
int TranslateIntCodes(TranslationContext& ctx, hir::Instr* i);
|
int TranslateIntCodes(TranslationContext& ctx, hir::Instr* i);
|
||||||
|
|
||||||
|
|
||||||
} // namespace ivm
|
} // namespace ivm
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_IVM_INTCODE_H_
|
#endif // ALLOY_BACKEND_IVM_INTCODE_H_
|
||||||
|
|
|
@ -9,15 +9,12 @@
|
||||||
|
|
||||||
#include <alloy/backend/ivm/ivm_stack.h>
|
#include <alloy/backend/ivm/ivm_stack.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::backend::ivm;
|
namespace ivm {
|
||||||
|
|
||||||
|
IVMStack::IVMStack()
|
||||||
IVMStack::IVMStack() :
|
: chunk_size_(2 * 1024 * 1024), head_chunk_(NULL), active_chunk_(NULL) {}
|
||||||
chunk_size_(2 * 1024 * 1024),
|
|
||||||
head_chunk_(NULL), active_chunk_(NULL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
IVMStack::~IVMStack() {
|
IVMStack::~IVMStack() {
|
||||||
Chunk* chunk = head_chunk_;
|
Chunk* chunk = head_chunk_;
|
||||||
|
@ -35,7 +32,7 @@ Register* IVMStack::Alloc(size_t register_count) {
|
||||||
if (active_chunk_->capacity - active_chunk_->offset < size) {
|
if (active_chunk_->capacity - active_chunk_->offset < size) {
|
||||||
Chunk* next = active_chunk_->next;
|
Chunk* next = active_chunk_->next;
|
||||||
if (!next) {
|
if (!next) {
|
||||||
XEASSERT(size < chunk_size_); // need to support larger chunks
|
XEASSERT(size < chunk_size_); // need to support larger chunks
|
||||||
next = new Chunk(chunk_size_);
|
next = new Chunk(chunk_size_);
|
||||||
next->prev = active_chunk_;
|
next->prev = active_chunk_;
|
||||||
active_chunk_->next = next;
|
active_chunk_->next = next;
|
||||||
|
@ -66,9 +63,8 @@ void IVMStack::Free(size_t register_count) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IVMStack::Chunk::Chunk(size_t chunk_size) :
|
IVMStack::Chunk::Chunk(size_t chunk_size)
|
||||||
prev(NULL), next(NULL),
|
: prev(NULL), next(NULL), capacity(chunk_size), buffer(0), offset(0) {
|
||||||
capacity(chunk_size), buffer(0), offset(0) {
|
|
||||||
buffer = (uint8_t*)xe_malloc(capacity);
|
buffer = (uint8_t*)xe_malloc(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,3 +73,7 @@ IVMStack::Chunk::~Chunk() {
|
||||||
xe_free(buffer);
|
xe_free(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ivm
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,44 +14,40 @@
|
||||||
|
|
||||||
#include <alloy/backend/ivm/ivm_intcode.h>
|
#include <alloy/backend/ivm/ivm_intcode.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace ivm {
|
namespace ivm {
|
||||||
|
|
||||||
|
|
||||||
class IVMStack {
|
class IVMStack {
|
||||||
public:
|
public:
|
||||||
IVMStack();
|
IVMStack();
|
||||||
~IVMStack();
|
~IVMStack();
|
||||||
|
|
||||||
Register* Alloc(size_t register_count);
|
Register* Alloc(size_t register_count);
|
||||||
void Free(size_t register_count);
|
void Free(size_t register_count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Chunk {
|
class Chunk {
|
||||||
public:
|
public:
|
||||||
Chunk(size_t chunk_size);
|
Chunk(size_t chunk_size);
|
||||||
~Chunk();
|
~Chunk();
|
||||||
|
|
||||||
Chunk* prev;
|
Chunk* prev;
|
||||||
Chunk* next;
|
Chunk* next;
|
||||||
|
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
uint8_t* buffer;
|
uint8_t* buffer;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t chunk_size_;
|
size_t chunk_size_;
|
||||||
Chunk* head_chunk_;
|
Chunk* head_chunk_;
|
||||||
Chunk* active_chunk_;
|
Chunk* active_chunk_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace ivm
|
} // namespace ivm
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_IVM_IVM_STACK_H_
|
#endif // ALLOY_BACKEND_IVM_IVM_STACK_H_
|
||||||
|
|
|
@ -12,24 +12,20 @@
|
||||||
|
|
||||||
#include <alloy/backend/tracing.h>
|
#include <alloy/backend/tracing.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace ivm {
|
namespace ivm {
|
||||||
|
|
||||||
const uint32_t ALLOY_BACKEND_IVM =
|
const uint32_t ALLOY_BACKEND_IVM = alloy::backend::EventType::ALLOY_BACKEND_IVM;
|
||||||
alloy::backend::EventType::ALLOY_BACKEND_IVM;
|
|
||||||
|
|
||||||
|
|
||||||
class EventType {
|
class EventType {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
ALLOY_BACKEND_IVM_INIT = ALLOY_BACKEND_IVM | (1),
|
ALLOY_BACKEND_IVM_INIT = ALLOY_BACKEND_IVM | (1),
|
||||||
ALLOY_BACKEND_IVM_DEINIT = ALLOY_BACKEND_IVM | (2),
|
ALLOY_BACKEND_IVM_DEINIT = ALLOY_BACKEND_IVM | (2),
|
||||||
|
ALLOY_BACKEND_IVM_ASSEMBLER = ALLOY_BACKEND_IVM | (1 << 20),
|
||||||
ALLOY_BACKEND_IVM_ASSEMBLER = ALLOY_BACKEND_IVM | (1 << 20),
|
ALLOY_BACKEND_IVM_ASSEMBLER_INIT = ALLOY_BACKEND_IVM_ASSEMBLER | (1),
|
||||||
ALLOY_BACKEND_IVM_ASSEMBLER_INIT = ALLOY_BACKEND_IVM_ASSEMBLER | (1),
|
ALLOY_BACKEND_IVM_ASSEMBLER_DEINIT = ALLOY_BACKEND_IVM_ASSEMBLER | (2),
|
||||||
ALLOY_BACKEND_IVM_ASSEMBLER_DEINIT = ALLOY_BACKEND_IVM_ASSEMBLER | (2),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Init_s {
|
typedef struct Init_s {
|
||||||
|
@ -47,10 +43,8 @@ public:
|
||||||
} AssemblerDeinit;
|
} AssemblerDeinit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace ivm
|
} // namespace ivm
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_IVM_TRACING_H_
|
#endif // ALLOY_BACKEND_IVM_TRACING_H_
|
||||||
|
|
|
@ -12,11 +12,9 @@
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
|
|
||||||
struct MachineInfo {
|
struct MachineInfo {
|
||||||
struct RegisterSet {
|
struct RegisterSet {
|
||||||
enum Types {
|
enum Types {
|
||||||
|
@ -31,9 +29,7 @@ struct MachineInfo {
|
||||||
} register_sets[8];
|
} register_sets[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_MACHINE_INFO_H_
|
#endif // ALLOY_BACKEND_MACHINE_INFO_H_
|
||||||
|
|
|
@ -13,24 +13,20 @@
|
||||||
#include <alloy/tracing/tracing.h>
|
#include <alloy/tracing/tracing.h>
|
||||||
#include <alloy/tracing/event_type.h>
|
#include <alloy/tracing/event_type.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
const uint32_t ALLOY_BACKEND = alloy::tracing::EventType::ALLOY_BACKEND;
|
const uint32_t ALLOY_BACKEND = alloy::tracing::EventType::ALLOY_BACKEND;
|
||||||
|
|
||||||
|
|
||||||
class EventType {
|
class EventType {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
ALLOY_BACKEND_IVM = ALLOY_BACKEND | (1 << 24),
|
ALLOY_BACKEND_IVM = ALLOY_BACKEND | (1 << 24),
|
||||||
ALLOY_BACKEND_X64 = ALLOY_BACKEND | (2 << 24),
|
ALLOY_BACKEND_X64 = ALLOY_BACKEND | (2 << 24),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_TRACING_H_
|
#endif // ALLOY_BACKEND_TRACING_H_
|
||||||
|
|
|
@ -12,24 +12,20 @@
|
||||||
|
|
||||||
#include <alloy/backend/tracing.h>
|
#include <alloy/backend/tracing.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
const uint32_t ALLOY_BACKEND_X64 =
|
const uint32_t ALLOY_BACKEND_X64 = alloy::backend::EventType::ALLOY_BACKEND_X64;
|
||||||
alloy::backend::EventType::ALLOY_BACKEND_X64;
|
|
||||||
|
|
||||||
|
|
||||||
class EventType {
|
class EventType {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
ALLOY_BACKEND_X64_INIT = ALLOY_BACKEND_X64 | (1),
|
ALLOY_BACKEND_X64_INIT = ALLOY_BACKEND_X64 | (1),
|
||||||
ALLOY_BACKEND_X64_DEINIT = ALLOY_BACKEND_X64 | (2),
|
ALLOY_BACKEND_X64_DEINIT = ALLOY_BACKEND_X64 | (2),
|
||||||
|
ALLOY_BACKEND_X64_ASSEMBLER = ALLOY_BACKEND_X64 | (1 << 20),
|
||||||
ALLOY_BACKEND_X64_ASSEMBLER = ALLOY_BACKEND_X64 | (1 << 20),
|
ALLOY_BACKEND_X64_ASSEMBLER_INIT = ALLOY_BACKEND_X64_ASSEMBLER | (1),
|
||||||
ALLOY_BACKEND_X64_ASSEMBLER_INIT = ALLOY_BACKEND_X64_ASSEMBLER | (1),
|
ALLOY_BACKEND_X64_ASSEMBLER_DEINIT = ALLOY_BACKEND_X64_ASSEMBLER | (2),
|
||||||
ALLOY_BACKEND_X64_ASSEMBLER_DEINIT = ALLOY_BACKEND_X64_ASSEMBLER | (2),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Init_s {
|
typedef struct Init_s {
|
||||||
|
@ -47,10 +43,8 @@ public:
|
||||||
} AssemblerDeinit;
|
} AssemblerDeinit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_TRACING_H_
|
#endif // ALLOY_BACKEND_X64_TRACING_H_
|
||||||
|
|
|
@ -21,22 +21,23 @@ namespace BE {
|
||||||
#include <beaengine/BeaEngine.h>
|
#include <beaengine/BeaEngine.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::backend::x64;
|
namespace x64 {
|
||||||
using namespace alloy::hir;
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::runtime;
|
using namespace alloy::runtime;
|
||||||
|
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::runtime::DebugInfo;
|
||||||
|
using alloy::runtime::Function;
|
||||||
|
using alloy::runtime::FunctionInfo;
|
||||||
|
|
||||||
X64Assembler::X64Assembler(X64Backend* backend) :
|
X64Assembler::X64Assembler(X64Backend* backend)
|
||||||
x64_backend_(backend),
|
: x64_backend_(backend), emitter_(0), allocator_(0), Assembler(backend) {}
|
||||||
emitter_(0), allocator_(0),
|
|
||||||
Assembler(backend) {
|
|
||||||
}
|
|
||||||
|
|
||||||
X64Assembler::~X64Assembler() {
|
X64Assembler::~X64Assembler() {
|
||||||
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({
|
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({}));
|
||||||
}));
|
|
||||||
|
|
||||||
delete emitter_;
|
delete emitter_;
|
||||||
delete allocator_;
|
delete allocator_;
|
||||||
|
@ -51,8 +52,7 @@ int X64Assembler::Initialize() {
|
||||||
allocator_ = new XbyakAllocator();
|
allocator_ = new XbyakAllocator();
|
||||||
emitter_ = new X64Emitter(x64_backend_, allocator_);
|
emitter_ = new X64Emitter(x64_backend_, allocator_);
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::AssemblerInit({
|
alloy::tracing::WriteEvent(EventType::AssemblerInit({}));
|
||||||
}));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -62,10 +62,9 @@ void X64Assembler::Reset() {
|
||||||
Assembler::Reset();
|
Assembler::Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Assembler::Assemble(
|
int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||||
FunctionInfo* symbol_info, HIRBuilder* builder,
|
uint32_t debug_info_flags, DebugInfo* debug_info,
|
||||||
uint32_t debug_info_flags, DebugInfo* debug_info,
|
Function** out_function) {
|
||||||
Function** out_function) {
|
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
@ -73,13 +72,12 @@ int X64Assembler::Assemble(
|
||||||
// Lower HIR -> x64.
|
// Lower HIR -> x64.
|
||||||
void* machine_code = 0;
|
void* machine_code = 0;
|
||||||
size_t code_size = 0;
|
size_t code_size = 0;
|
||||||
result = emitter_->Emit(builder,
|
result = emitter_->Emit(builder, debug_info_flags, debug_info, machine_code,
|
||||||
debug_info_flags, debug_info,
|
code_size);
|
||||||
machine_code, code_size);
|
|
||||||
XEEXPECTZERO(result);
|
XEEXPECTZERO(result);
|
||||||
|
|
||||||
// Stash generated machine code.
|
// Stash generated machine code.
|
||||||
if (debug_info_flags & DEBUG_INFO_MACHINE_CODE_DISASM) {
|
if (debug_info_flags & DebugInfoFlags::DEBUG_INFO_MACHINE_CODE_DISASM) {
|
||||||
DumpMachineCode(debug_info, machine_code, code_size, &string_buffer_);
|
DumpMachineCode(debug_info, machine_code, code_size, &string_buffer_);
|
||||||
debug_info->set_machine_code_disasm(string_buffer_.ToString());
|
debug_info->set_machine_code_disasm(string_buffer_.ToString());
|
||||||
string_buffer_.Reset();
|
string_buffer_.Reset();
|
||||||
|
@ -100,10 +98,8 @@ XECLEANUP:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Assembler::DumpMachineCode(
|
void X64Assembler::DumpMachineCode(DebugInfo* debug_info, void* machine_code,
|
||||||
DebugInfo* debug_info,
|
size_t code_size, StringBuffer* str) {
|
||||||
void* machine_code, size_t code_size,
|
|
||||||
StringBuffer* str) {
|
|
||||||
BE::DISASM disasm;
|
BE::DISASM disasm;
|
||||||
xe_zero_struct(&disasm, sizeof(disasm));
|
xe_zero_struct(&disasm, sizeof(disasm));
|
||||||
disasm.Archi = 64;
|
disasm.Archi = 64;
|
||||||
|
@ -113,8 +109,8 @@ void X64Assembler::DumpMachineCode(
|
||||||
uint64_t prev_source_offset = 0;
|
uint64_t prev_source_offset = 0;
|
||||||
while (disasm.EIP < eip_end) {
|
while (disasm.EIP < eip_end) {
|
||||||
// Look up source offset.
|
// Look up source offset.
|
||||||
auto map_entry = debug_info->LookupCodeOffset(
|
auto map_entry =
|
||||||
disasm.EIP - (BE::UIntPtr)machine_code);
|
debug_info->LookupCodeOffset(disasm.EIP - (BE::UIntPtr)machine_code);
|
||||||
if (map_entry) {
|
if (map_entry) {
|
||||||
if (map_entry->source_offset == prev_source_offset) {
|
if (map_entry->source_offset == prev_source_offset) {
|
||||||
str->Append(" ");
|
str->Append(" ");
|
||||||
|
@ -134,3 +130,7 @@ void X64Assembler::DumpMachineCode(
|
||||||
disasm.EIP += len;
|
disasm.EIP += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace x64
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include <alloy/backend/assembler.h>
|
#include <alloy/backend/assembler.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
@ -23,9 +22,8 @@ class X64Backend;
|
||||||
class X64Emitter;
|
class X64Emitter;
|
||||||
class XbyakAllocator;
|
class XbyakAllocator;
|
||||||
|
|
||||||
|
|
||||||
class X64Assembler : public Assembler {
|
class X64Assembler : public Assembler {
|
||||||
public:
|
public:
|
||||||
X64Assembler(X64Backend* backend);
|
X64Assembler(X64Backend* backend);
|
||||||
virtual ~X64Assembler();
|
virtual ~X64Assembler();
|
||||||
|
|
||||||
|
@ -33,28 +31,25 @@ public:
|
||||||
|
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
|
||||||
virtual int Assemble(
|
virtual int Assemble(runtime::FunctionInfo* symbol_info,
|
||||||
runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||||
uint32_t debug_info_flags, runtime::DebugInfo* debug_info,
|
runtime::DebugInfo* debug_info,
|
||||||
runtime::Function** out_function);
|
runtime::Function** out_function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DumpMachineCode(runtime::DebugInfo* debug_info,
|
void DumpMachineCode(runtime::DebugInfo* debug_info, void* machine_code,
|
||||||
void* machine_code, size_t code_size,
|
size_t code_size, StringBuffer* str);
|
||||||
StringBuffer* str);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
X64Backend* x64_backend_;
|
X64Backend* x64_backend_;
|
||||||
X64Emitter* emitter_;
|
X64Emitter* emitter_;
|
||||||
XbyakAllocator* allocator_;
|
XbyakAllocator* allocator_;
|
||||||
|
|
||||||
StringBuffer string_buffer_;
|
StringBuffer string_buffer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_X64_ASSEMBLER_H_
|
#endif // ALLOY_BACKEND_X64_X64_ASSEMBLER_H_
|
||||||
|
|
|
@ -15,20 +15,16 @@
|
||||||
#include <alloy/backend/x64/x64_sequences.h>
|
#include <alloy/backend/x64/x64_sequences.h>
|
||||||
#include <alloy/backend/x64/x64_thunk_emitter.h>
|
#include <alloy/backend/x64/x64_thunk_emitter.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::backend::x64;
|
namespace x64 {
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::runtime::Runtime;
|
||||||
|
|
||||||
X64Backend::X64Backend(Runtime* runtime) :
|
X64Backend::X64Backend(Runtime* runtime) : code_cache_(0), Backend(runtime) {}
|
||||||
code_cache_(0),
|
|
||||||
Backend(runtime) {
|
|
||||||
}
|
|
||||||
|
|
||||||
X64Backend::~X64Backend() {
|
X64Backend::~X64Backend() {
|
||||||
alloy::tracing::WriteEvent(EventType::Deinit({
|
alloy::tracing::WriteEvent(EventType::Deinit({}));
|
||||||
}));
|
|
||||||
delete code_cache_;
|
delete code_cache_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,17 +37,12 @@ int X64Backend::Initialize() {
|
||||||
RegisterSequences();
|
RegisterSequences();
|
||||||
|
|
||||||
machine_info_.register_sets[0] = {
|
machine_info_.register_sets[0] = {
|
||||||
0,
|
0, "gpr", MachineInfo::RegisterSet::INT_TYPES, X64Emitter::GPR_COUNT,
|
||||||
"gpr",
|
|
||||||
MachineInfo::RegisterSet::INT_TYPES,
|
|
||||||
X64Emitter::GPR_COUNT,
|
|
||||||
};
|
};
|
||||||
machine_info_.register_sets[1] = {
|
machine_info_.register_sets[1] = {
|
||||||
1,
|
1, "xmm", MachineInfo::RegisterSet::FLOAT_TYPES |
|
||||||
"xmm",
|
MachineInfo::RegisterSet::VEC_TYPES,
|
||||||
MachineInfo::RegisterSet::FLOAT_TYPES |
|
X64Emitter::XMM_COUNT,
|
||||||
MachineInfo::RegisterSet::VEC_TYPES,
|
|
||||||
X64Emitter::XMM_COUNT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
code_cache_ = new X64CodeCache();
|
code_cache_ = new X64CodeCache();
|
||||||
|
@ -67,12 +58,13 @@ int X64Backend::Initialize() {
|
||||||
delete thunk_emitter;
|
delete thunk_emitter;
|
||||||
delete allocator;
|
delete allocator;
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::Init({
|
alloy::tracing::WriteEvent(EventType::Init({}));
|
||||||
}));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assembler* X64Backend::CreateAssembler() {
|
Assembler* X64Backend::CreateAssembler() { return new X64Assembler(this); }
|
||||||
return new X64Assembler(this);
|
|
||||||
}
|
} // namespace x64
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,22 +14,19 @@
|
||||||
|
|
||||||
#include <alloy/backend/backend.h>
|
#include <alloy/backend/backend.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
class X64CodeCache;
|
class X64CodeCache;
|
||||||
|
|
||||||
|
|
||||||
#define ALLOY_HAS_X64_BACKEND 1
|
#define ALLOY_HAS_X64_BACKEND 1
|
||||||
|
|
||||||
|
|
||||||
typedef void* (*HostToGuestThunk)(void* target, void* arg0, void* arg1);
|
typedef void* (*HostToGuestThunk)(void* target, void* arg0, void* arg1);
|
||||||
typedef void* (*GuestToHostThunk)(void* target, void* arg0, void* arg1);
|
typedef void* (*GuestToHostThunk)(void* target, void* arg0, void* arg1);
|
||||||
|
|
||||||
class X64Backend : public Backend {
|
class X64Backend : public Backend {
|
||||||
public:
|
public:
|
||||||
X64Backend(runtime::Runtime* runtime);
|
X64Backend(runtime::Runtime* runtime);
|
||||||
virtual ~X64Backend();
|
virtual ~X64Backend();
|
||||||
|
|
||||||
|
@ -41,16 +38,14 @@ public:
|
||||||
|
|
||||||
virtual Assembler* CreateAssembler();
|
virtual Assembler* CreateAssembler();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
X64CodeCache* code_cache_;
|
X64CodeCache* code_cache_;
|
||||||
HostToGuestThunk host_to_guest_thunk_;
|
HostToGuestThunk host_to_guest_thunk_;
|
||||||
GuestToHostThunk guest_to_host_thunk_;
|
GuestToHostThunk guest_to_host_thunk_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_X64_BACKEND_H_
|
#endif // ALLOY_BACKEND_X64_X64_BACKEND_H_
|
||||||
|
|
|
@ -11,24 +11,20 @@
|
||||||
|
|
||||||
#include <alloy/backend/x64/tracing.h>
|
#include <alloy/backend/x64/tracing.h>
|
||||||
|
|
||||||
using namespace alloy;
|
|
||||||
using namespace alloy::backend;
|
|
||||||
using namespace alloy::backend::x64;
|
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
class X64CodeChunk {
|
class X64CodeChunk {
|
||||||
public:
|
public:
|
||||||
X64CodeChunk(size_t chunk_size);
|
X64CodeChunk(size_t chunk_size);
|
||||||
~X64CodeChunk();
|
~X64CodeChunk();
|
||||||
public:
|
|
||||||
|
public:
|
||||||
X64CodeChunk* next;
|
X64CodeChunk* next;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
uint8_t* buffer;
|
uint8_t* buffer;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
|
|
||||||
// Estimate of function sized use to determine initial table capacity.
|
// Estimate of function sized use to determine initial table capacity.
|
||||||
const static uint32_t ESTIMATED_FN_SIZE = 512;
|
const static uint32_t ESTIMATED_FN_SIZE = 512;
|
||||||
|
@ -36,24 +32,16 @@ public:
|
||||||
// TODO(benvanik): move this to emitter.
|
// TODO(benvanik): move this to emitter.
|
||||||
const static uint32_t UNWIND_INFO_SIZE = 4 + (2 * 1 + 2 + 2);
|
const static uint32_t UNWIND_INFO_SIZE = 4 + (2 * 1 + 2 + 2);
|
||||||
|
|
||||||
void* fn_table_handle;
|
void* fn_table_handle;
|
||||||
RUNTIME_FUNCTION* fn_table;
|
RUNTIME_FUNCTION* fn_table;
|
||||||
uint32_t fn_table_count;
|
uint32_t fn_table_count;
|
||||||
uint32_t fn_table_capacity;
|
uint32_t fn_table_capacity;
|
||||||
|
|
||||||
void AddTableEntry(uint8_t* code, size_t code_size, size_t stack_size);
|
void AddTableEntry(uint8_t* code, size_t code_size, size_t stack_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
X64CodeCache::X64CodeCache(size_t chunk_size)
|
||||||
} // namespace x64
|
: chunk_size_(chunk_size), head_chunk_(NULL), active_chunk_(NULL) {}
|
||||||
} // namespace backend
|
|
||||||
} // namespace alloy
|
|
||||||
|
|
||||||
|
|
||||||
X64CodeCache::X64CodeCache(size_t chunk_size) :
|
|
||||||
chunk_size_(chunk_size),
|
|
||||||
head_chunk_(NULL), active_chunk_(NULL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
X64CodeCache::~X64CodeCache() {
|
X64CodeCache::~X64CodeCache() {
|
||||||
std::lock_guard<std::mutex> guard(lock_);
|
std::lock_guard<std::mutex> guard(lock_);
|
||||||
|
@ -66,9 +54,7 @@ X64CodeCache::~X64CodeCache() {
|
||||||
head_chunk_ = NULL;
|
head_chunk_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64CodeCache::Initialize() {
|
int X64CodeCache::Initialize() { return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||||
size_t stack_size) {
|
size_t stack_size) {
|
||||||
|
@ -87,7 +73,7 @@ void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||||
if (active_chunk_->capacity - active_chunk_->offset < code_size) {
|
if (active_chunk_->capacity - active_chunk_->offset < code_size) {
|
||||||
auto next = active_chunk_->next;
|
auto next = active_chunk_->next;
|
||||||
if (!next) {
|
if (!next) {
|
||||||
XEASSERT(code_size < chunk_size_); // need to support larger chunks
|
XEASSERT(code_size < chunk_size_); // need to support larger chunks
|
||||||
next = new X64CodeChunk(chunk_size_);
|
next = new X64CodeChunk(chunk_size_);
|
||||||
active_chunk_->next = next;
|
active_chunk_->next = next;
|
||||||
}
|
}
|
||||||
|
@ -113,25 +99,19 @@ void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||||
return final_address;
|
return final_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
X64CodeChunk::X64CodeChunk(size_t chunk_size) :
|
X64CodeChunk::X64CodeChunk(size_t chunk_size)
|
||||||
next(NULL),
|
: next(NULL), capacity(chunk_size), buffer(0), offset(0) {
|
||||||
capacity(chunk_size), buffer(0), offset(0) {
|
buffer = (uint8_t*)VirtualAlloc(NULL, capacity, MEM_RESERVE | MEM_COMMIT,
|
||||||
buffer = (uint8_t*)VirtualAlloc(
|
PAGE_EXECUTE_READWRITE);
|
||||||
NULL, capacity,
|
|
||||||
MEM_RESERVE | MEM_COMMIT,
|
|
||||||
PAGE_EXECUTE_READWRITE);
|
|
||||||
|
|
||||||
fn_table_capacity = (uint32_t)XEROUNDUP(capacity / ESTIMATED_FN_SIZE, 16);
|
fn_table_capacity = (uint32_t)XEROUNDUP(capacity / ESTIMATED_FN_SIZE, 16);
|
||||||
size_t table_size = fn_table_capacity * sizeof(RUNTIME_FUNCTION);
|
size_t table_size = fn_table_capacity * sizeof(RUNTIME_FUNCTION);
|
||||||
fn_table = (RUNTIME_FUNCTION*)xe_malloc(table_size);
|
fn_table = (RUNTIME_FUNCTION*)xe_malloc(table_size);
|
||||||
fn_table_count = 0;
|
fn_table_count = 0;
|
||||||
fn_table_handle = 0;
|
fn_table_handle = 0;
|
||||||
RtlAddGrowableFunctionTable(
|
RtlAddGrowableFunctionTable(&fn_table_handle, fn_table, fn_table_count,
|
||||||
&fn_table_handle,
|
fn_table_capacity, (ULONG_PTR)buffer,
|
||||||
fn_table,
|
(ULONG_PTR)buffer + capacity);
|
||||||
fn_table_count,
|
|
||||||
fn_table_capacity,
|
|
||||||
(ULONG_PTR)buffer, (ULONG_PTR)buffer + capacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
X64CodeChunk::~X64CodeChunk() {
|
X64CodeChunk::~X64CodeChunk() {
|
||||||
|
@ -157,7 +137,7 @@ typedef enum _UNWIND_OP_CODES {
|
||||||
UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
|
UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
|
||||||
} UNWIND_CODE_OPS;
|
} UNWIND_CODE_OPS;
|
||||||
class UNWIND_REGISTER {
|
class UNWIND_REGISTER {
|
||||||
public:
|
public:
|
||||||
enum _ {
|
enum _ {
|
||||||
RAX = 0,
|
RAX = 0,
|
||||||
RCX = 1,
|
RCX = 1,
|
||||||
|
@ -182,25 +162,25 @@ typedef union _UNWIND_CODE {
|
||||||
struct {
|
struct {
|
||||||
uint8_t CodeOffset;
|
uint8_t CodeOffset;
|
||||||
uint8_t UnwindOp : 4;
|
uint8_t UnwindOp : 4;
|
||||||
uint8_t OpInfo : 4;
|
uint8_t OpInfo : 4;
|
||||||
};
|
};
|
||||||
USHORT FrameOffset;
|
USHORT FrameOffset;
|
||||||
} UNWIND_CODE, *PUNWIND_CODE;
|
} UNWIND_CODE, *PUNWIND_CODE;
|
||||||
|
|
||||||
typedef struct _UNWIND_INFO {
|
typedef struct _UNWIND_INFO {
|
||||||
uint8_t Version : 3;
|
uint8_t Version : 3;
|
||||||
uint8_t Flags : 5;
|
uint8_t Flags : 5;
|
||||||
uint8_t SizeOfProlog;
|
uint8_t SizeOfProlog;
|
||||||
uint8_t CountOfCodes;
|
uint8_t CountOfCodes;
|
||||||
uint8_t FrameRegister : 4;
|
uint8_t FrameRegister : 4;
|
||||||
uint8_t FrameOffset : 4;
|
uint8_t FrameOffset : 4;
|
||||||
UNWIND_CODE UnwindCode[1];
|
UNWIND_CODE UnwindCode[1];
|
||||||
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
|
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
|
||||||
* union {
|
* union {
|
||||||
* OPTIONAL ULONG ExceptionHandler;
|
* OPTIONAL ULONG ExceptionHandler;
|
||||||
* OPTIONAL ULONG FunctionEntry;
|
* OPTIONAL ULONG FunctionEntry;
|
||||||
* };
|
* };
|
||||||
* OPTIONAL ULONG ExceptionData[]; */
|
* OPTIONAL ULONG ExceptionData[]; */
|
||||||
} UNWIND_INFO, *PUNWIND_INFO;
|
} UNWIND_INFO, *PUNWIND_INFO;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -215,19 +195,17 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size,
|
||||||
RtlDeleteGrowableFunctionTable(fn_table_handle);
|
RtlDeleteGrowableFunctionTable(fn_table_handle);
|
||||||
size_t old_size = fn_table_capacity * sizeof(RUNTIME_FUNCTION);
|
size_t old_size = fn_table_capacity * sizeof(RUNTIME_FUNCTION);
|
||||||
size_t new_size = old_size * 2;
|
size_t new_size = old_size * 2;
|
||||||
auto new_table = (RUNTIME_FUNCTION*)xe_realloc(fn_table, old_size, new_size);
|
auto new_table =
|
||||||
|
(RUNTIME_FUNCTION*)xe_realloc(fn_table, old_size, new_size);
|
||||||
XEASSERTNOTNULL(new_table);
|
XEASSERTNOTNULL(new_table);
|
||||||
if (!new_table) {
|
if (!new_table) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fn_table = new_table;
|
fn_table = new_table;
|
||||||
fn_table_capacity *= 2;
|
fn_table_capacity *= 2;
|
||||||
RtlAddGrowableFunctionTable(
|
RtlAddGrowableFunctionTable(&fn_table_handle, fn_table, fn_table_count,
|
||||||
&fn_table_handle,
|
fn_table_capacity, (ULONG_PTR)buffer,
|
||||||
fn_table,
|
(ULONG_PTR)buffer + capacity);
|
||||||
fn_table_count,
|
|
||||||
fn_table_capacity,
|
|
||||||
(ULONG_PTR)buffer, (ULONG_PTR)buffer + capacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate unwind data. We know we have space because we overallocated.
|
// Allocate unwind data. We know we have space because we overallocated.
|
||||||
|
@ -261,7 +239,8 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size,
|
||||||
// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
|
// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
|
||||||
size_t co = 0;
|
size_t co = 0;
|
||||||
auto& unwind_code = unwind_info->UnwindCode[co++];
|
auto& unwind_code = unwind_info->UnwindCode[co++];
|
||||||
unwind_code.CodeOffset = 14; // end of instruction + 1 == offset of next instruction
|
unwind_code.CodeOffset =
|
||||||
|
14; // end of instruction + 1 == offset of next instruction
|
||||||
unwind_code.UnwindOp = UWOP_ALLOC_SMALL;
|
unwind_code.UnwindOp = UWOP_ALLOC_SMALL;
|
||||||
unwind_code.OpInfo = stack_size / 8 - 1;
|
unwind_code.OpInfo = stack_size / 8 - 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -280,7 +259,8 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size,
|
||||||
// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
|
// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
|
||||||
size_t co = 0;
|
size_t co = 0;
|
||||||
auto& unwind_code = unwind_info->UnwindCode[co++];
|
auto& unwind_code = unwind_info->UnwindCode[co++];
|
||||||
unwind_code.CodeOffset = 7; // end of instruction + 1 == offset of next instruction
|
unwind_code.CodeOffset =
|
||||||
|
7; // end of instruction + 1 == offset of next instruction
|
||||||
unwind_code.UnwindOp = UWOP_ALLOC_LARGE;
|
unwind_code.UnwindOp = UWOP_ALLOC_LARGE;
|
||||||
unwind_code.OpInfo = 0;
|
unwind_code.OpInfo = 0;
|
||||||
unwind_code = unwind_info->UnwindCode[co++];
|
unwind_code = unwind_info->UnwindCode[co++];
|
||||||
|
@ -296,3 +276,7 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size,
|
||||||
// Notify the function table that it has new entries.
|
// Notify the function table that it has new entries.
|
||||||
RtlGrowFunctionTable(fn_table_handle, fn_table_count);
|
RtlGrowFunctionTable(fn_table_handle, fn_table_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace x64
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
@ -22,7 +21,7 @@ namespace x64 {
|
||||||
class X64CodeChunk;
|
class X64CodeChunk;
|
||||||
|
|
||||||
class X64CodeCache {
|
class X64CodeCache {
|
||||||
public:
|
public:
|
||||||
X64CodeCache(size_t chunk_size = DEFAULT_CHUNK_SIZE);
|
X64CodeCache(size_t chunk_size = DEFAULT_CHUNK_SIZE);
|
||||||
virtual ~X64CodeCache();
|
virtual ~X64CodeCache();
|
||||||
|
|
||||||
|
@ -34,18 +33,16 @@ public:
|
||||||
|
|
||||||
void* PlaceCode(void* machine_code, size_t code_size, size_t stack_size);
|
void* PlaceCode(void* machine_code, size_t code_size, size_t stack_size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const static size_t DEFAULT_CHUNK_SIZE = 4 * 1024 * 1024;
|
const static size_t DEFAULT_CHUNK_SIZE = 4 * 1024 * 1024;
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
size_t chunk_size_;
|
size_t chunk_size_;
|
||||||
X64CodeChunk* head_chunk_;
|
X64CodeChunk* head_chunk_;
|
||||||
X64CodeChunk* active_chunk_;
|
X64CodeChunk* active_chunk_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_X64_CODE_CACHE_H_
|
#endif // ALLOY_BACKEND_X64_X64_CODE_CACHE_H_
|
||||||
|
|
|
@ -20,18 +20,21 @@
|
||||||
#include <alloy/runtime/symbol_info.h>
|
#include <alloy/runtime/symbol_info.h>
|
||||||
#include <alloy/runtime/thread_state.h>
|
#include <alloy/runtime/thread_state.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::backend::x64;
|
namespace x64 {
|
||||||
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
using namespace alloy::runtime;
|
using namespace alloy::runtime;
|
||||||
|
|
||||||
using namespace Xbyak;
|
using namespace Xbyak;
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::hir::Instr;
|
||||||
namespace alloy {
|
using alloy::runtime::Function;
|
||||||
namespace backend {
|
using alloy::runtime::FunctionInfo;
|
||||||
namespace x64 {
|
using alloy::runtime::SourceMapEntry;
|
||||||
|
using alloy::runtime::ThreadState;
|
||||||
|
|
||||||
static const size_t MAX_CODE_SIZE = 1 * 1024 * 1024;
|
static const size_t MAX_CODE_SIZE = 1 * 1024 * 1024;
|
||||||
|
|
||||||
|
@ -42,41 +45,29 @@ static const size_t STASH_OFFSET = 32;
|
||||||
// can get the value.
|
// can get the value.
|
||||||
#define STORE_EFLAGS 1
|
#define STORE_EFLAGS 1
|
||||||
|
|
||||||
} // namespace x64
|
|
||||||
} // namespace backend
|
|
||||||
} // namespace alloy
|
|
||||||
|
|
||||||
|
|
||||||
const uint32_t X64Emitter::gpr_reg_map_[X64Emitter::GPR_COUNT] = {
|
const uint32_t X64Emitter::gpr_reg_map_[X64Emitter::GPR_COUNT] = {
|
||||||
Operand::RBX,
|
Operand::RBX, Operand::R12, Operand::R13, Operand::R14, Operand::R15,
|
||||||
Operand::R12, Operand::R13, Operand::R14, Operand::R15,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
|
const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
|
||||||
6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator)
|
||||||
|
: runtime_(backend->runtime()),
|
||||||
|
backend_(backend),
|
||||||
|
code_cache_(backend->code_cache()),
|
||||||
|
allocator_(allocator),
|
||||||
|
current_instr_(0),
|
||||||
|
CodeGenerator(MAX_CODE_SIZE, AutoGrow, allocator) {}
|
||||||
|
|
||||||
X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator) :
|
X64Emitter::~X64Emitter() {}
|
||||||
runtime_(backend->runtime()),
|
|
||||||
backend_(backend),
|
|
||||||
code_cache_(backend->code_cache()),
|
|
||||||
allocator_(allocator),
|
|
||||||
current_instr_(0),
|
|
||||||
CodeGenerator(MAX_CODE_SIZE, AutoGrow, allocator) {
|
|
||||||
}
|
|
||||||
|
|
||||||
X64Emitter::~X64Emitter() {
|
int X64Emitter::Initialize() { return 0; }
|
||||||
}
|
|
||||||
|
|
||||||
int X64Emitter::Initialize() {
|
int X64Emitter::Emit(HIRBuilder* builder, uint32_t debug_info_flags,
|
||||||
return 0;
|
runtime::DebugInfo* debug_info, void*& out_code_address,
|
||||||
}
|
size_t& out_code_size) {
|
||||||
|
|
||||||
int X64Emitter::Emit(
|
|
||||||
HIRBuilder* builder,
|
|
||||||
uint32_t debug_info_flags, runtime::DebugInfo* debug_info,
|
|
||||||
void*& out_code_address, size_t& out_code_size) {
|
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
|
||||||
// Reset.
|
// Reset.
|
||||||
|
@ -99,8 +90,7 @@ int X64Emitter::Emit(
|
||||||
// Stash source map.
|
// Stash source map.
|
||||||
if (debug_info_flags & DEBUG_INFO_SOURCE_MAP) {
|
if (debug_info_flags & DEBUG_INFO_SOURCE_MAP) {
|
||||||
debug_info->InitializeSourceMap(
|
debug_info->InitializeSourceMap(
|
||||||
source_map_count_,
|
source_map_count_, (SourceMapEntry*)source_map_arena_.CloneContents());
|
||||||
(SourceMapEntry*)source_map_arena_.CloneContents());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -158,7 +148,7 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||||
mov(qword[rsp + StackLayout::GUEST_RCX_HOME], rcx);
|
mov(qword[rsp + StackLayout::GUEST_RCX_HOME], rcx);
|
||||||
mov(qword[rsp + StackLayout::GUEST_RET_ADDR], rdx);
|
mov(qword[rsp + StackLayout::GUEST_RET_ADDR], rdx);
|
||||||
mov(qword[rsp + StackLayout::GUEST_CALL_RET_ADDR], 0);
|
mov(qword[rsp + StackLayout::GUEST_CALL_RET_ADDR], 0);
|
||||||
mov(rdx, qword[rcx + 8]); // membase
|
mov(rdx, qword[rcx + 8]); // membase
|
||||||
}
|
}
|
||||||
|
|
||||||
// Body.
|
// Body.
|
||||||
|
@ -208,9 +198,9 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||||
|
|
||||||
void X64Emitter::MarkSourceOffset(const Instr* i) {
|
void X64Emitter::MarkSourceOffset(const Instr* i) {
|
||||||
auto entry = source_map_arena_.Alloc<SourceMapEntry>();
|
auto entry = source_map_arena_.Alloc<SourceMapEntry>();
|
||||||
entry->source_offset = i->src1.offset;
|
entry->source_offset = i->src1.offset;
|
||||||
entry->hir_offset = uint32_t(i->block->ordinal << 16) | i->ordinal;
|
entry->hir_offset = uint32_t(i->block->ordinal << 16) | i->ordinal;
|
||||||
entry->code_offset = getSize();
|
entry->code_offset = getSize();
|
||||||
source_map_count_++;
|
source_map_count_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,20 +211,20 @@ void X64Emitter::DebugBreak() {
|
||||||
|
|
||||||
void X64Emitter::Trap(uint16_t trap_type) {
|
void X64Emitter::Trap(uint16_t trap_type) {
|
||||||
switch (trap_type) {
|
switch (trap_type) {
|
||||||
case 20:
|
case 20:
|
||||||
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
|
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
|
||||||
// TODO(benvanik): debug print at runtime.
|
// TODO(benvanik): debug print at runtime.
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
case 22:
|
case 22:
|
||||||
// Always trap?
|
// Always trap?
|
||||||
// TODO(benvanik): post software interrupt to debugger.
|
// TODO(benvanik): post software interrupt to debugger.
|
||||||
db(0xCC);
|
db(0xCC);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XELOGW("Unknown trap type %d", trap_type);
|
XELOGW("Unknown trap type %d", trap_type);
|
||||||
db(0xCC);
|
db(0xCC);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +248,8 @@ const size_t ASM_OFFSET = 2 + 2 + 8 + 2 + 8;
|
||||||
// 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
|
// 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
|
||||||
// 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
|
// 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
|
||||||
// 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
|
// 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
|
||||||
// 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H] 66 0F 1F 84 00 00 00 00 00H
|
// 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H] 66 0F 1F 84 00 00 00 00
|
||||||
|
// 00H
|
||||||
|
|
||||||
uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
||||||
// TODO(benvanik): generate this thunk at runtime? or a shim?
|
// TODO(benvanik): generate this thunk at runtime? or a shim?
|
||||||
|
@ -275,7 +266,7 @@ uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
||||||
// Overwrite the call site.
|
// Overwrite the call site.
|
||||||
// The return address points to ReloadRCX work after the call.
|
// The return address points to ReloadRCX work after the call.
|
||||||
uint64_t return_address = reinterpret_cast<uint64_t>(_ReturnAddress());
|
uint64_t return_address = reinterpret_cast<uint64_t>(_ReturnAddress());
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct Asm {
|
struct Asm {
|
||||||
uint16_t mov_rax;
|
uint16_t mov_rax;
|
||||||
uint64_t rax_constant;
|
uint64_t rax_constant;
|
||||||
|
@ -284,7 +275,7 @@ uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
||||||
uint16_t call_rax;
|
uint16_t call_rax;
|
||||||
uint8_t mov_rcx[5];
|
uint8_t mov_rcx[5];
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
Asm* code = reinterpret_cast<Asm*>(return_address - ASM_OFFSET);
|
Asm* code = reinterpret_cast<Asm*>(return_address - ASM_OFFSET);
|
||||||
code->rax_constant = addr;
|
code->rax_constant = addr;
|
||||||
code->call_rax = 0x9066;
|
code->call_rax = 0x9066;
|
||||||
|
@ -293,7 +284,8 @@ uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::Call(const hir::Instr* instr, runtime::FunctionInfo* symbol_info) {
|
void X64Emitter::Call(const hir::Instr* instr,
|
||||||
|
runtime::FunctionInfo* symbol_info) {
|
||||||
auto fn = reinterpret_cast<X64Function*>(symbol_info->function());
|
auto fn = reinterpret_cast<X64Function*>(symbol_info->function());
|
||||||
// Resolve address to the function to call and store in rax.
|
// Resolve address to the function to call and store in rax.
|
||||||
// TODO(benvanik): caching/etc. For now this makes debugging easier.
|
// TODO(benvanik): caching/etc. For now this makes debugging easier.
|
||||||
|
@ -372,12 +364,12 @@ void X64Emitter::CallIndirect(const hir::Instr* instr, const Reg64& reg) {
|
||||||
|
|
||||||
uint64_t UndefinedCallExtern(void* raw_context, uint64_t symbol_info_ptr) {
|
uint64_t UndefinedCallExtern(void* raw_context, uint64_t symbol_info_ptr) {
|
||||||
auto symbol_info = reinterpret_cast<FunctionInfo*>(symbol_info_ptr);
|
auto symbol_info = reinterpret_cast<FunctionInfo*>(symbol_info_ptr);
|
||||||
XELOGW("undefined extern call to %.8X %s",
|
XELOGW("undefined extern call to %.8X %s", symbol_info->address(),
|
||||||
symbol_info->address(),
|
|
||||||
symbol_info->name());
|
symbol_info->name());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void X64Emitter::CallExtern(const hir::Instr* instr, const FunctionInfo* symbol_info) {
|
void X64Emitter::CallExtern(const hir::Instr* instr,
|
||||||
|
const FunctionInfo* symbol_info) {
|
||||||
XEASSERT(symbol_info->behavior() == FunctionInfo::BEHAVIOR_EXTERN);
|
XEASSERT(symbol_info->behavior() == FunctionInfo::BEHAVIOR_EXTERN);
|
||||||
if (!symbol_info->extern_handler()) {
|
if (!symbol_info->extern_handler()) {
|
||||||
CallNative(UndefinedCallExtern, reinterpret_cast<uint64_t>(symbol_info));
|
CallNative(UndefinedCallExtern, reinterpret_cast<uint64_t>(symbol_info));
|
||||||
|
@ -405,21 +397,22 @@ void X64Emitter::CallNative(void* fn) {
|
||||||
ReloadEDX();
|
ReloadEDX();
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::CallNative(uint64_t(*fn)(void* raw_context)) {
|
void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context)) {
|
||||||
mov(rax, reinterpret_cast<uint64_t>(fn));
|
mov(rax, reinterpret_cast<uint64_t>(fn));
|
||||||
call(rax);
|
call(rax);
|
||||||
ReloadECX();
|
ReloadECX();
|
||||||
ReloadEDX();
|
ReloadEDX();
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0)) {
|
void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0)) {
|
||||||
mov(rax, reinterpret_cast<uint64_t>(fn));
|
mov(rax, reinterpret_cast<uint64_t>(fn));
|
||||||
call(rax);
|
call(rax);
|
||||||
ReloadECX();
|
ReloadECX();
|
||||||
ReloadEDX();
|
ReloadEDX();
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0), uint64_t arg0) {
|
void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0),
|
||||||
|
uint64_t arg0) {
|
||||||
mov(rdx, arg0);
|
mov(rdx, arg0);
|
||||||
mov(rax, reinterpret_cast<uint64_t>(fn));
|
mov(rax, reinterpret_cast<uint64_t>(fn));
|
||||||
call(rax);
|
call(rax);
|
||||||
|
@ -428,17 +421,17 @@ void X64Emitter::CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0), uin
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::CallNativeSafe(void* fn) {
|
void X64Emitter::CallNativeSafe(void* fn) {
|
||||||
// rcx = context
|
// rcx = context
|
||||||
// rdx = target host function
|
// rdx = target host function
|
||||||
// r8 = arg0
|
// r8 = arg0
|
||||||
// r9 = arg1
|
// r9 = arg1
|
||||||
mov(rdx, reinterpret_cast<uint64_t>(fn));
|
mov(rdx, reinterpret_cast<uint64_t>(fn));
|
||||||
auto thunk = backend()->guest_to_host_thunk();
|
auto thunk = backend()->guest_to_host_thunk();
|
||||||
mov(rax, reinterpret_cast<uint64_t>(thunk));
|
mov(rax, reinterpret_cast<uint64_t>(thunk));
|
||||||
call(rax);
|
call(rax);
|
||||||
ReloadECX();
|
ReloadECX();
|
||||||
ReloadEDX();
|
ReloadEDX();
|
||||||
// rax = host return
|
// rax = host return
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::SetReturnAddress(uint64_t value) {
|
void X64Emitter::SetReturnAddress(uint64_t value) {
|
||||||
|
@ -450,7 +443,7 @@ void X64Emitter::ReloadECX() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::ReloadEDX() {
|
void X64Emitter::ReloadEDX() {
|
||||||
mov(rdx, qword[rcx + 8]); // membase
|
mov(rdx, qword[rcx + 8]); // membase
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::LoadEflags() {
|
void X64Emitter::LoadEflags() {
|
||||||
|
@ -459,7 +452,7 @@ void X64Emitter::LoadEflags() {
|
||||||
push(rax);
|
push(rax);
|
||||||
popf();
|
popf();
|
||||||
#else
|
#else
|
||||||
// EFLAGS already present.
|
// EFLAGS already present.
|
||||||
#endif // STORE_EFLAGS
|
#endif // STORE_EFLAGS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,8 +461,8 @@ void X64Emitter::StoreEflags() {
|
||||||
pushf();
|
pushf();
|
||||||
pop(qword[rsp + STASH_OFFSET]);
|
pop(qword[rsp + STASH_OFFSET]);
|
||||||
#else
|
#else
|
||||||
// EFLAGS should have CA set?
|
// EFLAGS should have CA set?
|
||||||
// (so long as we don't fuck with it)
|
// (so long as we don't fuck with it)
|
||||||
#endif // STORE_EFLAGS
|
#endif // STORE_EFLAGS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,32 +504,51 @@ void X64Emitter::MovMem64(const RegExp& addr, uint64_t v) {
|
||||||
|
|
||||||
Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
||||||
static const vec128_t xmm_consts[] = {
|
static const vec128_t xmm_consts[] = {
|
||||||
/* XMMZero */ vec128f(0.0f, 0.0f, 0.0f, 0.0f),
|
/* XMMZero */ vec128f(0.0f, 0.0f, 0.0f, 0.0f),
|
||||||
/* XMMOne */ vec128f(1.0f, 1.0f, 1.0f, 1.0f),
|
/* XMMOne */ vec128f(1.0f, 1.0f, 1.0f, 1.0f),
|
||||||
/* XMMNegativeOne */ vec128f(-1.0f, -1.0f, -1.0f, -1.0f),
|
/* XMMNegativeOne */ vec128f(-1.0f, -1.0f, -1.0f, -1.0f),
|
||||||
/* XMMMaskX16Y16 */ vec128i(0x0000FFFFu, 0xFFFF0000u, 0x00000000u, 0x00000000u),
|
/* XMMMaskX16Y16 */ vec128i(0x0000FFFFu, 0xFFFF0000u,
|
||||||
/* XMMFlipX16Y16 */ vec128i(0x00008000u, 0x00000000u, 0x00000000u, 0x00000000u),
|
0x00000000u, 0x00000000u),
|
||||||
/* XMMFixX16Y16 */ vec128f(-32768.0f, 0.0f, 0.0f, 0.0f),
|
/* XMMFlipX16Y16 */ vec128i(0x00008000u, 0x00000000u,
|
||||||
/* XMMNormalizeX16Y16 */ vec128f(1.0f / 32767.0f, 1.0f / (32767.0f * 65536.0f), 0.0f, 0.0f),
|
0x00000000u, 0x00000000u),
|
||||||
/* XMM0001 */ vec128f(0.0f, 0.0f, 0.0f, 1.0f),
|
/* XMMFixX16Y16 */ vec128f(-32768.0f, 0.0f, 0.0f, 0.0f),
|
||||||
/* XMM3301 */ vec128f(3.0f, 3.0f, 0.0f, 1.0f),
|
/* XMMNormalizeX16Y16 */ vec128f(
|
||||||
/* XMMSignMaskPS */ vec128i(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u),
|
1.0f / 32767.0f, 1.0f / (32767.0f * 65536.0f), 0.0f, 0.0f),
|
||||||
/* XMMSignMaskPD */ vec128i(0x00000000u, 0x80000000u, 0x00000000u, 0x80000000u),
|
/* XMM0001 */ vec128f(0.0f, 0.0f, 0.0f, 1.0f),
|
||||||
/* XMMAbsMaskPS */ vec128i(0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu),
|
/* XMM3301 */ vec128f(3.0f, 3.0f, 0.0f, 1.0f),
|
||||||
/* XMMAbsMaskPD */ vec128i(0xFFFFFFFFu, 0x7FFFFFFFu, 0xFFFFFFFFu, 0x7FFFFFFFu),
|
/* XMMSignMaskPS */ vec128i(0x80000000u, 0x80000000u,
|
||||||
/* XMMByteSwapMask */ vec128i(0x00010203u, 0x04050607u, 0x08090A0Bu, 0x0C0D0E0Fu),
|
0x80000000u, 0x80000000u),
|
||||||
/* XMMPermuteControl15 */ vec128b(15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15),
|
/* XMMSignMaskPD */ vec128i(0x00000000u, 0x80000000u,
|
||||||
/* XMMPackD3DCOLOR */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x0C000408u),
|
0x00000000u, 0x80000000u),
|
||||||
/* XMMUnpackD3DCOLOR */ vec128i(0xFFFFFF0Eu, 0xFFFFFF0Du, 0xFFFFFF0Cu, 0xFFFFFF0Fu),
|
/* XMMAbsMaskPS */ vec128i(0x7FFFFFFFu, 0x7FFFFFFFu,
|
||||||
/* XMMOneOver255 */ vec128f(1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f),
|
0x7FFFFFFFu, 0x7FFFFFFFu),
|
||||||
/* XMMShiftMaskPS */ vec128i(0x0000001Fu, 0x0000001Fu, 0x0000001Fu, 0x0000001Fu),
|
/* XMMAbsMaskPD */ vec128i(0xFFFFFFFFu, 0x7FFFFFFFu,
|
||||||
/* XMMShiftByteMask */ vec128i(0x000000FFu, 0x000000FFu, 0x000000FFu, 0x000000FFu),
|
0xFFFFFFFFu, 0x7FFFFFFFu),
|
||||||
/* XMMUnsignedDwordMax */ vec128i(0xFFFFFFFFu, 0x00000000u, 0xFFFFFFFFu, 0x00000000u),
|
/* XMMByteSwapMask */ vec128i(0x00010203u, 0x04050607u,
|
||||||
/* XMM255 */ vec128f(255.0f, 255.0f, 255.0f, 255.0f),
|
0x08090A0Bu, 0x0C0D0E0Fu),
|
||||||
/* XMMSignMaskI8 */ vec128i(0x80808080u, 0x80808080u, 0x80808080u, 0x80808080u),
|
/* XMMPermuteControl15 */ vec128b(15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||||
/* XMMSignMaskI16 */ vec128i(0x80008000u, 0x80008000u, 0x80008000u, 0x80008000u),
|
15, 15, 15, 15, 15, 15, 15),
|
||||||
/* XMMSignMaskI32 */ vec128i(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u),
|
/* XMMPackD3DCOLOR */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||||
/* XMMSignMaskF32 */ vec128i(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u),
|
0xFFFFFFFFu, 0x0C000408u),
|
||||||
|
/* XMMUnpackD3DCOLOR */ vec128i(0xFFFFFF0Eu, 0xFFFFFF0Du,
|
||||||
|
0xFFFFFF0Cu, 0xFFFFFF0Fu),
|
||||||
|
/* XMMOneOver255 */ vec128f(1.0f / 255.0f, 1.0f / 255.0f,
|
||||||
|
1.0f / 255.0f, 1.0f / 255.0f),
|
||||||
|
/* XMMShiftMaskPS */ vec128i(0x0000001Fu, 0x0000001Fu,
|
||||||
|
0x0000001Fu, 0x0000001Fu),
|
||||||
|
/* XMMShiftByteMask */ vec128i(0x000000FFu, 0x000000FFu,
|
||||||
|
0x000000FFu, 0x000000FFu),
|
||||||
|
/* XMMUnsignedDwordMax */ vec128i(0xFFFFFFFFu, 0x00000000u,
|
||||||
|
0xFFFFFFFFu, 0x00000000u),
|
||||||
|
/* XMM255 */ vec128f(255.0f, 255.0f, 255.0f, 255.0f),
|
||||||
|
/* XMMSignMaskI8 */ vec128i(0x80808080u, 0x80808080u,
|
||||||
|
0x80808080u, 0x80808080u),
|
||||||
|
/* XMMSignMaskI16 */ vec128i(0x80008000u, 0x80008000u,
|
||||||
|
0x80008000u, 0x80008000u),
|
||||||
|
/* XMMSignMaskI32 */ vec128i(0x80000000u, 0x80000000u,
|
||||||
|
0x80000000u, 0x80000000u),
|
||||||
|
/* XMMSignMaskF32 */ vec128i(0x80000000u, 0x80000000u,
|
||||||
|
0x80000000u, 0x80000000u),
|
||||||
};
|
};
|
||||||
// TODO(benvanik): cache base pointer somewhere? stack? It'd be nice to
|
// TODO(benvanik): cache base pointer somewhere? stack? It'd be nice to
|
||||||
// prevent this move.
|
// prevent this move.
|
||||||
|
@ -568,7 +580,7 @@ void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, float v) {
|
||||||
union {
|
union {
|
||||||
float f;
|
float f;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
} x = { v };
|
} x = {v};
|
||||||
if (!v) {
|
if (!v) {
|
||||||
// 0
|
// 0
|
||||||
vpxor(dest, dest);
|
vpxor(dest, dest);
|
||||||
|
@ -587,7 +599,7 @@ void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, double v) {
|
||||||
union {
|
union {
|
||||||
double d;
|
double d;
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
} x = { v };
|
} x = {v};
|
||||||
if (!v) {
|
if (!v) {
|
||||||
// 0
|
// 0
|
||||||
vpxor(dest, dest);
|
vpxor(dest, dest);
|
||||||
|
@ -614,3 +626,7 @@ Address X64Emitter::StashXmm(const vec128_t& v) {
|
||||||
vmovups(addr, xmm0);
|
vmovups(addr, xmm0);
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace x64
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -31,12 +31,12 @@ class X64Backend;
|
||||||
class X64CodeCache;
|
class X64CodeCache;
|
||||||
|
|
||||||
enum RegisterFlags {
|
enum RegisterFlags {
|
||||||
REG_DEST = (1 << 0),
|
REG_DEST = (1 << 0),
|
||||||
REG_ABCD = (1 << 1),
|
REG_ABCD = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum XmmConst {
|
enum XmmConst {
|
||||||
XMMZero = 0,
|
XMMZero = 0,
|
||||||
XMMOne,
|
XMMOne,
|
||||||
XMMNegativeOne,
|
XMMNegativeOne,
|
||||||
XMMMaskX16Y16,
|
XMMMaskX16Y16,
|
||||||
|
@ -66,12 +66,12 @@ enum XmmConst {
|
||||||
|
|
||||||
// Unfortunately due to the design of xbyak we have to pass this to the ctor.
|
// Unfortunately due to the design of xbyak we have to pass this to the ctor.
|
||||||
class XbyakAllocator : public Xbyak::Allocator {
|
class XbyakAllocator : public Xbyak::Allocator {
|
||||||
public:
|
public:
|
||||||
virtual bool useProtect() const { return false; }
|
virtual bool useProtect() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class X64Emitter : public Xbyak::CodeGenerator {
|
class X64Emitter : public Xbyak::CodeGenerator {
|
||||||
public:
|
public:
|
||||||
X64Emitter(X64Backend* backend, XbyakAllocator* allocator);
|
X64Emitter(X64Backend* backend, XbyakAllocator* allocator);
|
||||||
virtual ~X64Emitter();
|
virtual ~X64Emitter();
|
||||||
|
|
||||||
|
@ -80,11 +80,11 @@ public:
|
||||||
|
|
||||||
int Initialize();
|
int Initialize();
|
||||||
|
|
||||||
int Emit(hir::HIRBuilder* builder,
|
int Emit(hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||||
uint32_t debug_info_flags, runtime::DebugInfo* debug_info,
|
runtime::DebugInfo* debug_info, void*& out_code_address,
|
||||||
void*& out_code_address, size_t& out_code_size);
|
size_t& out_code_size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Reserved: rsp
|
// Reserved: rsp
|
||||||
// Scratch: rax/rcx/rdx
|
// Scratch: rax/rcx/rdx
|
||||||
// xmm0-2 (could be only xmm0 with some trickery)
|
// xmm0-2 (could be only xmm0 with some trickery)
|
||||||
|
@ -123,11 +123,13 @@ public:
|
||||||
|
|
||||||
void Call(const hir::Instr* instr, runtime::FunctionInfo* symbol_info);
|
void Call(const hir::Instr* instr, runtime::FunctionInfo* symbol_info);
|
||||||
void CallIndirect(const hir::Instr* instr, const Xbyak::Reg64& reg);
|
void CallIndirect(const hir::Instr* instr, const Xbyak::Reg64& reg);
|
||||||
void CallExtern(const hir::Instr* instr, const runtime::FunctionInfo* symbol_info);
|
void CallExtern(const hir::Instr* instr,
|
||||||
|
const runtime::FunctionInfo* symbol_info);
|
||||||
void CallNative(void* fn);
|
void CallNative(void* fn);
|
||||||
void CallNative(uint64_t(*fn)(void* raw_context));
|
void CallNative(uint64_t (*fn)(void* raw_context));
|
||||||
void CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0));
|
void CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0));
|
||||||
void CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0), uint64_t arg0);
|
void CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0),
|
||||||
|
uint64_t arg0);
|
||||||
void CallNativeSafe(void* fn);
|
void CallNativeSafe(void* fn);
|
||||||
void SetReturnAddress(uint64_t value);
|
void SetReturnAddress(uint64_t value);
|
||||||
void ReloadECX();
|
void ReloadECX();
|
||||||
|
@ -153,31 +155,29 @@ public:
|
||||||
|
|
||||||
size_t stack_size() const { return stack_size_; }
|
size_t stack_size() const { return stack_size_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void* Emplace(size_t stack_size);
|
void* Emplace(size_t stack_size);
|
||||||
int Emit(hir::HIRBuilder* builder, size_t& out_stack_size);
|
int Emit(hir::HIRBuilder* builder, size_t& out_stack_size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
runtime::Runtime* runtime_;
|
runtime::Runtime* runtime_;
|
||||||
X64Backend* backend_;
|
X64Backend* backend_;
|
||||||
X64CodeCache* code_cache_;
|
X64CodeCache* code_cache_;
|
||||||
XbyakAllocator* allocator_;
|
XbyakAllocator* allocator_;
|
||||||
|
|
||||||
hir::Instr* current_instr_;
|
hir::Instr* current_instr_;
|
||||||
|
|
||||||
size_t source_map_count_;
|
size_t source_map_count_;
|
||||||
Arena source_map_arena_;
|
Arena source_map_arena_;
|
||||||
|
|
||||||
size_t stack_size_;
|
size_t stack_size_;
|
||||||
|
|
||||||
static const uint32_t gpr_reg_map_[GPR_COUNT];
|
static const uint32_t gpr_reg_map_[GPR_COUNT];
|
||||||
static const uint32_t xmm_reg_map_[XMM_COUNT];
|
static const uint32_t xmm_reg_map_[XMM_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_X64_EMITTER_H_
|
#endif // ALLOY_BACKEND_X64_X64_EMITTER_H_
|
||||||
|
|
|
@ -14,16 +14,17 @@
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
#include <alloy/runtime/thread_state.h>
|
#include <alloy/runtime/thread_state.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace backend {
|
||||||
using namespace alloy::backend::x64;
|
namespace x64 {
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::runtime::Breakpoint;
|
||||||
|
using alloy::runtime::Function;
|
||||||
|
using alloy::runtime::FunctionInfo;
|
||||||
|
using alloy::runtime::ThreadState;
|
||||||
|
|
||||||
X64Function::X64Function(FunctionInfo* symbol_info) :
|
X64Function::X64Function(FunctionInfo* symbol_info)
|
||||||
machine_code_(NULL), code_size_(0),
|
: machine_code_(NULL), code_size_(0), Function(symbol_info) {}
|
||||||
Function(symbol_info) {
|
|
||||||
}
|
|
||||||
|
|
||||||
X64Function::~X64Function() {
|
X64Function::~X64Function() {
|
||||||
// machine_code_ is freed by code cache.
|
// machine_code_ is freed by code cache.
|
||||||
|
@ -34,20 +35,17 @@ void X64Function::Setup(void* machine_code, size_t code_size) {
|
||||||
code_size_ = code_size;
|
code_size_ = code_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Function::AddBreakpointImpl(Breakpoint* breakpoint) {
|
int X64Function::AddBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) {
|
int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int X64Function::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
int X64Function::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
||||||
auto backend = (X64Backend*)thread_state->runtime()->backend();
|
auto backend = (X64Backend*)thread_state->runtime()->backend();
|
||||||
auto thunk = backend->host_to_guest_thunk();
|
auto thunk = backend->host_to_guest_thunk();
|
||||||
thunk(
|
thunk(machine_code_, thread_state->raw_context(), (void*)return_address);
|
||||||
machine_code_,
|
|
||||||
thread_state->raw_context(),
|
|
||||||
(void*)return_address);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace x64
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,14 +14,12 @@
|
||||||
#include <alloy/runtime/function.h>
|
#include <alloy/runtime/function.h>
|
||||||
#include <alloy/runtime/symbol_info.h>
|
#include <alloy/runtime/symbol_info.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
|
|
||||||
class X64Function : public runtime::Function {
|
class X64Function : public runtime::Function {
|
||||||
public:
|
public:
|
||||||
X64Function(runtime::FunctionInfo* symbol_info);
|
X64Function(runtime::FunctionInfo* symbol_info);
|
||||||
virtual ~X64Function();
|
virtual ~X64Function();
|
||||||
|
|
||||||
|
@ -30,21 +28,19 @@ public:
|
||||||
|
|
||||||
void Setup(void* machine_code, size_t code_size);
|
void Setup(void* machine_code, size_t code_size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int AddBreakpointImpl(runtime::Breakpoint* breakpoint);
|
virtual int AddBreakpointImpl(runtime::Breakpoint* breakpoint);
|
||||||
virtual int RemoveBreakpointImpl(runtime::Breakpoint* breakpoint);
|
virtual int RemoveBreakpointImpl(runtime::Breakpoint* breakpoint);
|
||||||
virtual int CallImpl(runtime::ThreadState* thread_state,
|
virtual int CallImpl(runtime::ThreadState* thread_state,
|
||||||
uint64_t return_address);
|
uint64_t return_address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void* machine_code_;
|
void* machine_code_;
|
||||||
size_t code_size_;
|
size_t code_size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_X64_FUNCTION_H_
|
#endif // ALLOY_BACKEND_X64_X64_FUNCTION_H_
|
||||||
|
|
|
@ -20,14 +20,12 @@ namespace x64 {
|
||||||
|
|
||||||
class X64Emitter;
|
class X64Emitter;
|
||||||
|
|
||||||
|
|
||||||
void RegisterSequences();
|
void RegisterSequences();
|
||||||
bool SelectSequence(X64Emitter& e, const hir::Instr* i, const hir::Instr** new_tail);
|
bool SelectSequence(X64Emitter& e, const hir::Instr* i,
|
||||||
|
const hir::Instr** new_tail);
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_X64_SEQUENCES_H_
|
#endif // ALLOY_BACKEND_X64_X64_SEQUENCES_H_
|
||||||
|
|
|
@ -11,21 +11,16 @@
|
||||||
|
|
||||||
#include <third_party/xbyak/xbyak/xbyak.h>
|
#include <third_party/xbyak/xbyak/xbyak.h>
|
||||||
|
|
||||||
|
namespace alloy {
|
||||||
using namespace alloy;
|
namespace backend {
|
||||||
using namespace alloy::backend;
|
namespace x64 {
|
||||||
using namespace alloy::backend::x64;
|
|
||||||
|
|
||||||
using namespace Xbyak;
|
using namespace Xbyak;
|
||||||
|
|
||||||
|
X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
|
||||||
|
: X64Emitter(backend, allocator) {}
|
||||||
|
|
||||||
X64ThunkEmitter::X64ThunkEmitter(
|
X64ThunkEmitter::~X64ThunkEmitter() {}
|
||||||
X64Backend* backend, XbyakAllocator* allocator) :
|
|
||||||
X64Emitter(backend, allocator) {
|
|
||||||
}
|
|
||||||
|
|
||||||
X64ThunkEmitter::~X64ThunkEmitter() {
|
|
||||||
}
|
|
||||||
|
|
||||||
HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
|
HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
|
||||||
// rcx = target
|
// rcx = target
|
||||||
|
@ -101,7 +96,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
|
||||||
// rdx = target function
|
// rdx = target function
|
||||||
// r8 = arg0
|
// r8 = arg0
|
||||||
// r9 = arg1
|
// r9 = arg1
|
||||||
|
|
||||||
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
|
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
|
||||||
// rsp + 0 = return address
|
// rsp + 0 = return address
|
||||||
mov(qword[rsp + 8 * 2], rdx);
|
mov(qword[rsp + 8 * 2], rdx);
|
||||||
|
@ -143,3 +138,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
|
||||||
void* fn = Emplace(stack_size);
|
void* fn = Emplace(stack_size);
|
||||||
return (HostToGuestThunk)fn;
|
return (HostToGuestThunk)fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace x64
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,12 +14,10 @@
|
||||||
#include <alloy/backend/x64/x64_backend.h>
|
#include <alloy/backend/x64/x64_backend.h>
|
||||||
#include <alloy/backend/x64/x64_emitter.h>
|
#include <alloy/backend/x64/x64_emitter.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stack Layout
|
* Stack Layout
|
||||||
* ----------------------------
|
* ----------------------------
|
||||||
|
@ -116,7 +114,7 @@ namespace x64 {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class StackLayout {
|
class StackLayout {
|
||||||
public:
|
public:
|
||||||
const static size_t THUNK_STACK_SIZE = 120;
|
const static size_t THUNK_STACK_SIZE = 120;
|
||||||
|
|
||||||
const static size_t GUEST_STACK_SIZE = 88;
|
const static size_t GUEST_STACK_SIZE = 88;
|
||||||
|
@ -125,9 +123,8 @@ public:
|
||||||
const static size_t GUEST_CALL_RET_ADDR = 80;
|
const static size_t GUEST_CALL_RET_ADDR = 80;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class X64ThunkEmitter : public X64Emitter {
|
class X64ThunkEmitter : public X64Emitter {
|
||||||
public:
|
public:
|
||||||
X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator);
|
X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator);
|
||||||
virtual ~X64ThunkEmitter();
|
virtual ~X64ThunkEmitter();
|
||||||
|
|
||||||
|
@ -138,10 +135,8 @@ public:
|
||||||
GuestToHostThunk EmitGuestToHostThunk();
|
GuestToHostThunk EmitGuestToHostThunk();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_X64_THUNK_EMITTER_H_
|
#endif // ALLOY_BACKEND_X64_X64_THUNK_EMITTER_H_
|
||||||
|
|
|
@ -27,9 +27,12 @@ namespace x64 {
|
||||||
#define TARGET_THREAD 1
|
#define TARGET_THREAD 1
|
||||||
|
|
||||||
#define IFLUSH() fflush(stdout)
|
#define IFLUSH() fflush(stdout)
|
||||||
#define IPRINT if (thread_state->thread_id() == TARGET_THREAD) printf
|
#define IPRINT \
|
||||||
|
if (thread_state->thread_id() == TARGET_THREAD) printf
|
||||||
#define DFLUSH() fflush(stdout)
|
#define DFLUSH() fflush(stdout)
|
||||||
#define DPRINT DFLUSH(); if (thread_state->thread_id() == TARGET_THREAD) printf
|
#define DPRINT \
|
||||||
|
DFLUSH(); \
|
||||||
|
if (thread_state->thread_id() == TARGET_THREAD) printf
|
||||||
|
|
||||||
uint32_t GetTracingMode() {
|
uint32_t GetTracingMode() {
|
||||||
uint32_t mode = 0;
|
uint32_t mode = 0;
|
||||||
|
@ -66,7 +69,8 @@ void TraceContextLoadI64(void* raw_context, uint64_t offset, uint64_t value) {
|
||||||
}
|
}
|
||||||
void TraceContextLoadF32(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextLoadF32(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
DPRINT("%e (%X) = ctx f32 +%d\n", value.m128_f32[0], value.m128_i32[0], offset);
|
DPRINT("%e (%X) = ctx f32 +%d\n", value.m128_f32[0], value.m128_i32[0],
|
||||||
|
offset);
|
||||||
}
|
}
|
||||||
void TraceContextLoadF64(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextLoadF64(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
|
@ -80,9 +84,9 @@ void TraceContextLoadF64(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
void TraceContextLoadV128(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextLoadV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = ctx v128 +%d\n",
|
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = ctx v128 +%d\n",
|
||||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2], value.m128_f32[3],
|
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2],
|
||||||
value.m128_i32[0], value.m128_i32[1], value.m128_i32[2], value.m128_i32[3],
|
value.m128_f32[3], value.m128_i32[0], value.m128_i32[1],
|
||||||
offset);
|
value.m128_i32[2], value.m128_i32[3], offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceContextStoreI8(void* raw_context, uint64_t offset, uint8_t value) {
|
void TraceContextStoreI8(void* raw_context, uint64_t offset, uint8_t value) {
|
||||||
|
@ -103,7 +107,8 @@ void TraceContextStoreI64(void* raw_context, uint64_t offset, uint64_t value) {
|
||||||
}
|
}
|
||||||
void TraceContextStoreF32(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextStoreF32(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
DPRINT("ctx f32 +%d = %e (%X)\n", offset, value.m128_i32[0], value.m128_f32[0]);
|
DPRINT("ctx f32 +%d = %e (%X)\n", offset, value.m128_i32[0],
|
||||||
|
value.m128_f32[0]);
|
||||||
}
|
}
|
||||||
void TraceContextStoreF64(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextStoreF64(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
|
@ -117,8 +122,9 @@ void TraceContextStoreF64(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
void TraceContextStoreV128(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextStoreV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
DPRINT("ctx v128 +%d = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", offset,
|
DPRINT("ctx v128 +%d = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", offset,
|
||||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2], value.m128_f32[3],
|
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2],
|
||||||
value.m128_i32[0], value.m128_i32[1], value.m128_i32[2], value.m128_i32[3]);
|
value.m128_f32[3], value.m128_i32[0], value.m128_i32[1],
|
||||||
|
value.m128_i32[2], value.m128_i32[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceMemoryLoadI8(void* raw_context, uint64_t address, uint8_t value) {
|
void TraceMemoryLoadI8(void* raw_context, uint64_t address, uint8_t value) {
|
||||||
|
@ -139,7 +145,8 @@ void TraceMemoryLoadI64(void* raw_context, uint64_t address, uint64_t value) {
|
||||||
}
|
}
|
||||||
void TraceMemoryLoadF32(void* raw_context, uint64_t address, __m128 value) {
|
void TraceMemoryLoadF32(void* raw_context, uint64_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
DPRINT("%e (%X) = load.f32 %.8X\n", value.m128_f32[0], value.m128_i32[0], address);
|
DPRINT("%e (%X) = load.f32 %.8X\n", value.m128_f32[0], value.m128_i32[0],
|
||||||
|
address);
|
||||||
}
|
}
|
||||||
void TraceMemoryLoadF64(void* raw_context, uint64_t address, __m128 value) {
|
void TraceMemoryLoadF64(void* raw_context, uint64_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
|
@ -153,9 +160,9 @@ void TraceMemoryLoadF64(void* raw_context, uint64_t address, __m128 value) {
|
||||||
void TraceMemoryLoadV128(void* raw_context, uint64_t address, __m128 value) {
|
void TraceMemoryLoadV128(void* raw_context, uint64_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = load.v128 %.8X\n",
|
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = load.v128 %.8X\n",
|
||||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2], value.m128_f32[3],
|
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2],
|
||||||
value.m128_i32[0], value.m128_i32[1], value.m128_i32[2], value.m128_i32[3],
|
value.m128_f32[3], value.m128_i32[0], value.m128_i32[1],
|
||||||
address);
|
value.m128_i32[2], value.m128_i32[3], address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceMemoryStoreI8(void* raw_context, uint64_t address, uint8_t value) {
|
void TraceMemoryStoreI8(void* raw_context, uint64_t address, uint8_t value) {
|
||||||
|
@ -176,7 +183,8 @@ void TraceMemoryStoreI64(void* raw_context, uint64_t address, uint64_t value) {
|
||||||
}
|
}
|
||||||
void TraceMemoryStoreF32(void* raw_context, uint64_t address, __m128 value) {
|
void TraceMemoryStoreF32(void* raw_context, uint64_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
DPRINT("store.f32 %.8X = %e (%X)\n", address, value.m128_f32[0], value.m128_i32[0]);
|
DPRINT("store.f32 %.8X = %e (%X)\n", address, value.m128_f32[0],
|
||||||
|
value.m128_i32[0]);
|
||||||
}
|
}
|
||||||
void TraceMemoryStoreF64(void* raw_context, uint64_t address, __m128 value) {
|
void TraceMemoryStoreF64(void* raw_context, uint64_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
|
@ -189,12 +197,12 @@ void TraceMemoryStoreF64(void* raw_context, uint64_t address, __m128 value) {
|
||||||
}
|
}
|
||||||
void TraceMemoryStoreV128(void* raw_context, uint64_t address, __m128 value) {
|
void TraceMemoryStoreV128(void* raw_context, uint64_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *((ThreadState**)raw_context);
|
||||||
DPRINT("store.v128 %.8X = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", address,
|
DPRINT("store.v128 %.8X = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n",
|
||||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2], value.m128_f32[3],
|
address, value.m128_f32[0], value.m128_f32[1], value.m128_f32[2],
|
||||||
value.m128_i32[0], value.m128_i32[1], value.m128_i32[2], value.m128_i32[3]);
|
value.m128_f32[3], value.m128_i32[0], value.m128_i32[1],
|
||||||
|
value.m128_i32[2], value.m128_i32[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
|
@ -16,19 +16,18 @@
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
#else
|
#else
|
||||||
typedef union __declspec(align(16)) __m128 {
|
typedef union __declspec(align(16)) __m128 {
|
||||||
float m128_f32[4];
|
float m128_f32[4];
|
||||||
uint64_t m128_u64[2];
|
uint64_t m128_u64[2];
|
||||||
int8_t m128_i8[16];
|
int8_t m128_i8[16];
|
||||||
int16_t m128_i16[8];
|
int16_t m128_i16[8];
|
||||||
int32_t m128_i32[4];
|
int32_t m128_i32[4];
|
||||||
int64_t m128_i64[2];
|
int64_t m128_i64[2];
|
||||||
uint8_t m128_u8[16];
|
uint8_t m128_u8[16];
|
||||||
uint16_t m128_u16[8];
|
uint16_t m128_u16[8];
|
||||||
uint32_t m128_u32[4];
|
uint32_t m128_u32[4];
|
||||||
} __m128;
|
} __m128;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
@ -81,5 +80,4 @@ void TraceMemoryStoreV128(void* raw_context, uint64_t address, __m128 value);
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_X64_TRACERS_H_
|
#endif // ALLOY_BACKEND_X64_X64_TRACERS_H_
|
||||||
|
|
|
@ -12,18 +12,16 @@
|
||||||
#include <alloy/compiler/compiler_pass.h>
|
#include <alloy/compiler/compiler_pass.h>
|
||||||
#include <alloy/compiler/tracing.h>
|
#include <alloy/compiler/tracing.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::compiler;
|
namespace compiler {
|
||||||
using namespace alloy::hir;
|
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::runtime::Runtime;
|
||||||
|
|
||||||
Compiler::Compiler(Runtime* runtime) :
|
Compiler::Compiler(Runtime* runtime) : runtime_(runtime) {
|
||||||
runtime_(runtime) {
|
|
||||||
scratch_arena_ = new Arena();
|
scratch_arena_ = new Arena();
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::Init({
|
alloy::tracing::WriteEvent(EventType::Init({}));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Compiler::~Compiler() {
|
Compiler::~Compiler() {
|
||||||
|
@ -36,8 +34,7 @@ Compiler::~Compiler() {
|
||||||
|
|
||||||
delete scratch_arena_;
|
delete scratch_arena_;
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::Deinit({
|
alloy::tracing::WriteEvent(EventType::Deinit({}));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::AddPass(CompilerPass* pass) {
|
void Compiler::AddPass(CompilerPass* pass) {
|
||||||
|
@ -45,8 +42,7 @@ void Compiler::AddPass(CompilerPass* pass) {
|
||||||
passes_.push_back(pass);
|
passes_.push_back(pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::Reset() {
|
void Compiler::Reset() {}
|
||||||
}
|
|
||||||
|
|
||||||
int Compiler::Compile(HIRBuilder* builder) {
|
int Compiler::Compile(HIRBuilder* builder) {
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
@ -63,3 +59,6 @@ int Compiler::Compile(HIRBuilder* builder) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -13,17 +13,19 @@
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
#include <alloy/hir/hir_builder.h>
|
#include <alloy/hir/hir_builder.h>
|
||||||
|
|
||||||
namespace alloy { namespace runtime { class Runtime; } }
|
namespace alloy {
|
||||||
|
namespace runtime {
|
||||||
|
class Runtime;
|
||||||
|
} // namespace runtime
|
||||||
|
} // namespace alloy
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
class CompilerPass;
|
class CompilerPass;
|
||||||
|
|
||||||
|
|
||||||
class Compiler {
|
class Compiler {
|
||||||
public:
|
public:
|
||||||
Compiler(runtime::Runtime* runtime);
|
Compiler(runtime::Runtime* runtime);
|
||||||
~Compiler();
|
~Compiler();
|
||||||
|
|
||||||
|
@ -36,7 +38,7 @@ public:
|
||||||
|
|
||||||
int Compile(hir::HIRBuilder* builder);
|
int Compile(hir::HIRBuilder* builder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
runtime::Runtime* runtime_;
|
runtime::Runtime* runtime_;
|
||||||
Arena* scratch_arena_;
|
Arena* scratch_arena_;
|
||||||
|
|
||||||
|
@ -44,9 +46,7 @@ private:
|
||||||
PassList passes_;
|
PassList passes_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_COMPILER_H_
|
#endif // ALLOY_COMPILER_COMPILER_H_
|
||||||
|
|
|
@ -11,16 +11,12 @@
|
||||||
|
|
||||||
#include <alloy/compiler/compiler.h>
|
#include <alloy/compiler/compiler.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::compiler;
|
namespace compiler {
|
||||||
|
|
||||||
|
CompilerPass::CompilerPass() : runtime_(0), compiler_(0) {}
|
||||||
|
|
||||||
CompilerPass::CompilerPass() :
|
CompilerPass::~CompilerPass() {}
|
||||||
runtime_(0), compiler_(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CompilerPass::~CompilerPass() {
|
|
||||||
}
|
|
||||||
|
|
||||||
int CompilerPass::Initialize(Compiler* compiler) {
|
int CompilerPass::Initialize(Compiler* compiler) {
|
||||||
runtime_ = compiler->runtime();
|
runtime_ = compiler->runtime();
|
||||||
|
@ -31,3 +27,6 @@ int CompilerPass::Initialize(Compiler* compiler) {
|
||||||
Arena* CompilerPass::scratch_arena() const {
|
Arena* CompilerPass::scratch_arena() const {
|
||||||
return compiler_->scratch_arena();
|
return compiler_->scratch_arena();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,17 +14,19 @@
|
||||||
|
|
||||||
#include <alloy/hir/hir_builder.h>
|
#include <alloy/hir/hir_builder.h>
|
||||||
|
|
||||||
namespace alloy { namespace runtime { class Runtime; } }
|
namespace alloy {
|
||||||
|
namespace runtime {
|
||||||
|
class Runtime;
|
||||||
|
} // namespace runtime
|
||||||
|
} // namespace alloy
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
class Compiler;
|
class Compiler;
|
||||||
|
|
||||||
|
|
||||||
class CompilerPass {
|
class CompilerPass {
|
||||||
public:
|
public:
|
||||||
CompilerPass();
|
CompilerPass();
|
||||||
virtual ~CompilerPass();
|
virtual ~CompilerPass();
|
||||||
|
|
||||||
|
@ -32,17 +34,15 @@ public:
|
||||||
|
|
||||||
virtual int Run(hir::HIRBuilder* builder) = 0;
|
virtual int Run(hir::HIRBuilder* builder) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Arena* scratch_arena() const;
|
Arena* scratch_arena() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
runtime::Runtime* runtime_;
|
runtime::Runtime* runtime_;
|
||||||
Compiler* compiler_;
|
Compiler* compiler_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_COMPILER_PASS_H_
|
#endif // ALLOY_COMPILER_COMPILER_PASS_H_
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <alloy/compiler/passes/context_promotion_pass.h>
|
#include <alloy/compiler/passes/context_promotion_pass.h>
|
||||||
#include <alloy/compiler/passes/data_flow_analysis_pass.h>
|
#include <alloy/compiler/passes/data_flow_analysis_pass.h>
|
||||||
#include <alloy/compiler/passes/dead_code_elimination_pass.h>
|
#include <alloy/compiler/passes/dead_code_elimination_pass.h>
|
||||||
//#include <alloy/compiler/passes/dead_store_elimination_pass.h>
|
//#include <alloy/compiler/passes/dead_store_elimination_pass.h>
|
||||||
#include <alloy/compiler/passes/finalization_pass.h>
|
#include <alloy/compiler/passes/finalization_pass.h>
|
||||||
#include <alloy/compiler/passes/register_allocation_pass.h>
|
#include <alloy/compiler/passes/register_allocation_pass.h>
|
||||||
#include <alloy/compiler/passes/simplification_pass.h>
|
#include <alloy/compiler/passes/simplification_pass.h>
|
||||||
|
@ -49,7 +49,6 @@
|
||||||
// Block gets:
|
// Block gets:
|
||||||
// AddIncomingValue(Value* value, Block* src_block) ??
|
// AddIncomingValue(Value* value, Block* src_block) ??
|
||||||
|
|
||||||
|
|
||||||
// Potentially interesting passes:
|
// Potentially interesting passes:
|
||||||
//
|
//
|
||||||
// Run order:
|
// Run order:
|
||||||
|
|
|
@ -12,18 +12,20 @@
|
||||||
#include <alloy/runtime/function.h>
|
#include <alloy/runtime/function.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::compiler;
|
namespace compiler {
|
||||||
using namespace alloy::compiler::passes;
|
namespace passes {
|
||||||
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
|
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::hir::TypeName;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
ConstantPropagationPass::ConstantPropagationPass() :
|
ConstantPropagationPass::ConstantPropagationPass() : CompilerPass() {}
|
||||||
CompilerPass() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstantPropagationPass::~ConstantPropagationPass() {
|
ConstantPropagationPass::~ConstantPropagationPass() {}
|
||||||
}
|
|
||||||
|
|
||||||
int ConstantPropagationPass::Run(HIRBuilder* builder) {
|
int ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
@ -55,379 +57,379 @@ int ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
// v1 = 19
|
// v1 = 19
|
||||||
// v2 = 0
|
// v2 = 0
|
||||||
|
|
||||||
Block* block = builder->first_block();
|
auto block = builder->first_block();
|
||||||
while (block) {
|
while (block) {
|
||||||
Instr* i = block->instr_head;
|
auto i = block->instr_head;
|
||||||
while (i) {
|
while (i) {
|
||||||
Value* v = i->dest;
|
auto v = i->dest;
|
||||||
switch (i->opcode->num) {
|
switch (i->opcode->num) {
|
||||||
case OPCODE_DEBUG_BREAK_TRUE:
|
case OPCODE_DEBUG_BREAK_TRUE:
|
||||||
if (i->src1.value->IsConstant()) {
|
if (i->src1.value->IsConstant()) {
|
||||||
if (i->src1.value->IsConstantTrue()) {
|
if (i->src1.value->IsConstantTrue()) {
|
||||||
i->Replace(&OPCODE_DEBUG_BREAK_info, i->flags);
|
i->Replace(&OPCODE_DEBUG_BREAK_info, i->flags);
|
||||||
} else {
|
} else {
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE_TRAP_TRUE:
|
case OPCODE_TRAP_TRUE:
|
||||||
if (i->src1.value->IsConstant()) {
|
if (i->src1.value->IsConstant()) {
|
||||||
if (i->src1.value->IsConstantTrue()) {
|
if (i->src1.value->IsConstantTrue()) {
|
||||||
i->Replace(&OPCODE_TRAP_info, i->flags);
|
i->Replace(&OPCODE_TRAP_info, i->flags);
|
||||||
} else {
|
} else {
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE_CALL_TRUE:
|
case OPCODE_CALL_TRUE:
|
||||||
if (i->src1.value->IsConstant()) {
|
if (i->src1.value->IsConstant()) {
|
||||||
if (i->src1.value->IsConstantTrue()) {
|
if (i->src1.value->IsConstantTrue()) {
|
||||||
auto symbol_info = i->src2.symbol_info;
|
auto symbol_info = i->src2.symbol_info;
|
||||||
|
i->Replace(&OPCODE_CALL_info, i->flags);
|
||||||
|
i->src1.symbol_info = symbol_info;
|
||||||
|
} else {
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_CALL_INDIRECT:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
runtime::FunctionInfo* symbol_info;
|
||||||
|
if (runtime_->LookupFunctionInfo(
|
||||||
|
(uint32_t)i->src1.value->constant.i32, &symbol_info)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
i->Replace(&OPCODE_CALL_info, i->flags);
|
i->Replace(&OPCODE_CALL_info, i->flags);
|
||||||
i->src1.symbol_info = symbol_info;
|
i->src1.symbol_info = symbol_info;
|
||||||
} else {
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_CALL_INDIRECT_TRUE:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
if (i->src1.value->IsConstantTrue()) {
|
||||||
|
auto value = i->src2.value;
|
||||||
|
i->Replace(&OPCODE_CALL_INDIRECT_info, i->flags);
|
||||||
|
i->set_src1(value);
|
||||||
|
} else {
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE_BRANCH_TRUE:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
if (i->src1.value->IsConstantTrue()) {
|
||||||
|
auto label = i->src2.label;
|
||||||
|
i->Replace(&OPCODE_BRANCH_info, i->flags);
|
||||||
|
i->src1.label = label;
|
||||||
|
} else {
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_BRANCH_FALSE:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
if (i->src1.value->IsConstantFalse()) {
|
||||||
|
auto label = i->src2.label;
|
||||||
|
i->Replace(&OPCODE_BRANCH_info, i->flags);
|
||||||
|
i->src1.label = label;
|
||||||
|
} else {
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE_CAST:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
TypeName target_type = v->type;
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->Cast(target_type);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case OPCODE_ZERO_EXTEND:
|
||||||
case OPCODE_CALL_INDIRECT:
|
if (i->src1.value->IsConstant()) {
|
||||||
if (i->src1.value->IsConstant()) {
|
TypeName target_type = v->type;
|
||||||
runtime::FunctionInfo* symbol_info;
|
v->set_from(i->src1.value);
|
||||||
if (runtime_->LookupFunctionInfo(
|
v->ZeroExtend(target_type);
|
||||||
(uint32_t)i->src1.value->constant.i32, &symbol_info)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i->Replace(&OPCODE_CALL_info, i->flags);
|
|
||||||
i->src1.symbol_info = symbol_info;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_CALL_INDIRECT_TRUE:
|
|
||||||
if (i->src1.value->IsConstant()) {
|
|
||||||
if (i->src1.value->IsConstantTrue()) {
|
|
||||||
auto value = i->src2.value;
|
|
||||||
i->Replace(&OPCODE_CALL_INDIRECT_info, i->flags);
|
|
||||||
i->set_src1(value);
|
|
||||||
} else {
|
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case OPCODE_SIGN_EXTEND:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
case OPCODE_BRANCH_TRUE:
|
TypeName target_type = v->type;
|
||||||
if (i->src1.value->IsConstant()) {
|
v->set_from(i->src1.value);
|
||||||
if (i->src1.value->IsConstantTrue()) {
|
v->SignExtend(target_type);
|
||||||
auto label = i->src2.label;
|
|
||||||
i->Replace(&OPCODE_BRANCH_info, i->flags);
|
|
||||||
i->src1.label = label;
|
|
||||||
} else {
|
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case OPCODE_TRUNCATE:
|
||||||
case OPCODE_BRANCH_FALSE:
|
if (i->src1.value->IsConstant()) {
|
||||||
if (i->src1.value->IsConstant()) {
|
TypeName target_type = v->type;
|
||||||
if (i->src1.value->IsConstantFalse()) {
|
v->set_from(i->src1.value);
|
||||||
auto label = i->src2.label;
|
v->Truncate(target_type);
|
||||||
i->Replace(&OPCODE_BRANCH_info, i->flags);
|
|
||||||
i->src1.label = label;
|
|
||||||
} else {
|
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE_CAST:
|
case OPCODE_SELECT:
|
||||||
if (i->src1.value->IsConstant()) {
|
if (i->src1.value->IsConstant()) {
|
||||||
TypeName target_type = v->type;
|
if (i->src1.value->IsConstantTrue()) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src2.value);
|
||||||
v->Cast(target_type);
|
} else {
|
||||||
i->Remove();
|
v->set_from(i->src3.value);
|
||||||
}
|
}
|
||||||
break;
|
i->Remove();
|
||||||
case OPCODE_ZERO_EXTEND:
|
|
||||||
if (i->src1.value->IsConstant()) {
|
|
||||||
TypeName target_type = v->type;
|
|
||||||
v->set_from(i->src1.value);
|
|
||||||
v->ZeroExtend(target_type);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_SIGN_EXTEND:
|
|
||||||
if (i->src1.value->IsConstant()) {
|
|
||||||
TypeName target_type = v->type;
|
|
||||||
v->set_from(i->src1.value);
|
|
||||||
v->SignExtend(target_type);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_TRUNCATE:
|
|
||||||
if (i->src1.value->IsConstant()) {
|
|
||||||
TypeName target_type = v->type;
|
|
||||||
v->set_from(i->src1.value);
|
|
||||||
v->Truncate(target_type);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE_SELECT:
|
|
||||||
if (i->src1.value->IsConstant()) {
|
|
||||||
if (i->src1.value->IsConstantTrue()) {
|
|
||||||
v->set_from(i->src2.value);
|
|
||||||
} else {
|
|
||||||
v->set_from(i->src3.value);
|
|
||||||
}
|
}
|
||||||
i->Remove();
|
break;
|
||||||
}
|
case OPCODE_IS_TRUE:
|
||||||
break;
|
if (i->src1.value->IsConstant()) {
|
||||||
case OPCODE_IS_TRUE:
|
if (i->src1.value->IsConstantTrue()) {
|
||||||
if (i->src1.value->IsConstant()) {
|
v->set_constant((int8_t)1);
|
||||||
if (i->src1.value->IsConstantTrue()) {
|
} else {
|
||||||
v->set_constant((int8_t)1);
|
v->set_constant((int8_t)0);
|
||||||
} else {
|
}
|
||||||
v->set_constant((int8_t)0);
|
i->Remove();
|
||||||
}
|
}
|
||||||
i->Remove();
|
break;
|
||||||
}
|
case OPCODE_IS_FALSE:
|
||||||
break;
|
if (i->src1.value->IsConstant()) {
|
||||||
case OPCODE_IS_FALSE:
|
if (i->src1.value->IsConstantFalse()) {
|
||||||
if (i->src1.value->IsConstant()) {
|
v->set_constant((int8_t)1);
|
||||||
if (i->src1.value->IsConstantFalse()) {
|
} else {
|
||||||
v->set_constant((int8_t)1);
|
v->set_constant((int8_t)0);
|
||||||
} else {
|
}
|
||||||
v->set_constant((int8_t)0);
|
i->Remove();
|
||||||
}
|
}
|
||||||
i->Remove();
|
break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// TODO(benvanik): compares
|
// TODO(benvanik): compares
|
||||||
case OPCODE_COMPARE_EQ:
|
case OPCODE_COMPARE_EQ:
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
bool value = i->src1.value->IsConstantEQ(i->src2.value);
|
bool value = i->src1.value->IsConstantEQ(i->src2.value);
|
||||||
i->dest->set_constant(value);
|
i->dest->set_constant(value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_COMPARE_NE:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
bool value = i->src1.value->IsConstantNE(i->src2.value);
|
|
||||||
i->dest->set_constant(value);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_COMPARE_SLT:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
bool value = i->src1.value->IsConstantSLT(i->src2.value);
|
|
||||||
i->dest->set_constant(value);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_COMPARE_SLE:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
bool value = i->src1.value->IsConstantSLE(i->src2.value);
|
|
||||||
i->dest->set_constant(value);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_COMPARE_SGT:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
bool value = i->src1.value->IsConstantSGT(i->src2.value);
|
|
||||||
i->dest->set_constant(value);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_COMPARE_SGE:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
bool value = i->src1.value->IsConstantSGE(i->src2.value);
|
|
||||||
i->dest->set_constant(value);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_COMPARE_ULT:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
bool value = i->src1.value->IsConstantULT(i->src2.value);
|
|
||||||
i->dest->set_constant(value);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_COMPARE_ULE:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
bool value = i->src1.value->IsConstantULE(i->src2.value);
|
|
||||||
i->dest->set_constant(value);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_COMPARE_UGT:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
bool value = i->src1.value->IsConstantUGT(i->src2.value);
|
|
||||||
i->dest->set_constant(value);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPCODE_COMPARE_UGE:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
bool value = i->src1.value->IsConstantUGE(i->src2.value);
|
|
||||||
i->dest->set_constant(value);
|
|
||||||
i->Remove();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE_DID_CARRY:
|
|
||||||
XEASSERT(!i->src1.value->IsConstant());
|
|
||||||
break;
|
|
||||||
case OPCODE_DID_OVERFLOW:
|
|
||||||
XEASSERT(!i->src1.value->IsConstant());
|
|
||||||
break;
|
|
||||||
case OPCODE_DID_SATURATE:
|
|
||||||
XEASSERT(!i->src1.value->IsConstant());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE_ADD:
|
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
|
||||||
v->set_from(i->src1.value);
|
|
||||||
bool did_carry = v->Add(i->src2.value);
|
|
||||||
bool propagate_carry = !!(i->flags & ARITHMETIC_SET_CARRY);
|
|
||||||
i->Remove();
|
|
||||||
|
|
||||||
// If carry is set find the DID_CARRY and fix it.
|
|
||||||
if (propagate_carry) {
|
|
||||||
PropagateCarry(v, did_carry);
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case OPCODE_COMPARE_NE:
|
||||||
// TODO(benvanik): ADD_CARRY (w/ ARITHMETIC_SET_CARRY)
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
case OPCODE_SUB:
|
bool value = i->src1.value->IsConstantNE(i->src2.value);
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
i->dest->set_constant(value);
|
||||||
v->set_from(i->src1.value);
|
i->Remove();
|
||||||
bool did_carry = v->Sub(i->src2.value);
|
|
||||||
bool propagate_carry = !!(i->flags & ARITHMETIC_SET_CARRY);
|
|
||||||
i->Remove();
|
|
||||||
|
|
||||||
// If carry is set find the DID_CARRY and fix it.
|
|
||||||
if (propagate_carry) {
|
|
||||||
PropagateCarry(v, did_carry);
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case OPCODE_COMPARE_SLT:
|
||||||
case OPCODE_MUL:
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
bool value = i->src1.value->IsConstantSLT(i->src2.value);
|
||||||
v->set_from(i->src1.value);
|
i->dest->set_constant(value);
|
||||||
v->Mul(i->src2.value);
|
i->Remove();
|
||||||
i->Remove();
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case OPCODE_COMPARE_SLE:
|
||||||
case OPCODE_DIV:
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
bool value = i->src1.value->IsConstantSLE(i->src2.value);
|
||||||
v->set_from(i->src1.value);
|
i->dest->set_constant(value);
|
||||||
v->Div(i->src2.value);
|
i->Remove();
|
||||||
i->Remove();
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case OPCODE_COMPARE_SGT:
|
||||||
// case OPCODE_MUL_ADD:
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
// case OPCODE_MUL_SUB
|
bool value = i->src1.value->IsConstantSGT(i->src2.value);
|
||||||
case OPCODE_NEG:
|
i->dest->set_constant(value);
|
||||||
if (i->src1.value->IsConstant()) {
|
i->Remove();
|
||||||
v->set_from(i->src1.value);
|
}
|
||||||
v->Neg();
|
break;
|
||||||
i->Remove();
|
case OPCODE_COMPARE_SGE:
|
||||||
}
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
break;
|
bool value = i->src1.value->IsConstantSGE(i->src2.value);
|
||||||
case OPCODE_ABS:
|
i->dest->set_constant(value);
|
||||||
if (i->src1.value->IsConstant()) {
|
i->Remove();
|
||||||
v->set_from(i->src1.value);
|
}
|
||||||
v->Abs();
|
break;
|
||||||
i->Remove();
|
case OPCODE_COMPARE_ULT:
|
||||||
}
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
break;
|
bool value = i->src1.value->IsConstantULT(i->src2.value);
|
||||||
case OPCODE_SQRT:
|
i->dest->set_constant(value);
|
||||||
if (i->src1.value->IsConstant()) {
|
i->Remove();
|
||||||
v->set_from(i->src1.value);
|
}
|
||||||
v->Sqrt();
|
break;
|
||||||
i->Remove();
|
case OPCODE_COMPARE_ULE:
|
||||||
}
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
break;
|
bool value = i->src1.value->IsConstantULE(i->src2.value);
|
||||||
case OPCODE_RSQRT:
|
i->dest->set_constant(value);
|
||||||
if (i->src1.value->IsConstant()) {
|
i->Remove();
|
||||||
v->set_from(i->src1.value);
|
}
|
||||||
v->RSqrt();
|
break;
|
||||||
i->Remove();
|
case OPCODE_COMPARE_UGT:
|
||||||
}
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
break;
|
bool value = i->src1.value->IsConstantUGT(i->src2.value);
|
||||||
|
i->dest->set_constant(value);
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_COMPARE_UGE:
|
||||||
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
|
bool value = i->src1.value->IsConstantUGE(i->src2.value);
|
||||||
|
i->dest->set_constant(value);
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case OPCODE_AND:
|
case OPCODE_DID_CARRY:
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
XEASSERT(!i->src1.value->IsConstant());
|
||||||
v->set_from(i->src1.value);
|
break;
|
||||||
v->And(i->src2.value);
|
case OPCODE_DID_OVERFLOW:
|
||||||
i->Remove();
|
XEASSERT(!i->src1.value->IsConstant());
|
||||||
}
|
break;
|
||||||
break;
|
case OPCODE_DID_SATURATE:
|
||||||
case OPCODE_OR:
|
XEASSERT(!i->src1.value->IsConstant());
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
break;
|
||||||
v->set_from(i->src1.value);
|
|
||||||
v->Or(i->src2.value);
|
case OPCODE_ADD:
|
||||||
i->Remove();
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
}
|
v->set_from(i->src1.value);
|
||||||
break;
|
bool did_carry = v->Add(i->src2.value);
|
||||||
case OPCODE_XOR:
|
bool propagate_carry = !!(i->flags & ARITHMETIC_SET_CARRY);
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
i->Remove();
|
||||||
v->set_from(i->src1.value);
|
|
||||||
v->Xor(i->src2.value);
|
// If carry is set find the DID_CARRY and fix it.
|
||||||
i->Remove();
|
if (propagate_carry) {
|
||||||
}
|
PropagateCarry(v, did_carry);
|
||||||
break;
|
}
|
||||||
case OPCODE_NOT:
|
}
|
||||||
if (i->src1.value->IsConstant()) {
|
break;
|
||||||
v->set_from(i->src1.value);
|
// TODO(benvanik): ADD_CARRY (w/ ARITHMETIC_SET_CARRY)
|
||||||
v->Not();
|
case OPCODE_SUB:
|
||||||
i->Remove();
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
}
|
v->set_from(i->src1.value);
|
||||||
break;
|
bool did_carry = v->Sub(i->src2.value);
|
||||||
case OPCODE_SHL:
|
bool propagate_carry = !!(i->flags & ARITHMETIC_SET_CARRY);
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
i->Remove();
|
||||||
v->set_from(i->src1.value);
|
|
||||||
v->Shl(i->src2.value);
|
// If carry is set find the DID_CARRY and fix it.
|
||||||
i->Remove();
|
if (propagate_carry) {
|
||||||
}
|
PropagateCarry(v, did_carry);
|
||||||
break;
|
}
|
||||||
// TODO(benvanik): VECTOR_SHL
|
}
|
||||||
case OPCODE_SHR:
|
break;
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
case OPCODE_MUL:
|
||||||
v->set_from(i->src1.value);
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
v->Shr(i->src2.value);
|
v->set_from(i->src1.value);
|
||||||
i->Remove();
|
v->Mul(i->src2.value);
|
||||||
}
|
i->Remove();
|
||||||
break;
|
}
|
||||||
case OPCODE_SHA:
|
break;
|
||||||
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
case OPCODE_DIV:
|
||||||
v->set_from(i->src1.value);
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
v->Sha(i->src2.value);
|
v->set_from(i->src1.value);
|
||||||
i->Remove();
|
v->Div(i->src2.value);
|
||||||
}
|
i->Remove();
|
||||||
break;
|
}
|
||||||
// TODO(benvanik): ROTATE_LEFT
|
break;
|
||||||
case OPCODE_BYTE_SWAP:
|
// case OPCODE_MUL_ADD:
|
||||||
if (i->src1.value->IsConstant()) {
|
// case OPCODE_MUL_SUB
|
||||||
v->set_from(i->src1.value);
|
case OPCODE_NEG:
|
||||||
v->ByteSwap();
|
if (i->src1.value->IsConstant()) {
|
||||||
i->Remove();
|
v->set_from(i->src1.value);
|
||||||
}
|
v->Neg();
|
||||||
break;
|
i->Remove();
|
||||||
case OPCODE_CNTLZ:
|
}
|
||||||
if (i->src1.value->IsConstant()) {
|
break;
|
||||||
v->set_zero(v->type);
|
case OPCODE_ABS:
|
||||||
v->CountLeadingZeros(i->src1.value);
|
if (i->src1.value->IsConstant()) {
|
||||||
i->Remove();
|
v->set_from(i->src1.value);
|
||||||
}
|
v->Abs();
|
||||||
break;
|
i->Remove();
|
||||||
// TODO(benvanik): INSERT/EXTRACT
|
}
|
||||||
// TODO(benvanik): SPLAT/PERMUTE/SWIZZLE
|
break;
|
||||||
case OPCODE_SPLAT:
|
case OPCODE_SQRT:
|
||||||
if (i->src1.value->IsConstant()) {
|
if (i->src1.value->IsConstant()) {
|
||||||
// Quite a few of these, from building vec128s.
|
v->set_from(i->src1.value);
|
||||||
}
|
v->Sqrt();
|
||||||
break;
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_RSQRT:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->RSqrt();
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE_AND:
|
||||||
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->And(i->src2.value);
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_OR:
|
||||||
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->Or(i->src2.value);
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_XOR:
|
||||||
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->Xor(i->src2.value);
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_NOT:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->Not();
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_SHL:
|
||||||
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->Shl(i->src2.value);
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// TODO(benvanik): VECTOR_SHL
|
||||||
|
case OPCODE_SHR:
|
||||||
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->Shr(i->src2.value);
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_SHA:
|
||||||
|
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->Sha(i->src2.value);
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// TODO(benvanik): ROTATE_LEFT
|
||||||
|
case OPCODE_BYTE_SWAP:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
v->set_from(i->src1.value);
|
||||||
|
v->ByteSwap();
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_CNTLZ:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
v->set_zero(v->type);
|
||||||
|
v->CountLeadingZeros(i->src1.value);
|
||||||
|
i->Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// TODO(benvanik): INSERT/EXTRACT
|
||||||
|
// TODO(benvanik): SPLAT/PERMUTE/SWIZZLE
|
||||||
|
case OPCODE_SPLAT:
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
// Quite a few of these, from building vec128s.
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
i = i->next;
|
i = i->next;
|
||||||
}
|
}
|
||||||
|
@ -438,7 +440,7 @@ int ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPropagationPass::PropagateCarry(hir::Value* v, bool did_carry) {
|
void ConstantPropagationPass::PropagateCarry(Value* v, bool did_carry) {
|
||||||
auto next = v->use_head;
|
auto next = v->use_head;
|
||||||
while (next) {
|
while (next) {
|
||||||
auto use = next;
|
auto use = next;
|
||||||
|
@ -450,3 +452,7 @@ void ConstantPropagationPass::PropagateCarry(hir::Value* v, bool did_carry) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -12,27 +12,23 @@
|
||||||
|
|
||||||
#include <alloy/compiler/compiler_pass.h>
|
#include <alloy/compiler/compiler_pass.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
|
|
||||||
class ConstantPropagationPass : public CompilerPass {
|
class ConstantPropagationPass : public CompilerPass {
|
||||||
public:
|
public:
|
||||||
ConstantPropagationPass();
|
ConstantPropagationPass();
|
||||||
virtual ~ConstantPropagationPass();
|
virtual ~ConstantPropagationPass();
|
||||||
|
|
||||||
virtual int Run(hir::HIRBuilder* builder);
|
virtual int Run(hir::HIRBuilder* builder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PropagateCarry(hir::Value* v, bool did_carry);
|
void PropagateCarry(hir::Value* v, bool did_carry);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace passes
|
} // namespace passes
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
#endif // ALLOY_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||||
|
|
|
@ -14,22 +14,24 @@
|
||||||
#include <alloy/compiler/compiler.h>
|
#include <alloy/compiler/compiler.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
|
||||||
using namespace alloy::compiler;
|
|
||||||
using namespace alloy::compiler::passes;
|
|
||||||
using namespace alloy::frontend;
|
|
||||||
using namespace alloy::hir;
|
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_bool(store_all_context_values, false,
|
DEFINE_bool(store_all_context_values, false,
|
||||||
"Don't strip dead context stores to aid in debugging.");
|
"Don't strip dead context stores to aid in debugging.");
|
||||||
|
|
||||||
|
namespace alloy {
|
||||||
|
namespace compiler {
|
||||||
|
namespace passes {
|
||||||
|
|
||||||
ContextPromotionPass::ContextPromotionPass() :
|
// TODO(benvanik): remove when enums redefined.
|
||||||
context_values_size_(0), context_values_(0),
|
using namespace alloy::hir;
|
||||||
CompilerPass() {
|
|
||||||
}
|
using alloy::frontend::ContextInfo;
|
||||||
|
using alloy::hir::Block;
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::hir::Instr;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
|
ContextPromotionPass::ContextPromotionPass()
|
||||||
|
: context_values_size_(0), context_values_(0), CompilerPass() {}
|
||||||
|
|
||||||
ContextPromotionPass::~ContextPromotionPass() {
|
ContextPromotionPass::~ContextPromotionPass() {
|
||||||
if (context_values_) {
|
if (context_values_) {
|
||||||
|
@ -70,7 +72,7 @@ int ContextPromotionPass::Run(HIRBuilder* builder) {
|
||||||
|
|
||||||
// Promote loads to values.
|
// Promote loads to values.
|
||||||
// Process each block independently, for now.
|
// Process each block independently, for now.
|
||||||
Block* block = builder->first_block();
|
auto block = builder->first_block();
|
||||||
while (block) {
|
while (block) {
|
||||||
PromoteBlock(block);
|
PromoteBlock(block);
|
||||||
block = block->next;
|
block = block->next;
|
||||||
|
@ -121,7 +123,7 @@ void ContextPromotionPass::PromoteBlock(Block* block) {
|
||||||
void ContextPromotionPass::RemoveDeadStoresBlock(Block* block) {
|
void ContextPromotionPass::RemoveDeadStoresBlock(Block* block) {
|
||||||
// TODO(benvanik): use a bitvector.
|
// TODO(benvanik): use a bitvector.
|
||||||
// To avoid clearing the structure, we use a token.
|
// To avoid clearing the structure, we use a token.
|
||||||
Value* token = (Value*)block;
|
auto token = (Value*)block;
|
||||||
|
|
||||||
// Walk backwards and mark offsets that are written to.
|
// Walk backwards and mark offsets that are written to.
|
||||||
// If the offset was written to earlier, ignore the store.
|
// If the offset was written to earlier, ignore the store.
|
||||||
|
@ -141,3 +143,7 @@ void ContextPromotionPass::RemoveDeadStoresBlock(Block* block) {
|
||||||
i = prev;
|
i = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -12,14 +12,12 @@
|
||||||
|
|
||||||
#include <alloy/compiler/compiler_pass.h>
|
#include <alloy/compiler/compiler_pass.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
|
|
||||||
class ContextPromotionPass : public CompilerPass {
|
class ContextPromotionPass : public CompilerPass {
|
||||||
public:
|
public:
|
||||||
ContextPromotionPass();
|
ContextPromotionPass();
|
||||||
virtual ~ContextPromotionPass();
|
virtual ~ContextPromotionPass();
|
||||||
|
|
||||||
|
@ -27,19 +25,17 @@ public:
|
||||||
|
|
||||||
virtual int Run(hir::HIRBuilder* builder);
|
virtual int Run(hir::HIRBuilder* builder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PromoteBlock(hir::Block* block);
|
void PromoteBlock(hir::Block* block);
|
||||||
void RemoveDeadStoresBlock(hir::Block* block);
|
void RemoveDeadStoresBlock(hir::Block* block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t context_values_size_;
|
size_t context_values_size_;
|
||||||
hir::Value** context_values_;
|
hir::Value** context_values_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace passes
|
} // namespace passes
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
#endif // ALLOY_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||||
|
|
|
@ -13,21 +13,19 @@
|
||||||
#include <alloy/compiler/compiler.h>
|
#include <alloy/compiler/compiler.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace compiler {
|
||||||
using namespace alloy::compiler;
|
namespace passes {
|
||||||
using namespace alloy::compiler::passes;
|
|
||||||
using namespace alloy::frontend;
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::hir::Edge;
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
|
||||||
ControlFlowAnalysisPass::ControlFlowAnalysisPass() :
|
ControlFlowAnalysisPass::ControlFlowAnalysisPass() : CompilerPass() {}
|
||||||
CompilerPass() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ControlFlowAnalysisPass::~ControlFlowAnalysisPass() {
|
ControlFlowAnalysisPass::~ControlFlowAnalysisPass() {}
|
||||||
}
|
|
||||||
|
|
||||||
int ControlFlowAnalysisPass::Run(HIRBuilder* builder) {
|
int ControlFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
@ -46,7 +44,7 @@ int ControlFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||||
auto label = instr->src1.label;
|
auto label = instr->src1.label;
|
||||||
builder->AddEdge(block, label->block, Edge::UNCONDITIONAL);
|
builder->AddEdge(block, label->block, Edge::UNCONDITIONAL);
|
||||||
} else if (instr->opcode == &OPCODE_BRANCH_TRUE_info ||
|
} else if (instr->opcode == &OPCODE_BRANCH_TRUE_info ||
|
||||||
instr->opcode == &OPCODE_BRANCH_FALSE_info) {
|
instr->opcode == &OPCODE_BRANCH_FALSE_info) {
|
||||||
auto label = instr->src2.label;
|
auto label = instr->src2.label;
|
||||||
builder->AddEdge(block, label->block, 0);
|
builder->AddEdge(block, label->block, 0);
|
||||||
}
|
}
|
||||||
|
@ -67,3 +65,7 @@ int ControlFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -12,26 +12,22 @@
|
||||||
|
|
||||||
#include <alloy/compiler/compiler_pass.h>
|
#include <alloy/compiler/compiler_pass.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
|
|
||||||
class ControlFlowAnalysisPass : public CompilerPass {
|
class ControlFlowAnalysisPass : public CompilerPass {
|
||||||
public:
|
public:
|
||||||
ControlFlowAnalysisPass();
|
ControlFlowAnalysisPass();
|
||||||
virtual ~ControlFlowAnalysisPass();
|
virtual ~ControlFlowAnalysisPass();
|
||||||
|
|
||||||
virtual int Run(hir::HIRBuilder* builder);
|
virtual int Run(hir::HIRBuilder* builder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace passes
|
} // namespace passes
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
#endif // ALLOY_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
||||||
|
|
|
@ -19,21 +19,20 @@
|
||||||
#include <llvm/ADT/BitVector.h>
|
#include <llvm/ADT/BitVector.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace compiler {
|
||||||
using namespace alloy::compiler;
|
namespace passes {
|
||||||
using namespace alloy::compiler::passes;
|
|
||||||
using namespace alloy::frontend;
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::hir::OpcodeSignatureType;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
DataFlowAnalysisPass::DataFlowAnalysisPass() :
|
DataFlowAnalysisPass::DataFlowAnalysisPass() : CompilerPass() {}
|
||||||
CompilerPass() {
|
|
||||||
}
|
|
||||||
|
|
||||||
DataFlowAnalysisPass::~DataFlowAnalysisPass() {
|
DataFlowAnalysisPass::~DataFlowAnalysisPass() {}
|
||||||
}
|
|
||||||
|
|
||||||
int DataFlowAnalysisPass::Run(HIRBuilder* builder) {
|
int DataFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
@ -66,15 +65,15 @@ void DataFlowAnalysisPass::AnalyzeFlow(HIRBuilder* builder,
|
||||||
|
|
||||||
// Stash for value map. We may want to maintain this during building.
|
// Stash for value map. We may want to maintain this during building.
|
||||||
auto arena = builder->arena();
|
auto arena = builder->arena();
|
||||||
Value** value_map = (Value**)arena->Alloc(
|
Value** value_map =
|
||||||
sizeof(Value*) * max_value_estimate);
|
(Value**)arena->Alloc(sizeof(Value*) * max_value_estimate);
|
||||||
|
|
||||||
// Allocate incoming bitvectors for use by blocks. We don't need outgoing
|
// Allocate incoming bitvectors for use by blocks. We don't need outgoing
|
||||||
// because they are only used during the block iteration.
|
// because they are only used during the block iteration.
|
||||||
// Mapped by block ordinal.
|
// Mapped by block ordinal.
|
||||||
// TODO(benvanik): cache this list, grow as needed, etc.
|
// TODO(benvanik): cache this list, grow as needed, etc.
|
||||||
auto incoming_bitvectors = (llvm::BitVector**)arena->Alloc(
|
auto incoming_bitvectors =
|
||||||
sizeof(llvm::BitVector*) * block_count);
|
(llvm::BitVector**)arena->Alloc(sizeof(llvm::BitVector*) * block_count);
|
||||||
for (auto n = 0u; n < block_count; n++) {
|
for (auto n = 0u; n < block_count; n++) {
|
||||||
incoming_bitvectors[n] = new llvm::BitVector(max_value_estimate);
|
incoming_bitvectors[n] = new llvm::BitVector(max_value_estimate);
|
||||||
}
|
}
|
||||||
|
@ -90,10 +89,10 @@ void DataFlowAnalysisPass::AnalyzeFlow(HIRBuilder* builder,
|
||||||
auto instr = block->instr_head;
|
auto instr = block->instr_head;
|
||||||
while (instr) {
|
while (instr) {
|
||||||
uint32_t signature = instr->opcode->signature;
|
uint32_t signature = instr->opcode->signature;
|
||||||
#define SET_INCOMING_VALUE(v) \
|
#define SET_INCOMING_VALUE(v) \
|
||||||
if (v->def && v->def->block != block) { \
|
if (v->def && v->def->block != block) { \
|
||||||
incoming_values.set(v->ordinal); \
|
incoming_values.set(v->ordinal); \
|
||||||
} \
|
} \
|
||||||
XEASSERT(v->ordinal < max_value_estimate); \
|
XEASSERT(v->ordinal < max_value_estimate); \
|
||||||
value_map[v->ordinal] = v;
|
value_map[v->ordinal] = v;
|
||||||
if (GET_OPCODE_SIG_TYPE_SRC1(signature) == OPCODE_SIG_TYPE_V) {
|
if (GET_OPCODE_SIG_TYPE_SRC1(signature) == OPCODE_SIG_TYPE_V) {
|
||||||
|
@ -201,3 +200,7 @@ void DataFlowAnalysisPass::AnalyzeFlow(HIRBuilder* builder,
|
||||||
delete incoming_bitvectors[n];
|
delete incoming_bitvectors[n];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -9,18 +9,20 @@
|
||||||
|
|
||||||
#include <alloy/compiler/passes/dead_code_elimination_pass.h>
|
#include <alloy/compiler/passes/dead_code_elimination_pass.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::compiler;
|
namespace compiler {
|
||||||
using namespace alloy::compiler::passes;
|
namespace passes {
|
||||||
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
|
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::hir::Instr;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
DeadCodeEliminationPass::DeadCodeEliminationPass() :
|
DeadCodeEliminationPass::DeadCodeEliminationPass() : CompilerPass() {}
|
||||||
CompilerPass() {
|
|
||||||
}
|
|
||||||
|
|
||||||
DeadCodeEliminationPass::~DeadCodeEliminationPass() {
|
DeadCodeEliminationPass::~DeadCodeEliminationPass() {}
|
||||||
}
|
|
||||||
|
|
||||||
int DeadCodeEliminationPass::Run(HIRBuilder* builder) {
|
int DeadCodeEliminationPass::Run(HIRBuilder* builder) {
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
@ -63,7 +65,7 @@ int DeadCodeEliminationPass::Run(HIRBuilder* builder) {
|
||||||
|
|
||||||
bool any_instr_removed = false;
|
bool any_instr_removed = false;
|
||||||
bool any_locals_removed = false;
|
bool any_locals_removed = false;
|
||||||
Block* block = builder->first_block();
|
auto block = builder->first_block();
|
||||||
while (block) {
|
while (block) {
|
||||||
// Walk instructions in reverse.
|
// Walk instructions in reverse.
|
||||||
Instr* i = block->instr_tail;
|
Instr* i = block->instr_tail;
|
||||||
|
@ -71,8 +73,8 @@ int DeadCodeEliminationPass::Run(HIRBuilder* builder) {
|
||||||
auto prev = i->prev;
|
auto prev = i->prev;
|
||||||
|
|
||||||
auto opcode = i->opcode;
|
auto opcode = i->opcode;
|
||||||
if (!(opcode->flags & OPCODE_FLAG_VOLATILE) &&
|
if (!(opcode->flags & OPCODE_FLAG_VOLATILE) && i->dest &&
|
||||||
i->dest && !i->dest->use_head) {
|
!i->dest->use_head) {
|
||||||
// Has no uses and is not volatile. This instruction can die!
|
// Has no uses and is not volatile. This instruction can die!
|
||||||
MakeNopRecursive(i);
|
MakeNopRecursive(i);
|
||||||
any_instr_removed = true;
|
any_instr_removed = true;
|
||||||
|
@ -110,7 +112,7 @@ int DeadCodeEliminationPass::Run(HIRBuilder* builder) {
|
||||||
|
|
||||||
// Remove all nops.
|
// Remove all nops.
|
||||||
if (any_instr_removed) {
|
if (any_instr_removed) {
|
||||||
Block* block = builder->first_block();
|
auto block = builder->first_block();
|
||||||
while (block) {
|
while (block) {
|
||||||
Instr* i = block->instr_head;
|
Instr* i = block->instr_head;
|
||||||
while (i) {
|
while (i) {
|
||||||
|
@ -148,19 +150,19 @@ void DeadCodeEliminationPass::MakeNopRecursive(Instr* i) {
|
||||||
i->dest->def = NULL;
|
i->dest->def = NULL;
|
||||||
i->dest = NULL;
|
i->dest = NULL;
|
||||||
|
|
||||||
#define MAKE_NOP_SRC(n) \
|
#define MAKE_NOP_SRC(n) \
|
||||||
if (i->src##n##_use) { \
|
if (i->src##n##_use) { \
|
||||||
Value::Use* use = i->src##n##_use; \
|
Value::Use* use = i->src##n##_use; \
|
||||||
Value* value = i->src##n##.value; \
|
Value* value = i->src##n##.value; \
|
||||||
i->src##n##_use = NULL; \
|
i->src##n##_use = NULL; \
|
||||||
i->src##n##.value = NULL; \
|
i->src##n##.value = NULL; \
|
||||||
value->RemoveUse(use); \
|
value->RemoveUse(use); \
|
||||||
if (!value->use_head) { \
|
if (!value->use_head) { \
|
||||||
/* Value is now unused, so recursively kill it. */ \
|
/* Value is now unused, so recursively kill it. */ \
|
||||||
if (value->def && value->def != i) { \
|
if (value->def && value->def != i) { \
|
||||||
MakeNopRecursive(value->def); \
|
MakeNopRecursive(value->def); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
MAKE_NOP_SRC(1);
|
MAKE_NOP_SRC(1);
|
||||||
MAKE_NOP_SRC(2);
|
MAKE_NOP_SRC(2);
|
||||||
|
@ -209,3 +211,7 @@ bool DeadCodeEliminationPass::CheckLocalUse(Instr* i) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -13,21 +13,18 @@
|
||||||
#include <alloy/compiler/compiler.h>
|
#include <alloy/compiler/compiler.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace compiler {
|
||||||
using namespace alloy::compiler;
|
namespace passes {
|
||||||
using namespace alloy::compiler::passes;
|
|
||||||
using namespace alloy::frontend;
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
|
||||||
FinalizationPass::FinalizationPass() :
|
FinalizationPass::FinalizationPass() : CompilerPass() {}
|
||||||
CompilerPass() {
|
|
||||||
}
|
|
||||||
|
|
||||||
FinalizationPass::~FinalizationPass() {
|
FinalizationPass::~FinalizationPass() {}
|
||||||
}
|
|
||||||
|
|
||||||
int FinalizationPass::Run(HIRBuilder* builder) {
|
int FinalizationPass::Run(HIRBuilder* builder) {
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
@ -70,3 +67,7 @@ int FinalizationPass::Run(HIRBuilder* builder) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -12,26 +12,22 @@
|
||||||
|
|
||||||
#include <alloy/compiler/compiler_pass.h>
|
#include <alloy/compiler/compiler_pass.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
|
|
||||||
class FinalizationPass : public CompilerPass {
|
class FinalizationPass : public CompilerPass {
|
||||||
public:
|
public:
|
||||||
FinalizationPass();
|
FinalizationPass();
|
||||||
virtual ~FinalizationPass();
|
virtual ~FinalizationPass();
|
||||||
|
|
||||||
virtual int Run(hir::HIRBuilder* builder);
|
virtual int Run(hir::HIRBuilder* builder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace passes
|
} // namespace passes
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_PASSES_FINALIZATION_PASS_H_
|
#endif // ALLOY_COMPILER_PASSES_FINALIZATION_PASS_H_
|
||||||
|
|
|
@ -11,20 +11,25 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace compiler {
|
||||||
using namespace alloy::compiler;
|
namespace passes {
|
||||||
using namespace alloy::compiler::passes;
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
|
|
||||||
|
using alloy::backend::MachineInfo;
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::hir::Instr;
|
||||||
|
using alloy::hir::OpcodeSignatureType;
|
||||||
|
using alloy::hir::RegAssignment;
|
||||||
|
using alloy::hir::TypeName;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
#define ASSERT_NO_CYCLES 0
|
#define ASSERT_NO_CYCLES 0
|
||||||
|
|
||||||
|
RegisterAllocationPass::RegisterAllocationPass(const MachineInfo* machine_info)
|
||||||
RegisterAllocationPass::RegisterAllocationPass(
|
: machine_info_(machine_info), CompilerPass() {
|
||||||
const MachineInfo* machine_info) :
|
|
||||||
machine_info_(machine_info),
|
|
||||||
CompilerPass() {
|
|
||||||
// Initialize register sets.
|
// Initialize register sets.
|
||||||
// TODO(benvanik): rewrite in a way that makes sense - this is terrible.
|
// TODO(benvanik): rewrite in a way that makes sense - this is terrible.
|
||||||
auto mi_sets = machine_info->register_sets;
|
auto mi_sets = machine_info->register_sets;
|
||||||
|
@ -88,7 +93,7 @@ int RegisterAllocationPass::Run(HIRBuilder* builder) {
|
||||||
|
|
||||||
instr = block->instr_head;
|
instr = block->instr_head;
|
||||||
while (instr) {
|
while (instr) {
|
||||||
const OpcodeInfo* info = instr->opcode;
|
const auto info = instr->opcode;
|
||||||
uint32_t signature = info->signature;
|
uint32_t signature = info->signature;
|
||||||
|
|
||||||
// Update the register use heaps.
|
// Update the register use heaps.
|
||||||
|
@ -101,7 +106,7 @@ int RegisterAllocationPass::Run(HIRBuilder* builder) {
|
||||||
// reuse it.
|
// reuse it.
|
||||||
// NOTE: these checks require that the usage list be sorted!
|
// NOTE: these checks require that the usage list be sorted!
|
||||||
bool has_preferred_reg = false;
|
bool has_preferred_reg = false;
|
||||||
RegAssignment preferred_reg = { 0 };
|
RegAssignment preferred_reg = {0};
|
||||||
if (GET_OPCODE_SIG_TYPE_SRC1(signature) == OPCODE_SIG_TYPE_V &&
|
if (GET_OPCODE_SIG_TYPE_SRC1(signature) == OPCODE_SIG_TYPE_V &&
|
||||||
!instr->src1.value->IsConstant()) {
|
!instr->src1.value->IsConstant()) {
|
||||||
if (!instr->src1_use->next) {
|
if (!instr->src1_use->next) {
|
||||||
|
@ -117,7 +122,8 @@ int RegisterAllocationPass::Run(HIRBuilder* builder) {
|
||||||
// Must not have been set already.
|
// Must not have been set already.
|
||||||
XEASSERTNULL(instr->dest->reg.set);
|
XEASSERTNULL(instr->dest->reg.set);
|
||||||
|
|
||||||
// Sort the usage list. We depend on this in future uses of this variable.
|
// Sort the usage list. We depend on this in future uses of this
|
||||||
|
// variable.
|
||||||
SortUsageList(instr->dest);
|
SortUsageList(instr->dest);
|
||||||
|
|
||||||
// If we have a preferred register, use that.
|
// If we have a preferred register, use that.
|
||||||
|
@ -181,7 +187,6 @@ void RegisterAllocationPass::DumpUsage(const char* name) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegisterAllocationPass::PrepareBlockState() {
|
void RegisterAllocationPass::PrepareBlockState() {
|
||||||
for (size_t i = 0; i < XECOUNT(usage_sets_.all_sets); ++i) {
|
for (size_t i = 0; i < XECOUNT(usage_sets_.all_sets); ++i) {
|
||||||
auto usage_set = usage_sets_.all_sets[i];
|
auto usage_set = usage_sets_.all_sets[i];
|
||||||
|
@ -249,9 +254,8 @@ bool RegisterAllocationPass::IsRegInUse(const RegAssignment& reg) {
|
||||||
return !usage_set->availability.test(reg.index);
|
return !usage_set->availability.test(reg.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterAllocationPass::RegisterSetUsage*
|
RegisterAllocationPass::RegisterSetUsage* RegisterAllocationPass::MarkRegUsed(
|
||||||
RegisterAllocationPass::MarkRegUsed(const RegAssignment& reg,
|
const RegAssignment& reg, Value* value, Value::Use* use) {
|
||||||
Value* value, Value::Use* use) {
|
|
||||||
auto usage_set = RegisterSetForValue(value);
|
auto usage_set = RegisterSetForValue(value);
|
||||||
usage_set->availability.set(reg.index, false);
|
usage_set->availability.set(reg.index, false);
|
||||||
usage_set->upcoming_uses.emplace_back(value, use);
|
usage_set->upcoming_uses.emplace_back(value, use);
|
||||||
|
@ -298,7 +302,8 @@ bool RegisterAllocationPass::TryAllocateRegister(Value* value) {
|
||||||
// Find the first free register, if any.
|
// Find the first free register, if any.
|
||||||
// We have to ensure it's a valid one (in our count).
|
// We have to ensure it's a valid one (in our count).
|
||||||
unsigned long first_unused = 0;
|
unsigned long first_unused = 0;
|
||||||
bool all_used = _BitScanForward(&first_unused, usage_set->availability.to_ulong()) == 0;
|
bool all_used =
|
||||||
|
_BitScanForward(&first_unused, usage_set->availability.to_ulong()) == 0;
|
||||||
if (!all_used && first_unused < usage_set->count) {
|
if (!all_used && first_unused < usage_set->count) {
|
||||||
// Available! Use it!.
|
// Available! Use it!.
|
||||||
value->reg.set = usage_set->set;
|
value->reg.set = usage_set->set;
|
||||||
|
@ -311,8 +316,8 @@ bool RegisterAllocationPass::TryAllocateRegister(Value* value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RegisterAllocationPass::SpillOneRegister(
|
bool RegisterAllocationPass::SpillOneRegister(HIRBuilder* builder,
|
||||||
HIRBuilder* builder, TypeName required_type) {
|
TypeName required_type) {
|
||||||
// Get the set that we will be picking from.
|
// Get the set that we will be picking from.
|
||||||
RegisterSetUsage* usage_set;
|
RegisterSetUsage* usage_set;
|
||||||
if (required_type <= INT64_TYPE) {
|
if (required_type <= INT64_TYPE) {
|
||||||
|
@ -326,17 +331,17 @@ bool RegisterAllocationPass::SpillOneRegister(
|
||||||
DumpUsage("SpillOneRegister (pre)");
|
DumpUsage("SpillOneRegister (pre)");
|
||||||
// Pick the one with the furthest next use.
|
// Pick the one with the furthest next use.
|
||||||
XEASSERT(!usage_set->upcoming_uses.empty());
|
XEASSERT(!usage_set->upcoming_uses.empty());
|
||||||
auto furthest_usage = std::max_element(
|
auto furthest_usage = std::max_element(usage_set->upcoming_uses.begin(),
|
||||||
usage_set->upcoming_uses.begin(), usage_set->upcoming_uses.end(),
|
usage_set->upcoming_uses.end(),
|
||||||
RegisterUsage::Comparer());
|
RegisterUsage::Comparer());
|
||||||
Value* spill_value = furthest_usage->value;
|
auto spill_value = furthest_usage->value;
|
||||||
Value::Use* prev_use = furthest_usage->use->prev;
|
Value::Use* prev_use = furthest_usage->use->prev;
|
||||||
Value::Use* next_use = furthest_usage->use;
|
Value::Use* next_use = furthest_usage->use;
|
||||||
XEASSERTNOTNULL(next_use);
|
XEASSERTNOTNULL(next_use);
|
||||||
usage_set->upcoming_uses.erase(furthest_usage);
|
usage_set->upcoming_uses.erase(furthest_usage);
|
||||||
DumpUsage("SpillOneRegister (post)");
|
DumpUsage("SpillOneRegister (post)");
|
||||||
const auto reg = spill_value->reg;
|
const auto reg = spill_value->reg;
|
||||||
|
|
||||||
// We know the spill_value use list is sorted, so we can cut it right now.
|
// We know the spill_value use list is sorted, so we can cut it right now.
|
||||||
// This makes it easier down below.
|
// This makes it easier down below.
|
||||||
auto new_head_use = next_use;
|
auto new_head_use = next_use;
|
||||||
|
@ -367,7 +372,8 @@ bool RegisterAllocationPass::SpillOneRegister(
|
||||||
spill_value->last_use = spill_store;
|
spill_value->last_use = spill_store;
|
||||||
} else if (prev_use) {
|
} else if (prev_use) {
|
||||||
// We insert the store immediately before the previous use.
|
// We insert the store immediately before the previous use.
|
||||||
// If we were smarter we could then re-run allocation and reuse the register
|
// If we were smarter we could then re-run allocation and reuse the
|
||||||
|
// register
|
||||||
// once dropped.
|
// once dropped.
|
||||||
spill_store->MoveBefore(prev_use->instr);
|
spill_store->MoveBefore(prev_use->instr);
|
||||||
|
|
||||||
|
@ -396,7 +402,7 @@ bool RegisterAllocationPass::SpillOneRegister(
|
||||||
auto new_value = builder->LoadLocal(spill_value->local_slot);
|
auto new_value = builder->LoadLocal(spill_value->local_slot);
|
||||||
auto spill_load = builder->last_instr();
|
auto spill_load = builder->last_instr();
|
||||||
spill_load->MoveBefore(next_use->instr);
|
spill_load->MoveBefore(next_use->instr);
|
||||||
// Note: implicit first use added.
|
// Note: implicit first use added.
|
||||||
|
|
||||||
#if ASSERT_NO_CYCLES
|
#if ASSERT_NO_CYCLES
|
||||||
builder->AssertNoCycles();
|
builder->AssertNoCycles();
|
||||||
|
@ -448,8 +454,7 @@ bool RegisterAllocationPass::SpillOneRegister(
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterAllocationPass::RegisterSetUsage*
|
RegisterAllocationPass::RegisterSetUsage*
|
||||||
RegisterAllocationPass::RegisterSetForValue(
|
RegisterAllocationPass::RegisterSetForValue(const Value* value) {
|
||||||
const Value* value) {
|
|
||||||
if (value->type <= INT64_TYPE) {
|
if (value->type <= INT64_TYPE) {
|
||||||
return usage_sets_.int_set;
|
return usage_sets_.int_set;
|
||||||
} else if (value->type <= FLOAT64_TYPE) {
|
} else if (value->type <= FLOAT64_TYPE) {
|
||||||
|
@ -498,16 +503,24 @@ void RegisterAllocationPass::SortUsageList(Value* value) {
|
||||||
Value::Use* e = nullptr;
|
Value::Use* e = nullptr;
|
||||||
if (psize == 0) {
|
if (psize == 0) {
|
||||||
// p is empty; e must come from q
|
// p is empty; e must come from q
|
||||||
e = q; q = q->next; qsize--;
|
e = q;
|
||||||
|
q = q->next;
|
||||||
|
qsize--;
|
||||||
} else if (qsize == 0 || !q) {
|
} else if (qsize == 0 || !q) {
|
||||||
// q is empty; e must come from p
|
// q is empty; e must come from p
|
||||||
e = p; p = p->next; psize--;
|
e = p;
|
||||||
|
p = p->next;
|
||||||
|
psize--;
|
||||||
} else if (CompareValueUse(p, q) <= 0) {
|
} else if (CompareValueUse(p, q) <= 0) {
|
||||||
// First element of p is lower (or same); e must come from p
|
// First element of p is lower (or same); e must come from p
|
||||||
e = p; p = p->next; psize--;
|
e = p;
|
||||||
|
p = p->next;
|
||||||
|
psize--;
|
||||||
} else {
|
} else {
|
||||||
// First element of q is lower; e must come from q
|
// First element of q is lower; e must come from q
|
||||||
e = q; q = q->next; qsize--;
|
e = q;
|
||||||
|
q = q->next;
|
||||||
|
qsize--;
|
||||||
}
|
}
|
||||||
// add the next element to the merged list
|
// add the next element to the merged list
|
||||||
if (tail) {
|
if (tail) {
|
||||||
|
@ -537,3 +550,7 @@ void RegisterAllocationPass::SortUsageList(Value* value) {
|
||||||
value->use_head = head;
|
value->use_head = head;
|
||||||
value->last_use = tail->instr;
|
value->last_use = tail->instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -17,20 +17,18 @@
|
||||||
#include <alloy/backend/machine_info.h>
|
#include <alloy/backend/machine_info.h>
|
||||||
#include <alloy/compiler/compiler_pass.h>
|
#include <alloy/compiler/compiler_pass.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
|
|
||||||
class RegisterAllocationPass : public CompilerPass {
|
class RegisterAllocationPass : public CompilerPass {
|
||||||
public:
|
public:
|
||||||
RegisterAllocationPass(const backend::MachineInfo* machine_info);
|
RegisterAllocationPass(const backend::MachineInfo* machine_info);
|
||||||
virtual ~RegisterAllocationPass();
|
virtual ~RegisterAllocationPass();
|
||||||
|
|
||||||
virtual int Run(hir::HIRBuilder* builder);
|
virtual int Run(hir::HIRBuilder* builder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO(benvanik): rewrite all this set shit -- too much indirection, the
|
// TODO(benvanik): rewrite all this set shit -- too much indirection, the
|
||||||
// complexity is not needed.
|
// complexity is not needed.
|
||||||
struct RegisterUsage {
|
struct RegisterUsage {
|
||||||
|
@ -70,7 +68,7 @@ private:
|
||||||
|
|
||||||
void SortUsageList(hir::Value* value);
|
void SortUsageList(hir::Value* value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const backend::MachineInfo* machine_info_;
|
const backend::MachineInfo* machine_info_;
|
||||||
struct {
|
struct {
|
||||||
RegisterSetUsage* int_set = nullptr;
|
RegisterSetUsage* int_set = nullptr;
|
||||||
|
@ -80,10 +78,8 @@ private:
|
||||||
} usage_sets_;
|
} usage_sets_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace passes
|
} // namespace passes
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
#endif // ALLOY_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
||||||
|
|
|
@ -9,18 +9,20 @@
|
||||||
|
|
||||||
#include <alloy/compiler/passes/simplification_pass.h>
|
#include <alloy/compiler/passes/simplification_pass.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::compiler;
|
namespace compiler {
|
||||||
using namespace alloy::compiler::passes;
|
namespace passes {
|
||||||
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
|
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::hir::Instr;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
SimplificationPass::SimplificationPass() :
|
SimplificationPass::SimplificationPass() : CompilerPass() {}
|
||||||
CompilerPass() {
|
|
||||||
}
|
|
||||||
|
|
||||||
SimplificationPass::~SimplificationPass() {
|
SimplificationPass::~SimplificationPass() {}
|
||||||
}
|
|
||||||
|
|
||||||
int SimplificationPass::Run(HIRBuilder* builder) {
|
int SimplificationPass::Run(HIRBuilder* builder) {
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
@ -65,7 +67,7 @@ void SimplificationPass::CheckTruncate(Instr* i) {
|
||||||
// Walk backward up src's chain looking for an extend. We may have
|
// Walk backward up src's chain looking for an extend. We may have
|
||||||
// assigns, so skip those.
|
// assigns, so skip those.
|
||||||
auto src = i->src1.value;
|
auto src = i->src1.value;
|
||||||
Instr* def = src->def;
|
auto def = src->def;
|
||||||
while (def && def->opcode == &OPCODE_ASSIGN_info) {
|
while (def && def->opcode == &OPCODE_ASSIGN_info) {
|
||||||
// Skip asignments.
|
// Skip asignments.
|
||||||
def = def->src1.value->def;
|
def = def->src1.value->def;
|
||||||
|
@ -93,7 +95,7 @@ void SimplificationPass::CheckByteSwap(Instr* i) {
|
||||||
// Walk backward up src's chain looking for a byte swap. We may have
|
// Walk backward up src's chain looking for a byte swap. We may have
|
||||||
// assigns, so skip those.
|
// assigns, so skip those.
|
||||||
auto src = i->src1.value;
|
auto src = i->src1.value;
|
||||||
Instr* def = src->def;
|
auto def = src->def;
|
||||||
while (def && def->opcode == &OPCODE_ASSIGN_info) {
|
while (def && def->opcode == &OPCODE_ASSIGN_info) {
|
||||||
// Skip asignments.
|
// Skip asignments.
|
||||||
def = def->src1.value->def;
|
def = def->src1.value->def;
|
||||||
|
@ -147,11 +149,11 @@ void SimplificationPass::SimplifyAssignments(HIRBuilder* builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* SimplificationPass::CheckValue(Value* value) {
|
Value* SimplificationPass::CheckValue(Value* value) {
|
||||||
Instr* def = value->def;
|
auto def = value->def;
|
||||||
if (def && def->opcode == &OPCODE_ASSIGN_info) {
|
if (def && def->opcode == &OPCODE_ASSIGN_info) {
|
||||||
// Value comes from an assignment - recursively find if it comes from
|
// Value comes from an assignment - recursively find if it comes from
|
||||||
// another assignment. It probably doesn't, if we already replaced it.
|
// another assignment. It probably doesn't, if we already replaced it.
|
||||||
Value* replacement = def->src1.value;
|
auto replacement = def->src1.value;
|
||||||
while (true) {
|
while (true) {
|
||||||
def = replacement->def;
|
def = replacement->def;
|
||||||
if (!def || def->opcode != &OPCODE_ASSIGN_info) {
|
if (!def || def->opcode != &OPCODE_ASSIGN_info) {
|
||||||
|
@ -163,3 +165,7 @@ Value* SimplificationPass::CheckValue(Value* value) {
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -12,20 +12,18 @@
|
||||||
|
|
||||||
#include <alloy/compiler/compiler_pass.h>
|
#include <alloy/compiler/compiler_pass.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
|
|
||||||
class SimplificationPass : public CompilerPass {
|
class SimplificationPass : public CompilerPass {
|
||||||
public:
|
public:
|
||||||
SimplificationPass();
|
SimplificationPass();
|
||||||
virtual ~SimplificationPass();
|
virtual ~SimplificationPass();
|
||||||
|
|
||||||
virtual int Run(hir::HIRBuilder* builder);
|
virtual int Run(hir::HIRBuilder* builder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EliminateConversions(hir::HIRBuilder* builder);
|
void EliminateConversions(hir::HIRBuilder* builder);
|
||||||
void CheckTruncate(hir::Instr* i);
|
void CheckTruncate(hir::Instr* i);
|
||||||
void CheckByteSwap(hir::Instr* i);
|
void CheckByteSwap(hir::Instr* i);
|
||||||
|
@ -34,10 +32,8 @@ private:
|
||||||
hir::Value* CheckValue(hir::Value* value);
|
hir::Value* CheckValue(hir::Value* value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace passes
|
} // namespace passes
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
#endif // ALLOY_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||||
|
|
|
@ -13,21 +13,22 @@
|
||||||
#include <alloy/compiler/compiler.h>
|
#include <alloy/compiler/compiler.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace compiler {
|
||||||
using namespace alloy::compiler;
|
namespace passes {
|
||||||
using namespace alloy::compiler::passes;
|
|
||||||
using namespace alloy::frontend;
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::hir::Block;
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::hir::Instr;
|
||||||
|
using alloy::hir::OpcodeSignatureType;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
ValidationPass::ValidationPass() :
|
ValidationPass::ValidationPass() : CompilerPass() {}
|
||||||
CompilerPass() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ValidationPass::~ValidationPass() {
|
ValidationPass::~ValidationPass() {}
|
||||||
}
|
|
||||||
|
|
||||||
int ValidationPass::Run(HIRBuilder* builder) {
|
int ValidationPass::Run(HIRBuilder* builder) {
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
@ -90,7 +91,7 @@ int ValidationPass::ValidateInstruction(Block* block, Instr* instr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ValidationPass::ValidateValue(Block* block, Instr* instr, Value* value) {
|
int ValidationPass::ValidateValue(Block* block, Instr* instr, Value* value) {
|
||||||
//if (value->def) {
|
// if (value->def) {
|
||||||
// auto def = value->def;
|
// auto def = value->def;
|
||||||
// XEASSERT(def->block == block);
|
// XEASSERT(def->block == block);
|
||||||
// if (def->block != block) {
|
// if (def->block != block) {
|
||||||
|
@ -99,3 +100,7 @@ int ValidationPass::ValidateValue(Block* block, Instr* instr, Value* value) {
|
||||||
//}
|
//}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -12,28 +12,24 @@
|
||||||
|
|
||||||
#include <alloy/compiler/compiler_pass.h>
|
#include <alloy/compiler/compiler_pass.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
|
|
||||||
class ValidationPass : public CompilerPass {
|
class ValidationPass : public CompilerPass {
|
||||||
public:
|
public:
|
||||||
ValidationPass();
|
ValidationPass();
|
||||||
virtual ~ValidationPass();
|
virtual ~ValidationPass();
|
||||||
|
|
||||||
virtual int Run(hir::HIRBuilder* builder);
|
virtual int Run(hir::HIRBuilder* builder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int ValidateInstruction(hir::Block* block, hir::Instr* instr);
|
int ValidateInstruction(hir::Block* block, hir::Instr* instr);
|
||||||
int ValidateValue(hir::Block* block, hir::Instr* instr, hir::Value* value);
|
int ValidateValue(hir::Block* block, hir::Instr* instr, hir::Value* value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace passes
|
} // namespace passes
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_PASSES_VALIDATION_PASS_H_
|
#endif // ALLOY_COMPILER_PASSES_VALIDATION_PASS_H_
|
||||||
|
|
|
@ -19,21 +19,20 @@
|
||||||
#include <llvm/ADT/BitVector.h>
|
#include <llvm/ADT/BitVector.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace compiler {
|
||||||
using namespace alloy::compiler;
|
namespace passes {
|
||||||
using namespace alloy::compiler::passes;
|
|
||||||
using namespace alloy::frontend;
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::hir::HIRBuilder;
|
||||||
|
using alloy::hir::OpcodeInfo;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
ValueReductionPass::ValueReductionPass() :
|
ValueReductionPass::ValueReductionPass() : CompilerPass() {}
|
||||||
CompilerPass() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueReductionPass::~ValueReductionPass() {
|
ValueReductionPass::~ValueReductionPass() {}
|
||||||
}
|
|
||||||
|
|
||||||
void ValueReductionPass::ComputeLastUse(Value* value) {
|
void ValueReductionPass::ComputeLastUse(Value* value) {
|
||||||
// TODO(benvanik): compute during construction?
|
// TODO(benvanik): compute during construction?
|
||||||
|
@ -137,3 +136,7 @@ int ValueReductionPass::Run(HIRBuilder* builder) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -12,27 +12,23 @@
|
||||||
|
|
||||||
#include <alloy/compiler/compiler_pass.h>
|
#include <alloy/compiler/compiler_pass.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
|
|
||||||
class ValueReductionPass : public CompilerPass {
|
class ValueReductionPass : public CompilerPass {
|
||||||
public:
|
public:
|
||||||
ValueReductionPass();
|
ValueReductionPass();
|
||||||
virtual ~ValueReductionPass();
|
virtual ~ValueReductionPass();
|
||||||
|
|
||||||
virtual int Run(hir::HIRBuilder* builder);
|
virtual int Run(hir::HIRBuilder* builder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ComputeLastUse(hir::Value* value);
|
void ComputeLastUse(hir::Value* value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace passes
|
} // namespace passes
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
#endif // ALLOY_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
||||||
|
|
|
@ -13,18 +13,16 @@
|
||||||
#include <alloy/tracing/tracing.h>
|
#include <alloy/tracing/tracing.h>
|
||||||
#include <alloy/tracing/event_type.h>
|
#include <alloy/tracing/event_type.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
const uint32_t ALLOY_COMPILER = alloy::tracing::EventType::ALLOY_COMPILER;
|
const uint32_t ALLOY_COMPILER = alloy::tracing::EventType::ALLOY_COMPILER;
|
||||||
|
|
||||||
|
|
||||||
class EventType {
|
class EventType {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
ALLOY_COMPILER_INIT = ALLOY_COMPILER | (1),
|
ALLOY_COMPILER_INIT = ALLOY_COMPILER | (1),
|
||||||
ALLOY_COMPILER_DEINIT = ALLOY_COMPILER | (2),
|
ALLOY_COMPILER_DEINIT = ALLOY_COMPILER | (2),
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Init_s {
|
typedef struct Init_s {
|
||||||
|
@ -35,9 +33,7 @@ public:
|
||||||
} Deinit;
|
} Deinit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_COMPILER_TRACING_H_
|
#endif // ALLOY_COMPILER_TRACING_H_
|
||||||
|
|
|
@ -17,61 +17,76 @@
|
||||||
#include <alloy/delegate.h>
|
#include <alloy/delegate.h>
|
||||||
#include <alloy/string_buffer.h>
|
#include <alloy/string_buffer.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
|
|
||||||
typedef struct XECACHEALIGN vec128_s {
|
typedef struct XECACHEALIGN vec128_s {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
float z;
|
float z;
|
||||||
float w;
|
float w;
|
||||||
};
|
};
|
||||||
struct {
|
struct {
|
||||||
uint32_t ix;
|
uint32_t ix;
|
||||||
uint32_t iy;
|
uint32_t iy;
|
||||||
uint32_t iz;
|
uint32_t iz;
|
||||||
uint32_t iw;
|
uint32_t iw;
|
||||||
};
|
};
|
||||||
float f4[4];
|
float f4[4];
|
||||||
uint32_t i4[4];
|
uint32_t i4[4];
|
||||||
uint16_t s8[8];
|
uint16_t s8[8];
|
||||||
uint8_t b16[16];
|
uint8_t b16[16];
|
||||||
struct {
|
struct {
|
||||||
uint64_t low;
|
uint64_t low;
|
||||||
uint64_t high;
|
uint64_t high;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator== (const vec128_s& b) const {
|
bool operator==(const vec128_s& b) const {
|
||||||
return low == b.low && high == b.high;
|
return low == b.low && high == b.high;
|
||||||
}
|
}
|
||||||
} vec128_t;
|
} vec128_t;
|
||||||
XEFORCEINLINE vec128_t vec128i(uint32_t x, uint32_t y, uint32_t z, uint32_t w) {
|
XEFORCEINLINE vec128_t vec128i(uint32_t x, uint32_t y, uint32_t z, uint32_t w) {
|
||||||
vec128_t v;
|
vec128_t v;
|
||||||
v.i4[0] = x; v.i4[1] = y; v.i4[2] = z; v.i4[3] = w;
|
v.i4[0] = x;
|
||||||
|
v.i4[1] = y;
|
||||||
|
v.i4[2] = z;
|
||||||
|
v.i4[3] = w;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
XEFORCEINLINE vec128_t vec128f(float x, float y, float z, float w) {
|
XEFORCEINLINE vec128_t vec128f(float x, float y, float z, float w) {
|
||||||
vec128_t v;
|
vec128_t v;
|
||||||
v.f4[0] = x; v.f4[1] = y; v.f4[2] = z; v.f4[3] = w;
|
v.f4[0] = x;
|
||||||
|
v.f4[1] = y;
|
||||||
|
v.f4[2] = z;
|
||||||
|
v.f4[3] = w;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
XEFORCEINLINE vec128_t vec128b(
|
XEFORCEINLINE vec128_t vec128b(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3,
|
||||||
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 y0, uint8_t y1, uint8_t y2, uint8_t y3,
|
uint8_t z0, uint8_t z1, uint8_t z2, uint8_t z3,
|
||||||
uint8_t z0, uint8_t z1, uint8_t z2, uint8_t z3,
|
uint8_t w0, uint8_t w1, uint8_t w2, uint8_t w3) {
|
||||||
uint8_t w0, uint8_t w1, uint8_t w2, uint8_t w3) {
|
|
||||||
vec128_t v;
|
vec128_t v;
|
||||||
v.b16[0] = x3; v.b16[1] = x2; v.b16[2] = x1; v.b16[3] = x0;
|
v.b16[0] = x3;
|
||||||
v.b16[4] = y3; v.b16[5] = y2; v.b16[6] = y1; v.b16[7] = y0;
|
v.b16[1] = x2;
|
||||||
v.b16[8] = z3; v.b16[9] = z2; v.b16[10] = z1; v.b16[11] = z0;
|
v.b16[2] = x1;
|
||||||
v.b16[12] = w3; v.b16[13] = w2; v.b16[14] = w1; v.b16[15] = w0;
|
v.b16[3] = x0;
|
||||||
|
v.b16[4] = y3;
|
||||||
|
v.b16[5] = y2;
|
||||||
|
v.b16[6] = y1;
|
||||||
|
v.b16[7] = y0;
|
||||||
|
v.b16[8] = z3;
|
||||||
|
v.b16[9] = z2;
|
||||||
|
v.b16[10] = z1;
|
||||||
|
v.b16[11] = z0;
|
||||||
|
v.b16[12] = w3;
|
||||||
|
v.b16[13] = w2;
|
||||||
|
v.b16[14] = w1;
|
||||||
|
v.b16[15] = w0;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_CORE_H_
|
#endif // ALLOY_CORE_H_
|
||||||
|
|
|
@ -16,15 +16,13 @@
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
|
|
||||||
|
|
||||||
// TODO(benvanik): go lockfree, and don't hold the lock while emitting.
|
// TODO(benvanik): go lockfree, and don't hold the lock while emitting.
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Delegate {
|
class Delegate {
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(T&)> listener_t;
|
typedef std::function<void(T&)> listener_t;
|
||||||
|
|
||||||
void AddListener(listener_t const& listener) {
|
void AddListener(listener_t const& listener) {
|
||||||
|
@ -49,18 +47,16 @@ public:
|
||||||
|
|
||||||
void operator()(T& e) {
|
void operator()(T& e) {
|
||||||
std::lock_guard<std::mutex> guard(lock_);
|
std::lock_guard<std::mutex> guard(lock_);
|
||||||
for (auto &listener : listeners_) {
|
for (auto& listener : listeners_) {
|
||||||
listener(e);
|
listener(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
std::vector<listener_t> listeners_;
|
std::vector<listener_t> listeners_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_DELEGATE_H_
|
#endif // ALLOY_DELEGATE_H_
|
||||||
|
|
|
@ -9,14 +9,13 @@
|
||||||
|
|
||||||
#include <alloy/frontend/context_info.h>
|
#include <alloy/frontend/context_info.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::frontend;
|
namespace frontend {
|
||||||
|
|
||||||
|
ContextInfo::ContextInfo(size_t size, uintptr_t thread_state_offset)
|
||||||
|
: size_(size), thread_state_offset_(thread_state_offset) {}
|
||||||
|
|
||||||
ContextInfo::ContextInfo(size_t size, uintptr_t thread_state_offset) :
|
ContextInfo::~ContextInfo() {}
|
||||||
size_(size),
|
|
||||||
thread_state_offset_(thread_state_offset) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextInfo::~ContextInfo() {
|
} // namespace frontend
|
||||||
}
|
} // namespace alloy
|
||||||
|
|
|
@ -12,13 +12,11 @@
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
|
|
||||||
|
|
||||||
class ContextInfo {
|
class ContextInfo {
|
||||||
public:
|
public:
|
||||||
ContextInfo(size_t size, uintptr_t thread_state_offset);
|
ContextInfo(size_t size, uintptr_t thread_state_offset);
|
||||||
~ContextInfo();
|
~ContextInfo();
|
||||||
|
|
||||||
|
@ -26,14 +24,12 @@ public:
|
||||||
|
|
||||||
uintptr_t thread_state_offset() const { return thread_state_offset_; }
|
uintptr_t thread_state_offset() const { return thread_state_offset_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t size_;
|
size_t size_;
|
||||||
uintptr_t thread_state_offset_;
|
uintptr_t thread_state_offset_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_CONTEXT_INFO_H_
|
#endif // ALLOY_FRONTEND_CONTEXT_INFO_H_
|
||||||
|
|
|
@ -12,23 +12,17 @@
|
||||||
#include <alloy/frontend/tracing.h>
|
#include <alloy/frontend/tracing.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::frontend;
|
namespace frontend {
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
Frontend::Frontend(runtime::Runtime* runtime)
|
||||||
|
: runtime_(runtime), context_info_(0) {}
|
||||||
|
|
||||||
Frontend::Frontend(Runtime* runtime) :
|
Frontend::~Frontend() { delete context_info_; }
|
||||||
runtime_(runtime), context_info_(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Frontend::~Frontend() {
|
Memory* Frontend::memory() const { return runtime_->memory(); }
|
||||||
delete context_info_;
|
|
||||||
}
|
|
||||||
|
|
||||||
Memory* Frontend::memory() const {
|
int Frontend::Initialize() { return 0; }
|
||||||
return runtime_->memory();
|
|
||||||
}
|
|
||||||
|
|
||||||
int Frontend::Initialize() {
|
} // namespace frontend
|
||||||
return 0;
|
} // namespace alloy
|
||||||
}
|
|
||||||
|
|
|
@ -16,17 +16,17 @@
|
||||||
#include <alloy/runtime/function.h>
|
#include <alloy/runtime/function.h>
|
||||||
#include <alloy/runtime/symbol_info.h>
|
#include <alloy/runtime/symbol_info.h>
|
||||||
|
|
||||||
|
namespace alloy {
|
||||||
namespace alloy { namespace runtime {
|
namespace runtime {
|
||||||
class Runtime;
|
class Runtime;
|
||||||
} }
|
} // namespace runtime
|
||||||
|
} // namespace alloy
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
|
|
||||||
|
|
||||||
class Frontend {
|
class Frontend {
|
||||||
public:
|
public:
|
||||||
Frontend(runtime::Runtime* runtime);
|
Frontend(runtime::Runtime* runtime);
|
||||||
virtual ~Frontend();
|
virtual ~Frontend();
|
||||||
|
|
||||||
|
@ -36,20 +36,17 @@ public:
|
||||||
|
|
||||||
virtual int Initialize();
|
virtual int Initialize();
|
||||||
|
|
||||||
virtual int DeclareFunction(
|
virtual int DeclareFunction(runtime::FunctionInfo* symbol_info) = 0;
|
||||||
runtime::FunctionInfo* symbol_info) = 0;
|
virtual int DefineFunction(runtime::FunctionInfo* symbol_info,
|
||||||
virtual int DefineFunction(
|
uint32_t debug_info_flags,
|
||||||
runtime::FunctionInfo* symbol_info, uint32_t debug_info_flags,
|
runtime::Function** out_function) = 0;
|
||||||
runtime::Function** out_function) = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
runtime::Runtime* runtime_;
|
runtime::Runtime* runtime_;
|
||||||
ContextInfo* context_info_;
|
ContextInfo* context_info_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_FRONTEND_H_
|
#endif // ALLOY_FRONTEND_FRONTEND_H_
|
||||||
|
|
|
@ -9,19 +9,11 @@
|
||||||
|
|
||||||
#include <alloy/frontend/ppc/ppc_context.h>
|
#include <alloy/frontend/ppc/ppc_context.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::frontend;
|
namespace frontend {
|
||||||
using namespace alloy::frontend::ppc;
|
namespace ppc {
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
uint64_t ParseInt64(const char* value) {
|
|
||||||
return xestrtoulla(value, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
uint64_t ParseInt64(const char* value) { return xestrtoulla(value, NULL, 0); }
|
||||||
|
|
||||||
void PPCContext::SetRegFromString(const char* name, const char* value) {
|
void PPCContext::SetRegFromString(const char* name, const char* value) {
|
||||||
int n;
|
int n;
|
||||||
|
@ -32,9 +24,8 @@ void PPCContext::SetRegFromString(const char* name, const char* value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PPCContext::CompareRegWithString(
|
bool PPCContext::CompareRegWithString(const char* name, const char* value,
|
||||||
const char* name, const char* value,
|
char* out_value, size_t out_value_size) {
|
||||||
char* out_value, size_t out_value_size) {
|
|
||||||
int n;
|
int n;
|
||||||
if (sscanf(name, "r%d", &n) == 1) {
|
if (sscanf(name, "r%d", &n) == 1) {
|
||||||
uint64_t expected = ParseInt64(value);
|
uint64_t expected = ParseInt64(value);
|
||||||
|
@ -48,3 +39,7 @@ bool PPCContext::CompareRegWithString(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ppc
|
||||||
|
} // namespace frontend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -9,10 +9,6 @@
|
||||||
|
|
||||||
#include <alloy/frontend/ppc/ppc_disasm.h>
|
#include <alloy/frontend/ppc/ppc_disasm.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace alloy::frontend::ppc;
|
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
@ -26,221 +22,210 @@ void Disasm__(InstrData& i, StringBuffer* str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disasm_X_FRT_FRB(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s f%d, f%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||||
i.X.RT, i.X.RB);
|
i.X.Rc ? "." : "", i.X.RT, i.X.RB);
|
||||||
}
|
}
|
||||||
void Disasm_A_FRT_FRB(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||||
i.A.FRT, i.A.FRB);
|
i.A.Rc ? "." : "", i.A.FRT, i.A.FRB);
|
||||||
}
|
}
|
||||||
void Disasm_A_FRT_FRA_FRB(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||||
i.A.FRT, i.A.FRA, i.A.FRB);
|
i.A.Rc ? "." : "", i.A.FRT, i.A.FRA, i.A.FRB);
|
||||||
}
|
}
|
||||||
void Disasm_A_FRT_FRA_FRB_FRC(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s f%d, f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||||
i.A.FRT, i.A.FRA, i.A.FRB, i.A.FRC);
|
i.A.Rc ? "." : "", i.A.FRT, i.A.FRA, i.A.FRB, i.A.FRC);
|
||||||
}
|
}
|
||||||
void Disasm_X_RT_RA_RB(InstrData& i, StringBuffer* str) {
|
void Disasm_X_RT_RA_RB(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s r%d, r%d, %d", i.type->name,
|
str->Append("%-8s r%d, r%d, %d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||||
i.X.RT, i.X.RA, i.X.RB);
|
|
||||||
}
|
}
|
||||||
void Disasm_X_RT_RA0_RB(InstrData& i, StringBuffer* str) {
|
void Disasm_X_RT_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||||
if (i.X.RA) {
|
if (i.X.RA) {
|
||||||
str->Append("%-8s r%d, r%d, %d", i.type->name,
|
str->Append("%-8s r%d, r%d, %d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||||
i.X.RT, i.X.RA, i.X.RB);
|
|
||||||
} else {
|
} else {
|
||||||
str->Append("%-8s r%d, 0, %d", i.type->name,
|
str->Append("%-8s r%d, 0, %d", i.type->name, i.X.RT, i.X.RB);
|
||||||
i.X.RT, i.X.RB);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Disasm_X_FRT_RA_RB(InstrData& i, StringBuffer* str) {
|
void Disasm_X_FRT_RA_RB(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s f%d, r%d, %d", i.type->name,
|
str->Append("%-8s f%d, r%d, %d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||||
i.X.RT, i.X.RA, i.X.RB);
|
|
||||||
}
|
}
|
||||||
void Disasm_X_FRT_RA0_RB(InstrData& i, StringBuffer* str) {
|
void Disasm_X_FRT_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||||
if (i.X.RA) {
|
if (i.X.RA) {
|
||||||
str->Append("%-8s f%d, r%d, %d", i.type->name,
|
str->Append("%-8s f%d, r%d, %d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||||
i.X.RT, i.X.RA, i.X.RB);
|
|
||||||
} else {
|
} else {
|
||||||
str->Append("%-8s f%d, 0, %d", i.type->name,
|
str->Append("%-8s f%d, 0, %d", i.type->name, i.X.RT, i.X.RB);
|
||||||
i.X.RT, i.X.RB);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Disasm_D_RT_RA_I(InstrData& i, StringBuffer* str) {
|
void Disasm_D_RT_RA_I(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s r%d, r%d, %d", i.type->name,
|
str->Append("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||||
i.D.RT, i.D.RA, (int32_t)(int16_t)XEEXTS16(i.D.DS));
|
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||||
}
|
}
|
||||||
void Disasm_D_RT_RA0_I(InstrData& i, StringBuffer* str) {
|
void Disasm_D_RT_RA0_I(InstrData& i, StringBuffer* str) {
|
||||||
if (i.D.RA) {
|
if (i.D.RA) {
|
||||||
str->Append("%-8s r%d, r%d, %d", i.type->name,
|
str->Append("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||||
i.D.RT, i.D.RA, (int32_t)(int16_t)XEEXTS16(i.D.DS));
|
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||||
} else {
|
} else {
|
||||||
str->Append("%-8s r%d, 0, %d", i.type->name,
|
str->Append("%-8s r%d, 0, %d", i.type->name, i.D.RT,
|
||||||
i.D.RT, (int32_t)(int16_t)XEEXTS16(i.D.DS));
|
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Disasm_D_FRT_RA_I(InstrData& i, StringBuffer* str) {
|
void Disasm_D_FRT_RA_I(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s f%d, r%d, %d", i.type->name,
|
str->Append("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||||
i.D.RT, i.D.RA, (int32_t)(int16_t)XEEXTS16(i.D.DS));
|
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||||
}
|
}
|
||||||
void Disasm_D_FRT_RA0_I(InstrData& i, StringBuffer* str) {
|
void Disasm_D_FRT_RA0_I(InstrData& i, StringBuffer* str) {
|
||||||
if (i.D.RA) {
|
if (i.D.RA) {
|
||||||
str->Append("%-8s f%d, r%d, %d", i.type->name,
|
str->Append("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||||
i.D.RT, i.D.RA, (int32_t)(int16_t)XEEXTS16(i.D.DS));
|
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||||
} else {
|
} else {
|
||||||
str->Append("%-8s f%d, 0, %d", i.type->name,
|
str->Append("%-8s f%d, 0, %d", i.type->name, i.D.RT,
|
||||||
i.D.RT, (int32_t)(int16_t)XEEXTS16(i.D.DS));
|
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Disasm_DS_RT_RA_I(InstrData& i, StringBuffer* str) {
|
void Disasm_DS_RT_RA_I(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s r%d, r%d, %d", i.type->name,
|
str->Append("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||||
i.DS.RT, i.DS.RA, (int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
|
(int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
|
||||||
}
|
}
|
||||||
void Disasm_DS_RT_RA0_I(InstrData& i, StringBuffer* str) {
|
void Disasm_DS_RT_RA0_I(InstrData& i, StringBuffer* str) {
|
||||||
if (i.DS.RA) {
|
if (i.DS.RA) {
|
||||||
str->Append("%-8s r%d, r%d, %d", i.type->name,
|
str->Append("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||||
i.DS.RT, i.DS.RA, (int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
|
(int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
|
||||||
} else {
|
} else {
|
||||||
str->Append("%-8s r%d, 0, %d", i.type->name,
|
str->Append("%-8s r%d, 0, %d", i.type->name, i.DS.RT,
|
||||||
i.DS.RT, (int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
|
(int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Disasm_D_RA(InstrData& i, StringBuffer* str) {
|
void Disasm_D_RA(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s r%d", i.type->name,
|
str->Append("%-8s r%d", i.type->name, i.D.RA);
|
||||||
i.D.RA);
|
|
||||||
}
|
}
|
||||||
void Disasm_X_RA_RB(InstrData& i, StringBuffer* str) {
|
void Disasm_X_RA_RB(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s r%d, r%d", i.type->name,
|
str->Append("%-8s r%d, r%d", i.type->name, i.X.RA, i.X.RB);
|
||||||
i.X.RA, i.X.RB);
|
|
||||||
}
|
}
|
||||||
void Disasm_XO_RT_RA_RB(InstrData& i, 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,
|
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.OE ? "o" : "", i.XO.Rc ? "." : "", i.XO.RT, i.XO.RA,
|
||||||
i.XO.RT, i.XO.RA, i.XO.RB);
|
i.XO.RB);
|
||||||
}
|
}
|
||||||
void Disasm_XO_RT_RA(InstrData& i, 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,
|
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.OE ? "o" : "", i.XO.Rc ? "." : "", i.XO.RT, i.XO.RA);
|
||||||
i.XO.RT, i.XO.RA);
|
|
||||||
}
|
}
|
||||||
void Disasm_X_RA_RT_RB(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s r%d, r%d, r%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||||
i.X.RA, i.X.RT, i.X.RB);
|
i.X.Rc ? "." : "", i.X.RA, i.X.RT, i.X.RB);
|
||||||
}
|
}
|
||||||
void Disasm_D_RA_RT_I(InstrData& i, StringBuffer* str) {
|
void Disasm_D_RA_RT_I(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-7s. r%d, r%d, %.4Xh", i.type->name,
|
str->Append("%-7s. r%d, r%d, %.4Xh", i.type->name, i.D.RA, i.D.RT, i.D.DS);
|
||||||
i.D.RA, i.D.RT, i.D.DS);
|
|
||||||
}
|
}
|
||||||
void Disasm_X_RA_RT(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s r%d, r%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||||
i.X.RA, i.X.RT);
|
i.X.Rc ? "." : "", i.X.RA, i.X.RT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OP(x) ((((uint32_t)(x)) & 0x3f) << 26)
|
#define OP(x) ((((uint32_t)(x)) & 0x3f) << 26)
|
||||||
#define VX128(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x3d0))
|
#define VX128(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x3d0))
|
||||||
#define VX128_1(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x7f3))
|
#define VX128_1(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x7f3))
|
||||||
#define VX128_2(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x210))
|
#define VX128_2(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x210))
|
||||||
#define VX128_3(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x7f0))
|
#define VX128_3(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x7f0))
|
||||||
#define VX128_4(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x730))
|
#define VX128_4(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x730))
|
||||||
#define VX128_5(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x10))
|
#define VX128_5(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x10))
|
||||||
#define VX128_P(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x630))
|
#define VX128_P(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x630))
|
||||||
|
|
||||||
#define VX128_VD128 (i.VX128.VD128l | (i.VX128.VD128h << 5))
|
#define VX128_VD128 (i.VX128.VD128l | (i.VX128.VD128h << 5))
|
||||||
#define VX128_VA128 (i.VX128.VA128l | (i.VX128.VA128h << 5) | (i.VX128.VA128H << 6))
|
#define VX128_VA128 \
|
||||||
|
(i.VX128.VA128l | (i.VX128.VA128h << 5) | (i.VX128.VA128H << 6))
|
||||||
#define VX128_VB128 (i.VX128.VB128l | (i.VX128.VB128h << 5))
|
#define VX128_VB128 (i.VX128.VB128l | (i.VX128.VB128h << 5))
|
||||||
#define VX128_1_VD128 (i.VX128_1.VD128l | (i.VX128_1.VD128h << 5))
|
#define VX128_1_VD128 (i.VX128_1.VD128l | (i.VX128_1.VD128h << 5))
|
||||||
#define VX128_2_VD128 (i.VX128_2.VD128l | (i.VX128_2.VD128h << 5))
|
#define VX128_2_VD128 (i.VX128_2.VD128l | (i.VX128_2.VD128h << 5))
|
||||||
#define VX128_2_VA128 (i.VX128_2.VA128l | (i.VX128_2.VA128h << 5) | (i.VX128_2.VA128H << 6))
|
#define VX128_2_VA128 \
|
||||||
|
(i.VX128_2.VA128l | (i.VX128_2.VA128h << 5) | (i.VX128_2.VA128H << 6))
|
||||||
#define VX128_2_VB128 (i.VX128_2.VB128l | (i.VX128_2.VD128h << 5))
|
#define VX128_2_VB128 (i.VX128_2.VB128l | (i.VX128_2.VD128h << 5))
|
||||||
#define VX128_2_VC (i.VX128_2.VC)
|
#define VX128_2_VC (i.VX128_2.VC)
|
||||||
#define VX128_3_VD128 (i.VX128_3.VD128l | (i.VX128_3.VD128h << 5))
|
#define VX128_3_VD128 (i.VX128_3.VD128l | (i.VX128_3.VD128h << 5))
|
||||||
#define VX128_3_VB128 (i.VX128_3.VB128l | (i.VX128_3.VB128h << 5))
|
#define VX128_3_VB128 (i.VX128_3.VB128l | (i.VX128_3.VB128h << 5))
|
||||||
#define VX128_3_IMM (i.VX128_3.IMM)
|
#define VX128_3_IMM (i.VX128_3.IMM)
|
||||||
#define VX128_4_VD128 (i.VX128_4.VD128l | (i.VX128_4.VD128h << 5))
|
#define VX128_4_VD128 (i.VX128_4.VD128l | (i.VX128_4.VD128h << 5))
|
||||||
#define VX128_4_VB128 (i.VX128_4.VB128l | (i.VX128_4.VB128h << 5))
|
#define VX128_4_VB128 (i.VX128_4.VB128l | (i.VX128_4.VB128h << 5))
|
||||||
#define VX128_5_VD128 (i.VX128_5.VD128l | (i.VX128_5.VD128h << 5))
|
#define VX128_5_VD128 (i.VX128_5.VD128l | (i.VX128_5.VD128h << 5))
|
||||||
#define VX128_5_VA128 (i.VX128_5.VA128l | (i.VX128_5.VA128h << 5)) | (i.VX128_5.VA128H << 6)
|
#define VX128_5_VA128 \
|
||||||
|
(i.VX128_5.VA128l | (i.VX128_5.VA128h << 5)) | (i.VX128_5.VA128H << 6)
|
||||||
#define VX128_5_VB128 (i.VX128_5.VB128l | (i.VX128_5.VB128h << 5))
|
#define VX128_5_VB128 (i.VX128_5.VB128l | (i.VX128_5.VB128h << 5))
|
||||||
#define VX128_5_SH (i.VX128_5.SH)
|
#define VX128_5_SH (i.VX128_5.SH)
|
||||||
#define VX128_R_VD128 (i.VX128_R.VD128l | (i.VX128_R.VD128h << 5))
|
#define VX128_R_VD128 (i.VX128_R.VD128l | (i.VX128_R.VD128h << 5))
|
||||||
#define VX128_R_VA128 (i.VX128_R.VA128l | (i.VX128_R.VA128h << 5) | (i.VX128_R.VA128H << 6))
|
#define VX128_R_VA128 \
|
||||||
|
(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))
|
#define VX128_R_VB128 (i.VX128_R.VB128l | (i.VX128_R.VB128h << 5))
|
||||||
|
|
||||||
void Disasm_X_VX_RA0_RB(InstrData& i, StringBuffer* str) {
|
void Disasm_X_VX_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||||
if (i.X.RA) {
|
if (i.X.RA) {
|
||||||
str->Append("%-8s v%d, r%d, r%d", i.type->name,
|
str->Append("%-8s v%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||||
i.X.RT, i.X.RA, i.X.RB);
|
|
||||||
} else {
|
} else {
|
||||||
str->Append("%-8s v%d, 0, r%d", i.type->name,
|
str->Append("%-8s v%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||||
i.X.RT, i.X.RB);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Disasm_VX1281_VD_RA0_RB(InstrData& i, StringBuffer* str) {
|
void Disasm_VX1281_VD_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t vd = VX128_1_VD128;
|
const uint32_t vd = VX128_1_VD128;
|
||||||
if (i.VX128_1.RA) {
|
if (i.VX128_1.RA) {
|
||||||
str->Append("%-8s v%d, r%d, r%d", i.type->name,
|
str->Append("%-8s v%d, r%d, r%d", i.type->name, vd, i.VX128_1.RA,
|
||||||
vd, i.VX128_1.RA, i.VX128_1.RB);
|
i.VX128_1.RB);
|
||||||
} else {
|
} else {
|
||||||
str->Append("%-8s v%d, 0, r%d", i.type->name,
|
str->Append("%-8s v%d, 0, r%d", i.type->name, vd, i.VX128_1.RB);
|
||||||
vd, i.VX128_1.RB);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Disasm_VX1283_VD_VB(InstrData& i, StringBuffer* str) {
|
void Disasm_VX1283_VD_VB(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t vd = VX128_3_VD128;
|
const uint32_t vd = VX128_3_VD128;
|
||||||
const uint32_t vb = VX128_3_VB128;
|
const uint32_t vb = VX128_3_VB128;
|
||||||
str->Append("%-8s v%d, v%d", i.type->name,
|
str->Append("%-8s v%d, v%d", i.type->name, vd, vb);
|
||||||
vd, vb);
|
|
||||||
}
|
}
|
||||||
void Disasm_VX1283_VD_VB_I(InstrData& i, StringBuffer* str) {
|
void Disasm_VX1283_VD_VB_I(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t vd = VX128_VD128;
|
const uint32_t vd = VX128_VD128;
|
||||||
const uint32_t va = VX128_VA128;
|
const uint32_t va = VX128_VA128;
|
||||||
const uint32_t uimm = i.VX128_3.IMM;
|
const uint32_t uimm = i.VX128_3.IMM;
|
||||||
str->Append("%-8s v%d, v%d, %.2Xh", i.type->name,
|
str->Append("%-8s v%d, v%d, %.2Xh", i.type->name, vd, va, uimm);
|
||||||
vd, va, uimm);
|
|
||||||
}
|
}
|
||||||
void Disasm_VX_VD_VA_VB(InstrData& i, StringBuffer* str) {
|
void Disasm_VX_VD_VA_VB(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s v%d, v%d, v%d", i.type->name,
|
str->Append("%-8s v%d, v%d, v%d", i.type->name, i.VX.VD, i.VX.VA, i.VX.VB);
|
||||||
i.VX.VD, i.VX.VA, i.VX.VB);
|
|
||||||
}
|
}
|
||||||
void Disasm_VX128_VD_VA_VB(InstrData& i, StringBuffer* str) {
|
void Disasm_VX128_VD_VA_VB(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t vd = VX128_VD128;
|
const uint32_t vd = VX128_VD128;
|
||||||
const uint32_t va = VX128_VA128;
|
const uint32_t va = VX128_VA128;
|
||||||
const uint32_t vb = VX128_VB128;
|
const uint32_t vb = VX128_VB128;
|
||||||
str->Append("%-8s v%d, v%d, v%d", i.type->name,
|
str->Append("%-8s v%d, v%d, v%d", i.type->name, vd, va, vb);
|
||||||
vd, va, vb);
|
|
||||||
}
|
}
|
||||||
void Disasm_VX128_VD_VA_VD_VB(InstrData& i, StringBuffer* str) {
|
void Disasm_VX128_VD_VA_VD_VB(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t vd = VX128_VD128;
|
const uint32_t vd = VX128_VD128;
|
||||||
const uint32_t va = VX128_VA128;
|
const uint32_t va = VX128_VA128;
|
||||||
const uint32_t vb = VX128_VB128;
|
const uint32_t vb = VX128_VB128;
|
||||||
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name,
|
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name, vd, va, vd, vb);
|
||||||
vd, va, vd, vb);
|
|
||||||
}
|
}
|
||||||
void Disasm_VX1282_VD_VA_VB_VC(InstrData& i, StringBuffer* str) {
|
void Disasm_VX1282_VD_VA_VB_VC(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t vd = VX128_2_VD128;
|
const uint32_t vd = VX128_2_VD128;
|
||||||
const uint32_t va = VX128_2_VA128;
|
const uint32_t va = VX128_2_VA128;
|
||||||
const uint32_t vb = VX128_2_VB128;
|
const uint32_t vb = VX128_2_VB128;
|
||||||
const uint32_t vc = i.VX128_2.VC;
|
const uint32_t vc = i.VX128_2.VC;
|
||||||
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name,
|
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name, vd, va, vb, vc);
|
||||||
vd, va, vb, vc);
|
|
||||||
}
|
}
|
||||||
void Disasm_VXA_VD_VA_VB_VC(InstrData& i, 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,
|
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name, i.VXA.VD, i.VXA.VA,
|
||||||
i.VXA.VD, i.VXA.VA, i.VXA.VB, i.VXA.VC);
|
i.VXA.VB, i.VXA.VC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disasm_sync(InstrData& i, StringBuffer* str) {
|
void Disasm_sync(InstrData& i, StringBuffer* str) {
|
||||||
const char* name;
|
const char* name;
|
||||||
int L = i.X.RT & 3;
|
int L = i.X.RT & 3;
|
||||||
switch (L) {
|
switch (L) {
|
||||||
case 0: name = "hwsync"; break;
|
case 0:
|
||||||
case 1: name = "lwsync"; break;
|
name = "hwsync";
|
||||||
default:
|
break;
|
||||||
case 2:
|
case 1:
|
||||||
case 3:
|
name = "lwsync";
|
||||||
name = "sync";
|
break;
|
||||||
break;
|
default:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
name = "sync";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
str->Append("%-8s %.2X", name, L);
|
str->Append("%-8s %.2X", name, L);
|
||||||
}
|
}
|
||||||
|
@ -248,10 +233,18 @@ void Disasm_sync(InstrData& i, StringBuffer* str) {
|
||||||
void Disasm_dcbf(InstrData& i, StringBuffer* str) {
|
void Disasm_dcbf(InstrData& i, StringBuffer* str) {
|
||||||
const char* name;
|
const char* name;
|
||||||
switch (i.X.RT & 3) {
|
switch (i.X.RT & 3) {
|
||||||
case 0: name = "dcbf"; break;
|
case 0:
|
||||||
case 1: name = "dcbfl"; break;
|
name = "dcbf";
|
||||||
case 2: name = "dcbf.RESERVED"; break;
|
break;
|
||||||
case 3: name = "dcbflp"; break;
|
case 1:
|
||||||
|
name = "dcbfl";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
name = "dcbf.RESERVED";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
name = "dcbflp";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
str->Append("%-8s r%d, r%d", name, i.X.RA, i.X.RB);
|
str->Append("%-8s r%d, r%d", name, i.X.RA, i.X.RB);
|
||||||
}
|
}
|
||||||
|
@ -266,13 +259,12 @@ void Disasm_dcbz(InstrData& i, StringBuffer* str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disasm_fcmp(InstrData& i, StringBuffer* str) {
|
void Disasm_fcmp(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s cr%d, f%d, f%d", i.type->name,
|
str->Append("%-8s cr%d, f%d, f%d", i.type->name, i.X.RT >> 2, i.X.RA, i.X.RB);
|
||||||
i.X.RT >> 2, i.X.RA, i.X.RB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disasm_mffsx(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s f%d, FPSCR", i.X.Rc ? -7 : -8, i.type->name,
|
||||||
i.X.RT);
|
i.X.Rc ? "." : "", i.X.RT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disasm_bx(InstrData& i, StringBuffer* str) {
|
void Disasm_bx(InstrData& i, StringBuffer* str) {
|
||||||
|
@ -283,8 +275,7 @@ void Disasm_bx(InstrData& i, StringBuffer* str) {
|
||||||
} else {
|
} else {
|
||||||
nia = (uint32_t)(i.address + XEEXTS26(i.I.LI << 2));
|
nia = (uint32_t)(i.address + XEEXTS26(i.I.LI << 2));
|
||||||
}
|
}
|
||||||
str->Append("%-8s %.8X", name,
|
str->Append("%-8s %.8X", name, nia);
|
||||||
nia);
|
|
||||||
// TODO(benvanik): resolve target name?
|
// TODO(benvanik): resolve target name?
|
||||||
}
|
}
|
||||||
void Disasm_bcx(InstrData& i, StringBuffer* str) {
|
void Disasm_bcx(InstrData& i, StringBuffer* str) {
|
||||||
|
@ -295,7 +286,9 @@ void Disasm_bcx(InstrData& i, StringBuffer* str) {
|
||||||
} else {
|
} else {
|
||||||
s1 = "";
|
s1 = "";
|
||||||
}
|
}
|
||||||
char s2[8] = { 'c', 'r', 0, };
|
char s2[8] = {
|
||||||
|
'c', 'r', 0,
|
||||||
|
};
|
||||||
if (!XESELECTBITS(i.B.BO, 4, 4)) {
|
if (!XESELECTBITS(i.B.BO, 4, 4)) {
|
||||||
char* s2a = _itoa(i.B.BI >> 2, s2 + 2, 10);
|
char* s2a = _itoa(i.B.BI >> 2, s2 + 2, 10);
|
||||||
s2a += xestrlena(s2a);
|
s2a += xestrlena(s2a);
|
||||||
|
@ -310,14 +303,15 @@ void Disasm_bcx(InstrData& i, StringBuffer* str) {
|
||||||
} else {
|
} else {
|
||||||
nia = (uint32_t)(i.address + XEEXTS16(i.B.BD << 2));
|
nia = (uint32_t)(i.address + XEEXTS16(i.B.BD << 2));
|
||||||
}
|
}
|
||||||
str->Append("%-8s %s%s%s%.8X", i.type->name,
|
str->Append("%-8s %s%s%s%.8X", i.type->name, s0, s1, s2, nia);
|
||||||
s0, s1, s2, nia);
|
|
||||||
// TODO(benvanik): resolve target name?
|
// TODO(benvanik): resolve target name?
|
||||||
}
|
}
|
||||||
void Disasm_bcctrx(InstrData& i, StringBuffer* str) {
|
void Disasm_bcctrx(InstrData& i, StringBuffer* str) {
|
||||||
// TODO(benvanik): mnemonics
|
// TODO(benvanik): mnemonics
|
||||||
const char* s0 = i.XL.LK ? "lr, " : "";
|
const char* s0 = i.XL.LK ? "lr, " : "";
|
||||||
char s2[8] = { 'c', 'r', 0, };
|
char s2[8] = {
|
||||||
|
'c', 'r', 0,
|
||||||
|
};
|
||||||
if (!XESELECTBITS(i.XL.BO, 4, 4)) {
|
if (!XESELECTBITS(i.XL.BO, 4, 4)) {
|
||||||
char* s2a = _itoa(i.XL.BI >> 2, s2 + 2, 10);
|
char* s2a = _itoa(i.XL.BI >> 2, s2 + 2, 10);
|
||||||
s2a += xestrlena(s2a);
|
s2a += xestrlena(s2a);
|
||||||
|
@ -326,8 +320,7 @@ void Disasm_bcctrx(InstrData& i, StringBuffer* str) {
|
||||||
} else {
|
} else {
|
||||||
s2[0] = 0;
|
s2[0] = 0;
|
||||||
}
|
}
|
||||||
str->Append("%-8s %s%sctr", i.type->name,
|
str->Append("%-8s %s%sctr", i.type->name, s0, s2);
|
||||||
s0, s2);
|
|
||||||
// TODO(benvanik): resolve target name?
|
// TODO(benvanik): resolve target name?
|
||||||
}
|
}
|
||||||
void Disasm_bclrx(InstrData& i, StringBuffer* str) {
|
void Disasm_bclrx(InstrData& i, StringBuffer* str) {
|
||||||
|
@ -341,7 +334,9 @@ void Disasm_bclrx(InstrData& i, StringBuffer* str) {
|
||||||
} else {
|
} else {
|
||||||
s1 = "";
|
s1 = "";
|
||||||
}
|
}
|
||||||
char s2[8] = { 'c', 'r', 0, };
|
char s2[8] = {
|
||||||
|
'c', 'r', 0,
|
||||||
|
};
|
||||||
if (!XESELECTBITS(i.XL.BO, 4, 4)) {
|
if (!XESELECTBITS(i.XL.BO, 4, 4)) {
|
||||||
char* s2a = _itoa(i.XL.BI >> 2, s2 + 2, 10);
|
char* s2a = _itoa(i.XL.BI >> 2, s2 + 2, 10);
|
||||||
s2a += xestrlena(s2a);
|
s2a += xestrlena(s2a);
|
||||||
|
@ -350,179 +345,166 @@ void Disasm_bclrx(InstrData& i, StringBuffer* str) {
|
||||||
} else {
|
} else {
|
||||||
s2[0] = 0;
|
s2[0] = 0;
|
||||||
}
|
}
|
||||||
str->Append("%-8s %s%s", name,
|
str->Append("%-8s %s%s", name, s1, s2);
|
||||||
s1, s2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disasm_mfcr(InstrData& i, StringBuffer* str) {
|
void Disasm_mfcr(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s r%d, cr", i.type->name,
|
str->Append("%-8s r%d, cr", i.type->name, i.X.RT);
|
||||||
i.X.RT);
|
|
||||||
}
|
}
|
||||||
const char* Disasm_spr_name(uint32_t n) {
|
const char* Disasm_spr_name(uint32_t n) {
|
||||||
const char* reg = "???";
|
const char* reg = "???";
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1:
|
case 1:
|
||||||
reg = "xer";
|
reg = "xer";
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
reg = "lr";
|
reg = "lr";
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
reg = "ctr";
|
reg = "ctr";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
void Disasm_mfspr(InstrData& i, StringBuffer* str) {
|
void Disasm_mfspr(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
||||||
const char* reg = Disasm_spr_name(n);
|
const char* reg = Disasm_spr_name(n);
|
||||||
str->Append("%-8s r%d, %s", i.type->name,
|
str->Append("%-8s r%d, %s", i.type->name, i.XFX.RT, reg);
|
||||||
i.XFX.RT, reg);
|
|
||||||
}
|
}
|
||||||
void Disasm_mtspr(InstrData& i, StringBuffer* str) {
|
void Disasm_mtspr(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
||||||
const char* reg = Disasm_spr_name(n);
|
const char* reg = Disasm_spr_name(n);
|
||||||
str->Append("%-8s %s, r%d", i.type->name,
|
str->Append("%-8s %s, r%d", i.type->name, reg, i.XFX.RT);
|
||||||
reg, i.XFX.RT);
|
|
||||||
}
|
}
|
||||||
void Disasm_mftb(InstrData& i, StringBuffer* str) {
|
void Disasm_mftb(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s r%d, tb", i.type->name,
|
str->Append("%-8s r%d, tb", i.type->name, i.XFX.RT);
|
||||||
i.XFX.RT);
|
|
||||||
}
|
}
|
||||||
void Disasm_mfmsr(InstrData& i, StringBuffer* str) {
|
void Disasm_mfmsr(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s r%d", i.type->name,
|
str->Append("%-8s r%d", i.type->name, i.X.RT);
|
||||||
i.X.RT);
|
|
||||||
}
|
}
|
||||||
void Disasm_mtmsr(InstrData& i, StringBuffer* str) {
|
void Disasm_mtmsr(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s r%d, %d", i.type->name,
|
str->Append("%-8s r%d, %d", i.type->name, i.X.RT, (i.X.RA & 16) ? 1 : 0);
|
||||||
i.X.RT, (i.X.RA & 16) ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disasm_cmp(InstrData& i, StringBuffer* str) {
|
void Disasm_cmp(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s cr%d, %.2X, r%d, r%d", i.type->name,
|
str->Append("%-8s cr%d, %.2X, r%d, r%d", i.type->name, i.X.RT >> 2,
|
||||||
i.X.RT >> 2, i.X.RT & 1, i.X.RA, i.X.RB);
|
i.X.RT & 1, i.X.RA, i.X.RB);
|
||||||
}
|
}
|
||||||
void Disasm_cmpi(InstrData& i, StringBuffer* str) {
|
void Disasm_cmpi(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s cr%d, %.2X, r%d, %d", i.type->name,
|
str->Append("%-8s cr%d, %.2X, r%d, %d", i.type->name, i.D.RT >> 2, i.D.RT & 1,
|
||||||
i.D.RT >> 2, i.D.RT & 1, i.D.RA, XEEXTS16(i.D.DS));
|
i.D.RA, XEEXTS16(i.D.DS));
|
||||||
}
|
}
|
||||||
void Disasm_cmpli(InstrData& i, StringBuffer* str) {
|
void Disasm_cmpli(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s cr%d, %.2X, r%d, %.2X", i.type->name,
|
str->Append("%-8s cr%d, %.2X, r%d, %.2X", i.type->name, i.D.RT >> 2,
|
||||||
i.D.RT >> 2, i.D.RT & 1, i.D.RA, XEEXTS16(i.D.DS));
|
i.D.RT & 1, i.D.RA, XEEXTS16(i.D.DS));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disasm_rld(InstrData& i, StringBuffer* str) {
|
void Disasm_rld(InstrData& i, StringBuffer* str) {
|
||||||
if (i.MD.idx == 0) {
|
if (i.MD.idx == 0) {
|
||||||
// XEDISASMR(rldiclx, 0x78000000, MD )
|
// XEDISASMR(rldiclx, 0x78000000, MD )
|
||||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicl", i.MD.Rc ? "." : "",
|
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicl",
|
||||||
i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH, (i.MD.MB5 << 5) | i.MD.MB);
|
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH,
|
||||||
|
(i.MD.MB5 << 5) | i.MD.MB);
|
||||||
} else if (i.MD.idx == 1) {
|
} else if (i.MD.idx == 1) {
|
||||||
// XEDISASMR(rldicrx, 0x78000004, MD )
|
// XEDISASMR(rldicrx, 0x78000004, MD )
|
||||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicr", i.MD.Rc ? "." : "",
|
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicr",
|
||||||
i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH, (i.MD.MB5 << 5) | i.MD.MB);
|
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH,
|
||||||
|
(i.MD.MB5 << 5) | i.MD.MB);
|
||||||
} else if (i.MD.idx == 2) {
|
} else if (i.MD.idx == 2) {
|
||||||
// XEDISASMR(rldicx, 0x78000008, MD )
|
// XEDISASMR(rldicx, 0x78000008, MD )
|
||||||
uint32_t sh = (i.MD.SH5 << 5) | i.MD.SH;
|
uint32_t sh = (i.MD.SH5 << 5) | i.MD.SH;
|
||||||
uint32_t mb = (i.MD.MB5 << 5) | i.MD.MB;
|
uint32_t mb = (i.MD.MB5 << 5) | i.MD.MB;
|
||||||
const char* name = (mb == 0x3E) ? "sldi" : "rldic";
|
const char* name = (mb == 0x3E) ? "sldi" : "rldic";
|
||||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, name, i.MD.Rc ? "." : "",
|
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, name,
|
||||||
i.MD.RA, i.MD.RT, sh, mb);
|
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT, sh, mb);
|
||||||
} else if (i.MDS.idx == 8) {
|
} else if (i.MDS.idx == 8) {
|
||||||
// XEDISASMR(rldclx, 0x78000010, MDS)
|
// XEDISASMR(rldclx, 0x78000010, MDS)
|
||||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcl", i.MDS.Rc ? "." : "",
|
str->Append("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcl",
|
||||||
i.MDS.RA, i.MDS.RT, i.MDS.RB, (i.MDS.MB5 << 5) | i.MDS.MB);
|
i.MDS.Rc ? "." : "", i.MDS.RA, i.MDS.RT, i.MDS.RB,
|
||||||
|
(i.MDS.MB5 << 5) | i.MDS.MB);
|
||||||
} else if (i.MDS.idx == 9) {
|
} else if (i.MDS.idx == 9) {
|
||||||
// XEDISASMR(rldcrx, 0x78000012, MDS)
|
// XEDISASMR(rldcrx, 0x78000012, MDS)
|
||||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcr", i.MDS.Rc ? "." : "",
|
str->Append("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcr",
|
||||||
i.MDS.RA, i.MDS.RT, i.MDS.RB, (i.MDS.MB5 << 5) | i.MDS.MB);
|
i.MDS.Rc ? "." : "", i.MDS.RA, i.MDS.RT, i.MDS.RB,
|
||||||
|
(i.MDS.MB5 << 5) | i.MDS.MB);
|
||||||
} else if (i.MD.idx == 3) {
|
} else if (i.MD.idx == 3) {
|
||||||
// XEDISASMR(rldimix, 0x7800000C, MD )
|
// XEDISASMR(rldimix, 0x7800000C, MD )
|
||||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldimi", i.MD.Rc ? "." : "",
|
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldimi",
|
||||||
i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH, (i.MD.MB5 << 5) | i.MD.MB);
|
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH,
|
||||||
|
(i.MD.MB5 << 5) | i.MD.MB);
|
||||||
} else {
|
} else {
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Disasm_rlwim(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s r%d, r%d, %d, %d, %d", i.M.Rc ? -7 : -8, i.type->name,
|
||||||
i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
|
i.M.Rc ? "." : "", i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
|
||||||
}
|
}
|
||||||
void Disasm_rlwnmx(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s r%d, r%d, r%d, %d, %d", i.M.Rc ? -7 : -8, i.type->name,
|
||||||
i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
|
i.M.Rc ? "." : "", i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
|
||||||
}
|
}
|
||||||
void Disasm_srawix(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s r%d, r%d, %d", i.X.Rc ? -7 : -8, i.type->name,
|
||||||
i.X.RA, i.X.RT, i.X.RB);
|
i.X.Rc ? "." : "", i.X.RA, i.X.RT, i.X.RB);
|
||||||
}
|
}
|
||||||
void Disasm_sradix(InstrData& i, 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 ? "." : "",
|
str->Append("%*s%s r%d, r%d, %d", i.XS.Rc ? -7 : -8, i.type->name,
|
||||||
i.XS.RA, i.XS.RT, (i.XS.SH5 << 5) | i.XS.SH);
|
i.XS.Rc ? "." : "", i.XS.RA, i.XS.RT, (i.XS.SH5 << 5) | i.XS.SH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disasm_vpermwi128(InstrData& i, 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 vd = i.VX128_P.VD128l | (i.VX128_P.VD128h << 5);
|
||||||
const uint32_t vb = i.VX128_P.VB128l | (i.VX128_P.VB128h << 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,
|
str->Append("%-8s v%d, v%d, %.2X", i.type->name, vd, vb,
|
||||||
vd, vb, i.VX128_P.PERMl | (i.VX128_P.PERMh << 5));
|
i.VX128_P.PERMl | (i.VX128_P.PERMh << 5));
|
||||||
}
|
}
|
||||||
void Disasm_vrfin128(InstrData& i, StringBuffer* str) {
|
void Disasm_vrfin128(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t vd = VX128_3_VD128;
|
const uint32_t vd = VX128_3_VD128;
|
||||||
const uint32_t vb = VX128_3_VB128;
|
const uint32_t vb = VX128_3_VB128;
|
||||||
str->Append("%-8s v%d, v%d", i.type->name,
|
str->Append("%-8s v%d, v%d", i.type->name, vd, vb);
|
||||||
vd, vb);
|
|
||||||
}
|
}
|
||||||
void Disasm_vrlimi128(InstrData& i, StringBuffer* str) {
|
void Disasm_vrlimi128(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t vd = VX128_4_VD128;
|
const uint32_t vd = VX128_4_VD128;
|
||||||
const uint32_t vb = VX128_4_VB128;
|
const uint32_t vb = VX128_4_VB128;
|
||||||
str->Append("%-8s v%d, v%d, %.2X, %.2X", i.type->name,
|
str->Append("%-8s v%d, v%d, %.2X, %.2X", i.type->name, vd, vb, i.VX128_4.IMM,
|
||||||
vd, vb, i.VX128_4.IMM, i.VX128_4.z);
|
i.VX128_4.z);
|
||||||
}
|
}
|
||||||
void Disasm_vsldoi128(InstrData& i, StringBuffer* str) {
|
void Disasm_vsldoi128(InstrData& i, StringBuffer* str) {
|
||||||
const uint32_t vd = VX128_5_VD128;
|
const uint32_t vd = VX128_5_VD128;
|
||||||
const uint32_t va = VX128_5_VA128;
|
const uint32_t va = VX128_5_VA128;
|
||||||
const uint32_t vb = VX128_5_VB128;
|
const uint32_t vb = VX128_5_VB128;
|
||||||
const uint32_t sh = i.VX128_5.SH;
|
const uint32_t sh = i.VX128_5.SH;
|
||||||
str->Append("%-8s v%d, v%d, v%d, %.2X", i.type->name,
|
str->Append("%-8s v%d, v%d, v%d, %.2X", i.type->name, vd, va, vb, sh);
|
||||||
vd, va, vb, sh);
|
|
||||||
}
|
}
|
||||||
void Disasm_vspltb(InstrData& i, StringBuffer* str) {
|
void Disasm_vspltb(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name,
|
str->Append("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB,
|
||||||
i.VX.VD, i.VX.VB, i.VX.VA & 0xF);
|
i.VX.VA & 0xF);
|
||||||
}
|
}
|
||||||
void Disasm_vsplth(InstrData& i, StringBuffer* str) {
|
void Disasm_vsplth(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name,
|
str->Append("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB,
|
||||||
i.VX.VD, i.VX.VB, i.VX.VA & 0x7);
|
i.VX.VA & 0x7);
|
||||||
}
|
}
|
||||||
void Disasm_vspltw(InstrData& i, StringBuffer* str) {
|
void Disasm_vspltw(InstrData& i, StringBuffer* str) {
|
||||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name,
|
str->Append("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB, i.VX.VA);
|
||||||
i.VX.VD, i.VX.VB, i.VX.VA);
|
|
||||||
}
|
}
|
||||||
void Disasm_vspltisb(InstrData& i, StringBuffer* str) {
|
void Disasm_vspltisb(InstrData& i, StringBuffer* str) {
|
||||||
// 5bit -> 8bit sign extend
|
// 5bit -> 8bit sign extend
|
||||||
int8_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xF0) : i.VX.VA;
|
int8_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xF0) : i.VX.VA;
|
||||||
str->Append("%-8s v%d, %.2X", i.type->name,
|
str->Append("%-8s v%d, %.2X", i.type->name, i.VX.VD, simm);
|
||||||
i.VX.VD, simm);
|
|
||||||
}
|
}
|
||||||
void Disasm_vspltish(InstrData& i, StringBuffer* str) {
|
void Disasm_vspltish(InstrData& i, StringBuffer* str) {
|
||||||
// 5bit -> 16bit sign extend
|
// 5bit -> 16bit sign extend
|
||||||
int16_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFF0) : i.VX.VA;
|
int16_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFF0) : i.VX.VA;
|
||||||
str->Append("%-8s v%d, %.4X", i.type->name,
|
str->Append("%-8s v%d, %.4X", i.type->name, i.VX.VD, simm);
|
||||||
i.VX.VD, simm);
|
|
||||||
}
|
}
|
||||||
void Disasm_vspltisw(InstrData& i, StringBuffer* str) {
|
void Disasm_vspltisw(InstrData& i, StringBuffer* str) {
|
||||||
// 5bit -> 32bit sign extend
|
// 5bit -> 32bit sign extend
|
||||||
int32_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFFFFFF0) : i.VX.VA;
|
int32_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFFFFFF0) : i.VX.VA;
|
||||||
str->Append("%-8s v%d, %.8X", i.type->name,
|
str->Append("%-8s v%d, %.8X", i.type->name, i.VX.VD, simm);
|
||||||
i.VX.VD, simm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ppc
|
int DisasmPPC(InstrData& i, StringBuffer* str) {
|
||||||
} // namespace frontend
|
|
||||||
} // namespace alloy
|
|
||||||
|
|
||||||
|
|
||||||
int alloy::frontend::ppc::DisasmPPC(InstrData& i, StringBuffer* str) {
|
|
||||||
if (!i.type) {
|
if (!i.type) {
|
||||||
str->Append("???");
|
str->Append("???");
|
||||||
} else {
|
} else {
|
||||||
|
@ -531,3 +513,6 @@ int alloy::frontend::ppc::DisasmPPC(InstrData& i, StringBuffer* str) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ppc
|
||||||
|
} // namespace frontend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -12,18 +12,14 @@
|
||||||
|
|
||||||
#include <alloy/frontend/ppc/ppc_instr.h>
|
#include <alloy/frontend/ppc/ppc_instr.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
|
||||||
|
|
||||||
int DisasmPPC(InstrData& i, StringBuffer* str);
|
int DisasmPPC(InstrData& i, StringBuffer* str);
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_PPC_PPC_DISASM_H_
|
#endif // ALLOY_FRONTEND_PPC_PPC_DISASM_H_
|
||||||
|
|
|
@ -13,25 +13,21 @@
|
||||||
#include <alloy/frontend/ppc/ppc_emit.h>
|
#include <alloy/frontend/ppc/ppc_emit.h>
|
||||||
#include <alloy/frontend/ppc/ppc_instr.h>
|
#include <alloy/frontend/ppc/ppc_instr.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
|
||||||
|
|
||||||
#define XEEMITTER(name, opcode, format) int InstrEmit_##name
|
#define XEEMITTER(name, opcode, format) int InstrEmit_##name
|
||||||
|
|
||||||
#define XEREGISTERINSTR(name, opcode) \
|
#define XEREGISTERINSTR(name, opcode) \
|
||||||
RegisterInstrEmit(opcode, (InstrEmitFn)InstrEmit_##name);
|
RegisterInstrEmit(opcode, (InstrEmitFn)InstrEmit_##name);
|
||||||
|
|
||||||
#define XEINSTRNOTIMPLEMENTED()
|
#define XEINSTRNOTIMPLEMENTED()
|
||||||
//#define XEINSTRNOTIMPLEMENTED XEASSERTALWAYS
|
//#define XEINSTRNOTIMPLEMENTED XEASSERTALWAYS
|
||||||
//#define XEINSTRNOTIMPLEMENTED() __debugbreak()
|
//#define XEINSTRNOTIMPLEMENTED() __debugbreak()
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_PPC_PPC_EMIT_PRIVATE_H_
|
#endif // ALLOY_FRONTEND_PPC_PPC_EMIT_PRIVATE_H_
|
||||||
|
|
|
@ -12,22 +12,18 @@
|
||||||
|
|
||||||
#include <alloy/frontend/ppc/ppc_instr.h>
|
#include <alloy/frontend/ppc/ppc_instr.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
|
||||||
|
|
||||||
void RegisterEmitCategoryAltivec();
|
void RegisterEmitCategoryAltivec();
|
||||||
void RegisterEmitCategoryALU();
|
void RegisterEmitCategoryALU();
|
||||||
void RegisterEmitCategoryControl();
|
void RegisterEmitCategoryControl();
|
||||||
void RegisterEmitCategoryFPU();
|
void RegisterEmitCategoryFPU();
|
||||||
void RegisterEmitCategoryMemory();
|
void RegisterEmitCategoryMemory();
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_PPC_PPC_EMIT_H_
|
#endif // ALLOY_FRONTEND_PPC_PPC_EMIT_H_
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -12,21 +12,19 @@
|
||||||
#include <alloy/frontend/ppc/ppc_context.h>
|
#include <alloy/frontend/ppc/ppc_context.h>
|
||||||
#include <alloy/frontend/ppc/ppc_hir_builder.h>
|
#include <alloy/frontend/ppc/ppc_hir_builder.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace alloy::frontend::ppc;
|
|
||||||
using namespace alloy::hir;
|
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
|
using namespace alloy::hir;
|
||||||
|
|
||||||
int InstrEmit_branch(
|
using alloy::hir::Label;
|
||||||
PPCHIRBuilder& f, const char* src, uint64_t cia,
|
using alloy::hir::Value;
|
||||||
Value* nia, bool lk, Value* cond = NULL, bool expect_true = true,
|
|
||||||
bool nia_is_lr = false) {
|
int InstrEmit_branch(PPCHIRBuilder& f, const char* src, uint64_t cia,
|
||||||
|
Value* nia, bool lk, Value* cond = NULL,
|
||||||
|
bool expect_true = true, bool nia_is_lr = false) {
|
||||||
uint32_t call_flags = 0;
|
uint32_t call_flags = 0;
|
||||||
|
|
||||||
// TODO(benvanik): this may be wrong and overwrite LRs when not desired!
|
// TODO(benvanik): this may be wrong and overwrite LRs when not desired!
|
||||||
|
@ -54,8 +52,7 @@ int InstrEmit_branch(
|
||||||
// recursion.
|
// recursion.
|
||||||
uint64_t nia_value = nia->AsUint64() & 0xFFFFFFFF;
|
uint64_t nia_value = nia->AsUint64() & 0xFFFFFFFF;
|
||||||
bool is_recursion = false;
|
bool is_recursion = false;
|
||||||
if (nia_value == f.symbol_info()->address() &&
|
if (nia_value == f.symbol_info()->address() && lk) {
|
||||||
lk) {
|
|
||||||
is_recursion = true;
|
is_recursion = true;
|
||||||
}
|
}
|
||||||
Label* label = is_recursion ? NULL : f.LookupLabel(nia_value);
|
Label* label = is_recursion ? NULL : f.LookupLabel(nia_value);
|
||||||
|
@ -73,7 +70,7 @@ int InstrEmit_branch(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Call function.
|
// Call function.
|
||||||
FunctionInfo* symbol_info = f.LookupFunction(nia_value);
|
auto symbol_info = f.LookupFunction(nia_value);
|
||||||
if (cond) {
|
if (cond) {
|
||||||
if (!expect_true) {
|
if (!expect_true) {
|
||||||
cond = f.IsFalse(cond);
|
cond = f.IsFalse(cond);
|
||||||
|
@ -84,27 +81,27 @@ int InstrEmit_branch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Indirect branch to pointer.
|
// Indirect branch to pointer.
|
||||||
|
|
||||||
// TODO(benvanik): runtime recursion detection?
|
// TODO(benvanik): runtime recursion detection?
|
||||||
|
|
||||||
// TODO(benvanik): run a DFA pass to see if we can detect whether this is
|
// TODO(benvanik): run a DFA pass to see if we can detect whether this is
|
||||||
// a normal function return that is pulling the LR from the stack that
|
// a normal function return that is pulling the LR from the stack that
|
||||||
// it set in the prolog. If so, we can omit the dynamic check!
|
// it set in the prolog. If so, we can omit the dynamic check!
|
||||||
|
|
||||||
//// Dynamic test when branching to LR, which is usually used for the return.
|
//// Dynamic test when branching to LR, which is usually used for the return.
|
||||||
//// We only do this if LK=0 as returns wouldn't set LR.
|
//// We only do this if LK=0 as returns wouldn't set LR.
|
||||||
//// Ideally it's a return and we can just do a simple ret and be done.
|
//// Ideally it's a return and we can just do a simple ret and be done.
|
||||||
//// If it's not, we fall through to the full indirection logic.
|
//// If it's not, we fall through to the full indirection logic.
|
||||||
//if (!lk && reg == kXEPPCRegLR) {
|
// if (!lk && reg == kXEPPCRegLR) {
|
||||||
// // The return block will spill registers for us.
|
// // The return block will spill registers for us.
|
||||||
// // TODO(benvanik): 'lr_mismatch' debug info.
|
// // TODO(benvanik): 'lr_mismatch' debug info.
|
||||||
// // Note: we need to test on *only* the 32-bit target, as the target ptr may
|
// // Note: we need to test on *only* the 32-bit target, as the target ptr may
|
||||||
// // have garbage in the upper 32 bits.
|
// // have garbage in the upper 32 bits.
|
||||||
// c.cmp(target.r32(), c.getGpArg(1).r32());
|
// c.cmp(target.r32(), c.getGpArg(1).r32());
|
||||||
// // TODO(benvanik): evaluate hint here.
|
// // TODO(benvanik): evaluate hint here.
|
||||||
// c.je(e.GetReturnLabel(), kCondHintLikely);
|
// c.je(e.GetReturnLabel(), kCondHintLikely);
|
||||||
//}
|
//}
|
||||||
#if 0
|
#if 0
|
||||||
// This breaks longjump, as that uses blr with a non-return lr.
|
// This breaks longjump, as that uses blr with a non-return lr.
|
||||||
// It'd be nice to move SET_RETURN_ADDRESS semantics up into context
|
// It'd be nice to move SET_RETURN_ADDRESS semantics up into context
|
||||||
|
@ -124,27 +121,26 @@ int InstrEmit_branch(
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
// Jump to pointer.
|
// Jump to pointer.
|
||||||
bool likely_return = !lk && nia_is_lr;
|
bool likely_return = !lk && nia_is_lr;
|
||||||
if (likely_return) {
|
if (likely_return) {
|
||||||
call_flags |= CALL_POSSIBLE_RETURN;
|
call_flags |= CALL_POSSIBLE_RETURN;
|
||||||
}
|
}
|
||||||
if (cond) {
|
if (cond) {
|
||||||
if (!expect_true) {
|
if (!expect_true) {
|
||||||
cond = f.IsFalse(cond);
|
cond = f.IsFalse(cond);
|
||||||
}
|
|
||||||
f.CallIndirectTrue(cond, nia, call_flags);
|
|
||||||
} else {
|
|
||||||
f.CallIndirect(nia, call_flags);
|
|
||||||
}
|
}
|
||||||
|
f.CallIndirectTrue(cond, nia, call_flags);
|
||||||
|
} else {
|
||||||
|
f.CallIndirect(nia, call_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
XEEMITTER(bx, 0x48000000, I )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(bx, 0x48000000, I)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if AA then
|
// if AA then
|
||||||
// NIA <- EXTS(LI || 0b00)
|
// NIA <- EXTS(LI || 0b00)
|
||||||
// else
|
// else
|
||||||
|
@ -159,11 +155,10 @@ XEEMITTER(bx, 0x48000000, I )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
nia = (uint32_t)(i.address + XEEXTS26(i.I.LI << 2));
|
nia = (uint32_t)(i.address + XEEXTS26(i.I.LI << 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
return InstrEmit_branch(
|
return InstrEmit_branch(f, "bx", i.address, f.LoadConstant(nia), i.I.LK);
|
||||||
f, "bx", i.address, f.LoadConstant(nia), i.I.LK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(bcx, 0x40000000, B )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(bcx, 0x40000000, B)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if ¬BO[2] then
|
// if ¬BO[2] then
|
||||||
// CTR <- CTR - 1
|
// CTR <- CTR - 1
|
||||||
// ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3])
|
// ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3])
|
||||||
|
@ -236,11 +231,11 @@ XEEMITTER(bcx, 0x40000000, B )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
} else {
|
} else {
|
||||||
nia = (uint32_t)(i.address + XEEXTS16(i.B.BD << 2));
|
nia = (uint32_t)(i.address + XEEXTS16(i.B.BD << 2));
|
||||||
}
|
}
|
||||||
return InstrEmit_branch(
|
return InstrEmit_branch(f, "bcx", i.address, f.LoadConstant(nia), i.B.LK, ok,
|
||||||
f, "bcx", i.address, f.LoadConstant(nia), i.B.LK, ok, expect_true);
|
expect_true);
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(bcctrx, 0x4C000420, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(bcctrx, 0x4C000420, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1])
|
// cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1])
|
||||||
// if cond_ok then
|
// if cond_ok then
|
||||||
// NIA <- CTR[0:61] || 0b00
|
// NIA <- CTR[0:61] || 0b00
|
||||||
|
@ -268,11 +263,11 @@ XEEMITTER(bcctrx, 0x4C000420, XL )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool expect_true = !not_cond_ok;
|
bool expect_true = !not_cond_ok;
|
||||||
return InstrEmit_branch(
|
return InstrEmit_branch(f, "bcctrx", i.address, f.LoadCTR(), i.XL.LK, cond_ok,
|
||||||
f, "bcctrx", i.address, f.LoadCTR(), i.XL.LK, cond_ok, expect_true);
|
expect_true);
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(bclrx, 0x4C000020, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(bclrx, 0x4C000020, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if ¬BO[2] then
|
// if ¬BO[2] then
|
||||||
// CTR <- CTR - 1
|
// CTR <- CTR - 1
|
||||||
// ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3]
|
// ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3]
|
||||||
|
@ -336,71 +331,68 @@ XEEMITTER(bclrx, 0x4C000020, XL )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
expect_true = !not_cond_ok;
|
expect_true = !not_cond_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
return InstrEmit_branch(
|
return InstrEmit_branch(f, "bclrx", i.address, f.LoadLR(), i.XL.LK, ok,
|
||||||
f, "bclrx", i.address, f.LoadLR(), i.XL.LK, ok, expect_true, true);
|
expect_true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Condition register logical (A-23)
|
// Condition register logical (A-23)
|
||||||
|
|
||||||
XEEMITTER(crand, 0x4C000202, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(crand, 0x4C000202, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(crandc, 0x4C000102, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(crandc, 0x4C000102, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(creqv, 0x4C000242, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(creqv, 0x4C000242, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(crnand, 0x4C0001C2, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(crnand, 0x4C0001C2, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(crnor, 0x4C000042, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(crnor, 0x4C000042, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(cror, 0x4C000382, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(cror, 0x4C000382, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(crorc, 0x4C000342, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(crorc, 0x4C000342, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(crxor, 0x4C000182, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(crxor, 0x4C000182, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mcrf, 0x4C000000, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mcrf, 0x4C000000, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// System linkage (A-24)
|
// System linkage (A-24)
|
||||||
|
|
||||||
XEEMITTER(sc, 0x44000002, SC )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(sc, 0x44000002, SC)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
f.CallExtern(f.symbol_info());
|
f.CallExtern(f.symbol_info());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Trap (A-25)
|
// Trap (A-25)
|
||||||
|
|
||||||
int InstrEmit_trap(PPCHIRBuilder& f, InstrData& i,
|
int InstrEmit_trap(PPCHIRBuilder& f, InstrData& i, Value* va, Value* vb,
|
||||||
Value* va, Value* vb, uint32_t TO) {
|
uint32_t TO) {
|
||||||
// if (a < b) & TO[0] then TRAP
|
// if (a < b) & TO[0] then TRAP
|
||||||
// if (a > b) & TO[1] then TRAP
|
// if (a > b) & TO[1] then TRAP
|
||||||
// if (a = b) & TO[2] then TRAP
|
// if (a = b) & TO[2] then TRAP
|
||||||
|
@ -435,7 +427,7 @@ int InstrEmit_trap(PPCHIRBuilder& f, InstrData& i,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(td, 0x7C000088, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(td, 0x7C000088, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// a <- (RA)
|
// a <- (RA)
|
||||||
// b <- (RB)
|
// b <- (RB)
|
||||||
// if (a < b) & TO[0] then TRAP
|
// if (a < b) & TO[0] then TRAP
|
||||||
|
@ -448,7 +440,7 @@ XEEMITTER(td, 0x7C000088, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return InstrEmit_trap(f, i, ra, rb, i.X.RT);
|
return InstrEmit_trap(f, i, ra, rb, i.X.RT);
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(tdi, 0x08000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(tdi, 0x08000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// a <- (RA)
|
// a <- (RA)
|
||||||
// if (a < EXTS(SI)) & TO[0] then TRAP
|
// if (a < EXTS(SI)) & TO[0] then TRAP
|
||||||
// if (a > EXTS(SI)) & TO[1] then TRAP
|
// if (a > EXTS(SI)) & TO[1] then TRAP
|
||||||
|
@ -460,7 +452,7 @@ XEEMITTER(tdi, 0x08000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return InstrEmit_trap(f, i, ra, rb, i.D.RT);
|
return InstrEmit_trap(f, i, ra, rb, i.D.RT);
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(tw, 0x7C000008, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(tw, 0x7C000008, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// a <- EXTS((RA)[32:63])
|
// a <- EXTS((RA)[32:63])
|
||||||
// b <- EXTS((RB)[32:63])
|
// b <- EXTS((RB)[32:63])
|
||||||
// if (a < b) & TO[0] then TRAP
|
// if (a < b) & TO[0] then TRAP
|
||||||
|
@ -468,14 +460,14 @@ XEEMITTER(tw, 0x7C000008, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if (a = b) & TO[2] then TRAP
|
// if (a = b) & TO[2] then TRAP
|
||||||
// if (a <u b) & TO[3] then TRAP
|
// if (a <u b) & TO[3] then TRAP
|
||||||
// if (a >u b) & TO[4] then TRAP
|
// if (a >u b) & TO[4] then TRAP
|
||||||
Value* ra = f.SignExtend(f.Truncate(
|
Value* ra =
|
||||||
f.LoadGPR(i.X.RA), INT32_TYPE), INT64_TYPE);
|
f.SignExtend(f.Truncate(f.LoadGPR(i.X.RA), INT32_TYPE), INT64_TYPE);
|
||||||
Value* rb = f.SignExtend(f.Truncate(
|
Value* rb =
|
||||||
f.LoadGPR(i.X.RB), INT32_TYPE), INT64_TYPE);
|
f.SignExtend(f.Truncate(f.LoadGPR(i.X.RB), INT32_TYPE), INT64_TYPE);
|
||||||
return InstrEmit_trap(f, i, ra, rb, i.X.RT);
|
return InstrEmit_trap(f, i, ra, rb, i.X.RT);
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(twi, 0x0C000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(twi, 0x0C000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// a <- EXTS((RA)[32:63])
|
// a <- EXTS((RA)[32:63])
|
||||||
// if (a < EXTS(SI)) & TO[0] then TRAP
|
// if (a < EXTS(SI)) & TO[0] then TRAP
|
||||||
// if (a > EXTS(SI)) & TO[1] then TRAP
|
// if (a > EXTS(SI)) & TO[1] then TRAP
|
||||||
|
@ -488,21 +480,20 @@ XEEMITTER(twi, 0x0C000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
f.Trap(type);
|
f.Trap(type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Value* ra = f.SignExtend(f.Truncate(
|
Value* ra =
|
||||||
f.LoadGPR(i.D.RA), INT32_TYPE), INT64_TYPE);
|
f.SignExtend(f.Truncate(f.LoadGPR(i.D.RA), INT32_TYPE), INT64_TYPE);
|
||||||
Value* rb = f.LoadConstant(XEEXTS16(i.D.DS));
|
Value* rb = f.LoadConstant(XEEXTS16(i.D.DS));
|
||||||
return InstrEmit_trap(f, i, ra, rb, i.D.RT);
|
return InstrEmit_trap(f, i, ra, rb, i.D.RT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Processor control (A-26)
|
// Processor control (A-26)
|
||||||
|
|
||||||
XEEMITTER(mfcr, 0x7C000026, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mfcr, 0x7C000026, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mfspr, 0x7C0002A6, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mfspr, 0x7C0002A6, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// n <- spr[5:9] || spr[0:4]
|
// n <- spr[5:9] || spr[0:4]
|
||||||
// if length(SPR(n)) = 64 then
|
// if length(SPR(n)) = 64 then
|
||||||
// RT <- SPR(n)
|
// RT <- SPR(n)
|
||||||
|
@ -511,40 +502,40 @@ XEEMITTER(mfspr, 0x7C0002A6, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
Value* v;
|
Value* v;
|
||||||
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1:
|
case 1:
|
||||||
// XER
|
// XER
|
||||||
v = f.LoadXER();
|
v = f.LoadXER();
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
// LR
|
// LR
|
||||||
v = f.LoadLR();
|
v = f.LoadLR();
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
// CTR
|
// CTR
|
||||||
v = f.LoadCTR();
|
v = f.LoadCTR();
|
||||||
break;
|
break;
|
||||||
// 268 + 269 = TB + TBU
|
// 268 + 269 = TB + TBU
|
||||||
default:
|
default:
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
f.StoreGPR(i.XFX.RT, v);
|
f.StoreGPR(i.XFX.RT, v);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mftb, 0x7C0002E6, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mftb, 0x7C0002E6, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
Value* time = f.LoadClock();
|
Value* time = f.LoadClock();
|
||||||
f.StoreGPR(i.XFX.RT, time);
|
f.StoreGPR(i.XFX.RT, time);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mtcrf, 0x7C000120, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mtcrf, 0x7C000120, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mtspr, 0x7C0003A6, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mtspr, 0x7C0003A6, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// n <- spr[5:9] || spr[0:4]
|
// n <- spr[5:9] || spr[0:4]
|
||||||
// if length(SPR(n)) = 64 then
|
// if length(SPR(n)) = 64 then
|
||||||
// SPR(n) <- (RS)
|
// SPR(n) <- (RS)
|
||||||
|
@ -555,21 +546,21 @@ XEEMITTER(mtspr, 0x7C0003A6, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
|
|
||||||
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1:
|
case 1:
|
||||||
// XER
|
// XER
|
||||||
f.StoreXER(rt);
|
f.StoreXER(rt);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
// LR
|
// LR
|
||||||
f.StoreLR(rt);
|
f.StoreLR(rt);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
// CTR
|
// CTR
|
||||||
f.StoreCTR(rt);
|
f.StoreCTR(rt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -578,52 +569,50 @@ XEEMITTER(mtspr, 0x7C0003A6, XFX)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// TODO(benvanik): MSR is used for toggling interrupts, and it'd be nice to
|
// TODO(benvanik): MSR is used for toggling interrupts, and it'd be nice to
|
||||||
// obey that setting. It's usually guarding atomic stores.
|
// obey that setting. It's usually guarding atomic stores.
|
||||||
|
|
||||||
XEEMITTER(mfmsr, 0x7C0000A6, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mfmsr, 0x7C0000A6, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
f.Nop();
|
f.Nop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mtmsr, 0x7C000124, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mtmsr, 0x7C000124, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
f.Nop();
|
f.Nop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mtmsrd, 0x7C000164, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mtmsrd, 0x7C000164, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
f.Nop();
|
f.Nop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegisterEmitCategoryControl() {
|
void RegisterEmitCategoryControl() {
|
||||||
XEREGISTERINSTR(bx, 0x48000000);
|
XEREGISTERINSTR(bx, 0x48000000);
|
||||||
XEREGISTERINSTR(bcx, 0x40000000);
|
XEREGISTERINSTR(bcx, 0x40000000);
|
||||||
XEREGISTERINSTR(bcctrx, 0x4C000420);
|
XEREGISTERINSTR(bcctrx, 0x4C000420);
|
||||||
XEREGISTERINSTR(bclrx, 0x4C000020);
|
XEREGISTERINSTR(bclrx, 0x4C000020);
|
||||||
XEREGISTERINSTR(crand, 0x4C000202);
|
XEREGISTERINSTR(crand, 0x4C000202);
|
||||||
XEREGISTERINSTR(crandc, 0x4C000102);
|
XEREGISTERINSTR(crandc, 0x4C000102);
|
||||||
XEREGISTERINSTR(creqv, 0x4C000242);
|
XEREGISTERINSTR(creqv, 0x4C000242);
|
||||||
XEREGISTERINSTR(crnand, 0x4C0001C2);
|
XEREGISTERINSTR(crnand, 0x4C0001C2);
|
||||||
XEREGISTERINSTR(crnor, 0x4C000042);
|
XEREGISTERINSTR(crnor, 0x4C000042);
|
||||||
XEREGISTERINSTR(cror, 0x4C000382);
|
XEREGISTERINSTR(cror, 0x4C000382);
|
||||||
XEREGISTERINSTR(crorc, 0x4C000342);
|
XEREGISTERINSTR(crorc, 0x4C000342);
|
||||||
XEREGISTERINSTR(crxor, 0x4C000182);
|
XEREGISTERINSTR(crxor, 0x4C000182);
|
||||||
XEREGISTERINSTR(mcrf, 0x4C000000);
|
XEREGISTERINSTR(mcrf, 0x4C000000);
|
||||||
XEREGISTERINSTR(sc, 0x44000002);
|
XEREGISTERINSTR(sc, 0x44000002);
|
||||||
XEREGISTERINSTR(td, 0x7C000088);
|
XEREGISTERINSTR(td, 0x7C000088);
|
||||||
XEREGISTERINSTR(tdi, 0x08000000);
|
XEREGISTERINSTR(tdi, 0x08000000);
|
||||||
XEREGISTERINSTR(tw, 0x7C000008);
|
XEREGISTERINSTR(tw, 0x7C000008);
|
||||||
XEREGISTERINSTR(twi, 0x0C000000);
|
XEREGISTERINSTR(twi, 0x0C000000);
|
||||||
XEREGISTERINSTR(mfcr, 0x7C000026);
|
XEREGISTERINSTR(mfcr, 0x7C000026);
|
||||||
XEREGISTERINSTR(mfspr, 0x7C0002A6);
|
XEREGISTERINSTR(mfspr, 0x7C0002A6);
|
||||||
XEREGISTERINSTR(mftb, 0x7C0002E6);
|
XEREGISTERINSTR(mftb, 0x7C0002E6);
|
||||||
XEREGISTERINSTR(mtcrf, 0x7C000120);
|
XEREGISTERINSTR(mtcrf, 0x7C000120);
|
||||||
XEREGISTERINSTR(mtspr, 0x7C0003A6);
|
XEREGISTERINSTR(mtspr, 0x7C0003A6);
|
||||||
XEREGISTERINSTR(mfmsr, 0x7C0000A6);
|
XEREGISTERINSTR(mfmsr, 0x7C0000A6);
|
||||||
XEREGISTERINSTR(mtmsr, 0x7C000124);
|
XEREGISTERINSTR(mtmsr, 0x7C000124);
|
||||||
XEREGISTERINSTR(mtmsrd, 0x7C000164);
|
XEREGISTERINSTR(mtmsrd, 0x7C000164);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
|
@ -12,148 +12,145 @@
|
||||||
#include <alloy/frontend/ppc/ppc_context.h>
|
#include <alloy/frontend/ppc/ppc_context.h>
|
||||||
#include <alloy/frontend/ppc/ppc_hir_builder.h>
|
#include <alloy/frontend/ppc/ppc_hir_builder.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace alloy::frontend::ppc;
|
|
||||||
using namespace alloy::hir;
|
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
|
using namespace alloy::hir;
|
||||||
|
|
||||||
|
using alloy::hir::RoundMode;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
// Good source of information:
|
// Good source of information:
|
||||||
// http://mamedev.org/source/src/emu/cpu/powerpc/ppc_ops.c
|
// http://mamedev.org/source/src/emu/cpu/powerpc/ppc_ops.c
|
||||||
// The correctness of that code is not reflected here yet -_-
|
// The correctness of that code is not reflected here yet -_-
|
||||||
|
|
||||||
|
|
||||||
// Enable rounding numbers to single precision as required.
|
// Enable rounding numbers to single precision as required.
|
||||||
// This adds a bunch of work per operation and I'm not sure it's required.
|
// This adds a bunch of work per operation and I'm not sure it's required.
|
||||||
#define ROUND_TO_SINGLE
|
#define ROUND_TO_SINGLE
|
||||||
|
|
||||||
|
|
||||||
// Floating-point arithmetic (A-8)
|
// Floating-point arithmetic (A-8)
|
||||||
|
|
||||||
XEEMITTER(faddx, 0xFC00002A, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(faddx, 0xFC00002A, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA) + (frB)
|
// frD <- (frA) + (frB)
|
||||||
Value* v = f.Add(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
Value* v = f.Add(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(faddsx, 0xEC00002A, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(faddsx, 0xEC00002A, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA) + (frB)
|
// frD <- (frA) + (frB)
|
||||||
Value* v = f.Add(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
Value* v = f.Add(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
||||||
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fdivx, 0xFC000024, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fdivx, 0xFC000024, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- frA / frB
|
// frD <- frA / frB
|
||||||
Value* v = f.Div(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
Value* v = f.Div(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fdivsx, 0xEC000024, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fdivsx, 0xEC000024, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- frA / frB
|
// frD <- frA / frB
|
||||||
Value* v = f.Div(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
Value* v = f.Div(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
||||||
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fmulx, 0xFC000032, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fmulx, 0xFC000032, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA) x (frC)
|
// frD <- (frA) x (frC)
|
||||||
Value* v = f.Mul(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC));
|
Value* v = f.Mul(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC));
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fmulsx, 0xEC000032, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fmulsx, 0xEC000032, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA) x (frC)
|
// frD <- (frA) x (frC)
|
||||||
Value* v = f.Mul(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC));
|
Value* v = f.Mul(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC));
|
||||||
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fresx, 0xEC000030, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fresx, 0xEC000030, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(frsqrtex, 0xFC000034, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(frsqrtex, 0xFC000034, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fsubx, 0xFC000028, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fsubx, 0xFC000028, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA) - (frB)
|
// frD <- (frA) - (frB)
|
||||||
Value* v = f.Sub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
Value* v = f.Sub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fsubsx, 0xEC000028, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fsubsx, 0xEC000028, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA) - (frB)
|
// frD <- (frA) - (frB)
|
||||||
Value* v = f.Sub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
Value* v = f.Sub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
|
||||||
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fselx, 0xFC00002E, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fselx, 0xFC00002E, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if (frA) >= 0.0
|
// if (frA) >= 0.0
|
||||||
// then frD <- (frC)
|
// then frD <- (frC)
|
||||||
// else frD <- (frB)
|
// else frD <- (frB)
|
||||||
|
@ -161,28 +158,28 @@ XEEMITTER(fselx, 0xFC00002E, A )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
Value* v = f.Select(ge, f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
|
Value* v = f.Select(ge, f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fsqrtx, 0xFC00002C, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fsqrtx, 0xFC00002C, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// Double precision:
|
// Double precision:
|
||||||
// frD <- sqrt(frB)
|
// frD <- sqrt(frB)
|
||||||
Value* v = f.Sqrt(f.LoadFPR(i.A.FRA));
|
Value* v = f.Sqrt(f.LoadFPR(i.A.FRA));
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fsqrtsx, 0xEC00002C, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fsqrtsx, 0xEC00002C, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// Single precision:
|
// Single precision:
|
||||||
// frD <- sqrt(frB)
|
// frD <- sqrt(frB)
|
||||||
Value* v = f.Sqrt(f.LoadFPR(i.A.FRA));
|
Value* v = f.Sqrt(f.LoadFPR(i.A.FRA));
|
||||||
|
@ -190,144 +187,128 @@ XEEMITTER(fsqrtsx, 0xEC00002C, A )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Floating-point multiply-add (A-9)
|
// Floating-point multiply-add (A-9)
|
||||||
|
|
||||||
XEEMITTER(fmaddx, 0xFC00003A, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fmaddx, 0xFC00003A, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA x frC) + frB
|
// frD <- (frA x frC) + frB
|
||||||
Value* v = f.MulAdd(
|
Value* v =
|
||||||
f.LoadFPR(i.A.FRA),
|
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
|
||||||
f.LoadFPR(i.A.FRC),
|
|
||||||
f.LoadFPR(i.A.FRB));
|
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fmaddsx, 0xEC00003A, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fmaddsx, 0xEC00003A, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA x frC) + frB
|
// frD <- (frA x frC) + frB
|
||||||
Value* v = f.MulAdd(
|
Value* v =
|
||||||
f.LoadFPR(i.A.FRA),
|
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
|
||||||
f.LoadFPR(i.A.FRC),
|
|
||||||
f.LoadFPR(i.A.FRB));
|
|
||||||
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fmsubx, 0xFC000038, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fmsubx, 0xFC000038, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA x frC) - frB
|
// frD <- (frA x frC) - frB
|
||||||
Value* v = f.MulSub(
|
Value* v =
|
||||||
f.LoadFPR(i.A.FRA),
|
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
|
||||||
f.LoadFPR(i.A.FRC),
|
|
||||||
f.LoadFPR(i.A.FRB));
|
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fmsubsx, 0xEC000038, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fmsubsx, 0xEC000038, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frA x frC) - frB
|
// frD <- (frA x frC) - frB
|
||||||
Value* v = f.MulSub(
|
Value* v =
|
||||||
f.LoadFPR(i.A.FRA),
|
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
|
||||||
f.LoadFPR(i.A.FRC),
|
|
||||||
f.LoadFPR(i.A.FRB));
|
|
||||||
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fnmaddx, 0xFC00003E, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fnmaddx, 0xFC00003E, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fnmaddsx, 0xEC00003E, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fnmaddsx, 0xEC00003E, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fnmsubx, 0xFC00003C, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fnmsubx, 0xFC00003C, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- -([frA x frC] - frB)
|
// frD <- -([frA x frC] - frB)
|
||||||
Value* v = f.Neg(f.MulSub(
|
Value* v = f.Neg(
|
||||||
f.LoadFPR(i.A.FRA),
|
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
|
||||||
f.LoadFPR(i.A.FRC),
|
|
||||||
f.LoadFPR(i.A.FRB)));
|
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fnmsubsx, 0xEC00003C, A )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fnmsubsx, 0xEC00003C, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- -([frA x frC] - frB)
|
// frD <- -([frA x frC] - frB)
|
||||||
Value* v = f.Neg(f.MulSub(
|
Value* v = f.Neg(
|
||||||
f.LoadFPR(i.A.FRA),
|
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
|
||||||
f.LoadFPR(i.A.FRC),
|
|
||||||
f.LoadFPR(i.A.FRB)));
|
|
||||||
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Floating-point rounding and conversion (A-10)
|
// Floating-point rounding and conversion (A-10)
|
||||||
|
|
||||||
XEEMITTER(fcfidx, 0xFC00069C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fcfidx, 0xFC00069C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- signed_int64_to_double( frB )
|
// frD <- signed_int64_to_double( frB )
|
||||||
Value* v = f.Convert(
|
Value* v = f.Convert(f.Cast(f.LoadFPR(i.A.FRB), INT64_TYPE), FLOAT64_TYPE);
|
||||||
f.Cast(f.LoadFPR(i.A.FRB), INT64_TYPE),
|
|
||||||
FLOAT64_TYPE);
|
|
||||||
f.StoreFPR(i.A.FRT, v);
|
f.StoreFPR(i.A.FRT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fctidx, 0xFC00065C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fctidx, 0xFC00065C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- double_to_signed_int64( frB )
|
// frD <- double_to_signed_int64( frB )
|
||||||
// TODO(benvanik): pull from FPSCR[RN]
|
// TODO(benvanik): pull from FPSCR[RN]
|
||||||
RoundMode round_mode = ROUND_TO_ZERO;
|
RoundMode round_mode = ROUND_TO_ZERO;
|
||||||
|
@ -336,19 +317,19 @@ XEEMITTER(fctidx, 0xFC00065C, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
f.StoreFPR(i.X.RT, v);
|
f.StoreFPR(i.X.RT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.X.Rc) {
|
if (i.X.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fctidzx, 0xFC00065E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fctidzx, 0xFC00065E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// TODO(benvanik): assuming round to zero is always set, is that ok?
|
// TODO(benvanik): assuming round to zero is always set, is that ok?
|
||||||
return InstrEmit_fctidx(f, i);
|
return InstrEmit_fctidx(f, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fctiwx, 0xFC00001C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fctiwx, 0xFC00001C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- double_to_signed_int32( frB )
|
// frD <- double_to_signed_int32( frB )
|
||||||
// TODO(benvanik): pull from FPSCR[RN]
|
// TODO(benvanik): pull from FPSCR[RN]
|
||||||
RoundMode round_mode = ROUND_TO_ZERO;
|
RoundMode round_mode = ROUND_TO_ZERO;
|
||||||
|
@ -357,19 +338,19 @@ XEEMITTER(fctiwx, 0xFC00001C, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
f.StoreFPR(i.X.RT, v);
|
f.StoreFPR(i.X.RT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.A.Rc) {
|
if (i.A.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fctiwzx, 0xFC00001E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fctiwzx, 0xFC00001E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// TODO(benvanik): assuming round to zero is always set, is that ok?
|
// TODO(benvanik): assuming round to zero is always set, is that ok?
|
||||||
return InstrEmit_fctiwx(f, i);
|
return InstrEmit_fctiwx(f, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(frspx, 0xFC000018, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(frspx, 0xFC000018, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- Round_single(frB)
|
// frD <- Round_single(frB)
|
||||||
// TODO(benvanik): pull from FPSCR[RN]
|
// TODO(benvanik): pull from FPSCR[RN]
|
||||||
RoundMode round_mode = ROUND_TO_ZERO;
|
RoundMode round_mode = ROUND_TO_ZERO;
|
||||||
|
@ -378,14 +359,13 @@ XEEMITTER(frspx, 0xFC000018, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
f.StoreFPR(i.X.RT, v);
|
f.StoreFPR(i.X.RT, v);
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
if (i.X.Rc) {
|
if (i.X.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Floating-point compare (A-11)
|
// Floating-point compare (A-11)
|
||||||
|
|
||||||
int InstrEmit_fcmpx_(PPCHIRBuilder& f, InstrData& i, bool ordered) {
|
int InstrEmit_fcmpx_(PPCHIRBuilder& f, InstrData& i, bool ordered) {
|
||||||
|
@ -410,22 +390,21 @@ int InstrEmit_fcmpx_(PPCHIRBuilder& f, InstrData& i, bool ordered) {
|
||||||
f.UpdateCR(crf, f.LoadFPR(i.X.RA), f.LoadFPR(i.X.RB), false);
|
f.UpdateCR(crf, f.LoadFPR(i.X.RA), f.LoadFPR(i.X.RB), false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
XEEMITTER(fcmpo, 0xFC000040, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fcmpo, 0xFC000040, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return InstrEmit_fcmpx_(f, i, true);
|
return InstrEmit_fcmpx_(f, i, true);
|
||||||
}
|
}
|
||||||
XEEMITTER(fcmpu, 0xFC000000, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fcmpu, 0xFC000000, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return InstrEmit_fcmpx_(f, i, false);
|
return InstrEmit_fcmpx_(f, i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Floating-point status and control register (A
|
// Floating-point status and control register (A
|
||||||
|
|
||||||
XEEMITTER(mcrfs, 0xFC000080, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mcrfs, 0xFC000080, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mffsx, 0xFC00048E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mffsx, 0xFC00048E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
if (i.X.Rc) {
|
if (i.X.Rc) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -434,17 +413,17 @@ XEEMITTER(mffsx, 0xFC00048E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mtfsb0x, 0xFC00008C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mtfsb0x, 0xFC00008C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mtfsb1x, 0xFC00004C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mtfsb1x, 0xFC00004C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mtfsfx, 0xFC00058E, XFL)(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mtfsfx, 0xFC00058E, XFL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
if (i.XFL.Rc) {
|
if (i.XFL.Rc) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -460,99 +439,96 @@ XEEMITTER(mtfsfx, 0xFC00058E, XFL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mtfsfix, 0xFC00010C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(mtfsfix, 0xFC00010C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Floating-point move (A-21)
|
// Floating-point move (A-21)
|
||||||
|
|
||||||
XEEMITTER(fabsx, 0xFC000210, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fabsx, 0xFC000210, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- abs(frB)
|
// frD <- abs(frB)
|
||||||
Value* v = f.Abs(f.LoadFPR(i.X.RB));
|
Value* v = f.Abs(f.LoadFPR(i.X.RB));
|
||||||
f.StoreFPR(i.X.RT, v);
|
f.StoreFPR(i.X.RT, v);
|
||||||
if (i.X.Rc) {
|
if (i.X.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fmrx, 0xFC000090, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fmrx, 0xFC000090, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- (frB)
|
// frD <- (frB)
|
||||||
Value* v = f.LoadFPR(i.X.RB);
|
Value* v = f.LoadFPR(i.X.RB);
|
||||||
f.StoreFPR(i.X.RT, v);
|
f.StoreFPR(i.X.RT, v);
|
||||||
if (i.X.Rc) {
|
if (i.X.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fnabsx, 0xFC000110, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fnabsx, 0xFC000110, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(fnegx, 0xFC000050, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(fnegx, 0xFC000050, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// frD <- ¬ frB[0] || frB[1-63]
|
// frD <- ¬ frB[0] || frB[1-63]
|
||||||
Value* v = f.Neg(f.LoadFPR(i.X.RB));
|
Value* v = f.Neg(f.LoadFPR(i.X.RB));
|
||||||
f.StoreFPR(i.X.RT, v);
|
f.StoreFPR(i.X.RT, v);
|
||||||
if (i.X.Rc) {
|
if (i.X.Rc) {
|
||||||
//e.update_cr_with_cond(1, v);
|
// e.update_cr_with_cond(1, v);
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegisterEmitCategoryFPU() {
|
void RegisterEmitCategoryFPU() {
|
||||||
XEREGISTERINSTR(faddx, 0xFC00002A);
|
XEREGISTERINSTR(faddx, 0xFC00002A);
|
||||||
XEREGISTERINSTR(faddsx, 0xEC00002A);
|
XEREGISTERINSTR(faddsx, 0xEC00002A);
|
||||||
XEREGISTERINSTR(fdivx, 0xFC000024);
|
XEREGISTERINSTR(fdivx, 0xFC000024);
|
||||||
XEREGISTERINSTR(fdivsx, 0xEC000024);
|
XEREGISTERINSTR(fdivsx, 0xEC000024);
|
||||||
XEREGISTERINSTR(fmulx, 0xFC000032);
|
XEREGISTERINSTR(fmulx, 0xFC000032);
|
||||||
XEREGISTERINSTR(fmulsx, 0xEC000032);
|
XEREGISTERINSTR(fmulsx, 0xEC000032);
|
||||||
XEREGISTERINSTR(fresx, 0xEC000030);
|
XEREGISTERINSTR(fresx, 0xEC000030);
|
||||||
XEREGISTERINSTR(frsqrtex, 0xFC000034);
|
XEREGISTERINSTR(frsqrtex, 0xFC000034);
|
||||||
XEREGISTERINSTR(fsubx, 0xFC000028);
|
XEREGISTERINSTR(fsubx, 0xFC000028);
|
||||||
XEREGISTERINSTR(fsubsx, 0xEC000028);
|
XEREGISTERINSTR(fsubsx, 0xEC000028);
|
||||||
XEREGISTERINSTR(fselx, 0xFC00002E);
|
XEREGISTERINSTR(fselx, 0xFC00002E);
|
||||||
XEREGISTERINSTR(fsqrtx, 0xFC00002C);
|
XEREGISTERINSTR(fsqrtx, 0xFC00002C);
|
||||||
XEREGISTERINSTR(fsqrtsx, 0xEC00002C);
|
XEREGISTERINSTR(fsqrtsx, 0xEC00002C);
|
||||||
XEREGISTERINSTR(fmaddx, 0xFC00003A);
|
XEREGISTERINSTR(fmaddx, 0xFC00003A);
|
||||||
XEREGISTERINSTR(fmaddsx, 0xEC00003A);
|
XEREGISTERINSTR(fmaddsx, 0xEC00003A);
|
||||||
XEREGISTERINSTR(fmsubx, 0xFC000038);
|
XEREGISTERINSTR(fmsubx, 0xFC000038);
|
||||||
XEREGISTERINSTR(fmsubsx, 0xEC000038);
|
XEREGISTERINSTR(fmsubsx, 0xEC000038);
|
||||||
XEREGISTERINSTR(fnmaddx, 0xFC00003E);
|
XEREGISTERINSTR(fnmaddx, 0xFC00003E);
|
||||||
XEREGISTERINSTR(fnmaddsx, 0xEC00003E);
|
XEREGISTERINSTR(fnmaddsx, 0xEC00003E);
|
||||||
XEREGISTERINSTR(fnmsubx, 0xFC00003C);
|
XEREGISTERINSTR(fnmsubx, 0xFC00003C);
|
||||||
XEREGISTERINSTR(fnmsubsx, 0xEC00003C);
|
XEREGISTERINSTR(fnmsubsx, 0xEC00003C);
|
||||||
XEREGISTERINSTR(fcfidx, 0xFC00069C);
|
XEREGISTERINSTR(fcfidx, 0xFC00069C);
|
||||||
XEREGISTERINSTR(fctidx, 0xFC00065C);
|
XEREGISTERINSTR(fctidx, 0xFC00065C);
|
||||||
XEREGISTERINSTR(fctidzx, 0xFC00065E);
|
XEREGISTERINSTR(fctidzx, 0xFC00065E);
|
||||||
XEREGISTERINSTR(fctiwx, 0xFC00001C);
|
XEREGISTERINSTR(fctiwx, 0xFC00001C);
|
||||||
XEREGISTERINSTR(fctiwzx, 0xFC00001E);
|
XEREGISTERINSTR(fctiwzx, 0xFC00001E);
|
||||||
XEREGISTERINSTR(frspx, 0xFC000018);
|
XEREGISTERINSTR(frspx, 0xFC000018);
|
||||||
XEREGISTERINSTR(fcmpo, 0xFC000040);
|
XEREGISTERINSTR(fcmpo, 0xFC000040);
|
||||||
XEREGISTERINSTR(fcmpu, 0xFC000000);
|
XEREGISTERINSTR(fcmpu, 0xFC000000);
|
||||||
XEREGISTERINSTR(mcrfs, 0xFC000080);
|
XEREGISTERINSTR(mcrfs, 0xFC000080);
|
||||||
XEREGISTERINSTR(mffsx, 0xFC00048E);
|
XEREGISTERINSTR(mffsx, 0xFC00048E);
|
||||||
XEREGISTERINSTR(mtfsb0x, 0xFC00008C);
|
XEREGISTERINSTR(mtfsb0x, 0xFC00008C);
|
||||||
XEREGISTERINSTR(mtfsb1x, 0xFC00004C);
|
XEREGISTERINSTR(mtfsb1x, 0xFC00004C);
|
||||||
XEREGISTERINSTR(mtfsfx, 0xFC00058E);
|
XEREGISTERINSTR(mtfsfx, 0xFC00058E);
|
||||||
XEREGISTERINSTR(mtfsfix, 0xFC00010C);
|
XEREGISTERINSTR(mtfsfix, 0xFC00010C);
|
||||||
XEREGISTERINSTR(fabsx, 0xFC000210);
|
XEREGISTERINSTR(fabsx, 0xFC000210);
|
||||||
XEREGISTERINSTR(fmrx, 0xFC000090);
|
XEREGISTERINSTR(fmrx, 0xFC000090);
|
||||||
XEREGISTERINSTR(fnabsx, 0xFC000110);
|
XEREGISTERINSTR(fnabsx, 0xFC000110);
|
||||||
XEREGISTERINSTR(fnegx, 0xFC000050);
|
XEREGISTERINSTR(fnegx, 0xFC000050);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
|
@ -12,23 +12,22 @@
|
||||||
#include <alloy/frontend/ppc/ppc_context.h>
|
#include <alloy/frontend/ppc/ppc_context.h>
|
||||||
#include <alloy/frontend/ppc/ppc_hir_builder.h>
|
#include <alloy/frontend/ppc/ppc_hir_builder.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace alloy::frontend::ppc;
|
|
||||||
using namespace alloy::hir;
|
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
|
using namespace alloy::hir;
|
||||||
|
|
||||||
|
using alloy::hir::Value;
|
||||||
|
|
||||||
#define TRUNCATE_ADDRESSES 0
|
#define TRUNCATE_ADDRESSES 0
|
||||||
|
|
||||||
Value* CalculateEA(PPCHIRBuilder& f, uint32_t ra, uint32_t rb) {
|
Value* CalculateEA(PPCHIRBuilder& f, uint32_t ra, uint32_t rb) {
|
||||||
#if TRUNCATE_ADDRESSES
|
#if TRUNCATE_ADDRESSES
|
||||||
return f.ZeroExtend(f.Add(
|
return f.ZeroExtend(f.Add(f.Truncate(f.LoadGPR(ra), INT32_TYPE),
|
||||||
f.Truncate(f.LoadGPR(ra), INT32_TYPE),
|
f.Truncate(f.LoadGPR(rb), INT32_TYPE)),
|
||||||
f.Truncate(f.LoadGPR(rb), INT32_TYPE)), INT64_TYPE);
|
INT64_TYPE);
|
||||||
#else
|
#else
|
||||||
return f.Add(f.LoadGPR(ra), f.LoadGPR(rb));
|
return f.Add(f.LoadGPR(ra), f.LoadGPR(rb));
|
||||||
#endif // TRUNCATE_ADDRESSES
|
#endif // TRUNCATE_ADDRESSES
|
||||||
|
@ -37,9 +36,9 @@ Value* CalculateEA(PPCHIRBuilder& f, uint32_t ra, uint32_t rb) {
|
||||||
Value* CalculateEA_0(PPCHIRBuilder& f, uint32_t ra, uint32_t rb) {
|
Value* CalculateEA_0(PPCHIRBuilder& f, uint32_t ra, uint32_t rb) {
|
||||||
#if TRUNCATE_ADDRESSES
|
#if TRUNCATE_ADDRESSES
|
||||||
if (ra) {
|
if (ra) {
|
||||||
return f.ZeroExtend(f.Add(
|
return f.ZeroExtend(f.Add(f.Truncate(f.LoadGPR(ra), INT32_TYPE),
|
||||||
f.Truncate(f.LoadGPR(ra), INT32_TYPE),
|
f.Truncate(f.LoadGPR(rb), INT32_TYPE)),
|
||||||
f.Truncate(f.LoadGPR(rb), INT32_TYPE)), INT64_TYPE);
|
INT64_TYPE);
|
||||||
} else {
|
} else {
|
||||||
return f.ZeroExtend(f.Truncate(f.LoadGPR(rb), INT32_TYPE), INT64_TYPE);
|
return f.ZeroExtend(f.Truncate(f.LoadGPR(rb), INT32_TYPE), INT64_TYPE);
|
||||||
}
|
}
|
||||||
|
@ -54,9 +53,9 @@ Value* CalculateEA_0(PPCHIRBuilder& f, uint32_t ra, uint32_t rb) {
|
||||||
|
|
||||||
Value* CalculateEA_i(PPCHIRBuilder& f, uint32_t ra, uint64_t imm) {
|
Value* CalculateEA_i(PPCHIRBuilder& f, uint32_t ra, uint64_t imm) {
|
||||||
#if TRUNCATE_ADDRESSES
|
#if TRUNCATE_ADDRESSES
|
||||||
return f.ZeroExtend(f.Add(
|
return f.ZeroExtend(f.Add(f.Truncate(f.LoadGPR(ra), INT32_TYPE),
|
||||||
f.Truncate(f.LoadGPR(ra), INT32_TYPE),
|
f.LoadConstant((int32_t)imm)),
|
||||||
f.LoadConstant((int32_t)imm)), INT64_TYPE);
|
INT64_TYPE);
|
||||||
#else
|
#else
|
||||||
return f.Add(f.LoadGPR(ra), f.LoadConstant(imm));
|
return f.Add(f.LoadGPR(ra), f.LoadConstant(imm));
|
||||||
#endif // TRUNCATE_ADDRESSES
|
#endif // TRUNCATE_ADDRESSES
|
||||||
|
@ -65,9 +64,9 @@ Value* CalculateEA_i(PPCHIRBuilder& f, uint32_t ra, uint64_t imm) {
|
||||||
Value* CalculateEA_0_i(PPCHIRBuilder& f, uint32_t ra, uint64_t imm) {
|
Value* CalculateEA_0_i(PPCHIRBuilder& f, uint32_t ra, uint64_t imm) {
|
||||||
#if TRUNCATE_ADDRESSES
|
#if TRUNCATE_ADDRESSES
|
||||||
if (ra) {
|
if (ra) {
|
||||||
return f.ZeroExtend(f.Add(
|
return f.ZeroExtend(f.Add(f.Truncate(f.LoadGPR(ra), INT32_TYPE),
|
||||||
f.Truncate(f.LoadGPR(ra), INT32_TYPE),
|
f.LoadConstant((int32_t)imm)),
|
||||||
f.LoadConstant((int32_t)imm)), INT64_TYPE);
|
INT64_TYPE);
|
||||||
} else {
|
} else {
|
||||||
return f.ZeroExtend(f.LoadConstant((int32_t)imm), INT64_TYPE);
|
return f.ZeroExtend(f.LoadConstant((int32_t)imm), INT64_TYPE);
|
||||||
}
|
}
|
||||||
|
@ -80,10 +79,9 @@ Value* CalculateEA_0_i(PPCHIRBuilder& f, uint32_t ra, uint64_t imm) {
|
||||||
#endif // TRUNCATE_ADDRESSES
|
#endif // TRUNCATE_ADDRESSES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Integer load (A-13)
|
// Integer load (A-13)
|
||||||
|
|
||||||
XEEMITTER(lbz, 0x88000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lbz, 0x88000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -96,7 +94,7 @@ XEEMITTER(lbz, 0x88000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lbzu, 0x8C000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lbzu, 0x8C000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// RT <- i56.0 || MEM(EA, 1)
|
// RT <- i56.0 || MEM(EA, 1)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -107,7 +105,7 @@ XEEMITTER(lbzu, 0x8C000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lbzux, 0x7C0000EE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lbzux, 0x7C0000EE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// RT <- i56.0 || MEM(EA, 1)
|
// RT <- i56.0 || MEM(EA, 1)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -118,7 +116,7 @@ XEEMITTER(lbzux, 0x7C0000EE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lbzx, 0x7C0000AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lbzx, 0x7C0000AE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -131,7 +129,7 @@ XEEMITTER(lbzx, 0x7C0000AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lha, 0xA8000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lha, 0xA8000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -144,17 +142,17 @@ XEEMITTER(lha, 0xA8000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lhau, 0xAC000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lhau, 0xAC000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lhaux, 0x7C0002EE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lhaux, 0x7C0002EE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lhax, 0x7C0002AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lhax, 0x7C0002AE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -167,7 +165,7 @@ XEEMITTER(lhax, 0x7C0002AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lhz, 0xA0000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lhz, 0xA0000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -180,7 +178,7 @@ XEEMITTER(lhz, 0xA0000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lhzu, 0xA4000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lhzu, 0xA4000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// RT <- i48.0 || MEM(EA, 2)
|
// RT <- i48.0 || MEM(EA, 2)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -191,7 +189,7 @@ XEEMITTER(lhzu, 0xA4000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lhzux, 0x7C00026E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lhzux, 0x7C00026E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// RT <- i48.0 || MEM(EA, 2)
|
// RT <- i48.0 || MEM(EA, 2)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -202,7 +200,7 @@ XEEMITTER(lhzux, 0x7C00026E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lhzx, 0x7C00022E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lhzx, 0x7C00022E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -215,7 +213,7 @@ XEEMITTER(lhzx, 0x7C00022E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwa, 0xE8000002, DS )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lwa, 0xE8000002, DS)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -228,7 +226,7 @@ XEEMITTER(lwa, 0xE8000002, DS )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwaux, 0x7C0002EA, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lwaux, 0x7C0002EA, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// RT <- EXTS(MEM(EA, 4))
|
// RT <- EXTS(MEM(EA, 4))
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -239,7 +237,7 @@ XEEMITTER(lwaux, 0x7C0002EA, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwax, 0x7C0002AA, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lwax, 0x7C0002AA, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -252,7 +250,7 @@ XEEMITTER(lwax, 0x7C0002AA, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwz, 0x80000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lwz, 0x80000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -265,7 +263,7 @@ XEEMITTER(lwz, 0x80000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwzu, 0x84000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lwzu, 0x84000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// RT <- i32.0 || MEM(EA, 4)
|
// RT <- i32.0 || MEM(EA, 4)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -276,7 +274,7 @@ XEEMITTER(lwzu, 0x84000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwzux, 0x7C00006E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lwzux, 0x7C00006E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// RT <- i32.0 || MEM(EA, 4)
|
// RT <- i32.0 || MEM(EA, 4)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -287,7 +285,7 @@ XEEMITTER(lwzux, 0x7C00006E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwzx, 0x7C00002E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lwzx, 0x7C00002E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -300,8 +298,7 @@ XEEMITTER(lwzx, 0x7C00002E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XEEMITTER(ld, 0xE8000000, DS)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEEMITTER(ld, 0xE8000000, DS )(PPCHIRBuilder& f, InstrData& i) {
|
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -314,7 +311,7 @@ XEEMITTER(ld, 0xE8000000, DS )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(ldu, 0xE8000001, DS )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(ldu, 0xE8000001, DS)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(DS || 0b00)
|
// EA <- (RA) + EXTS(DS || 0b00)
|
||||||
// RT <- MEM(EA, 8)
|
// RT <- MEM(EA, 8)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -325,7 +322,7 @@ XEEMITTER(ldu, 0xE8000001, DS )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(ldux, 0x7C00006A, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(ldux, 0x7C00006A, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// RT <- MEM(EA, 8)
|
// RT <- MEM(EA, 8)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -336,7 +333,7 @@ XEEMITTER(ldux, 0x7C00006A, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(ldx, 0x7C00002A, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(ldx, 0x7C00002A, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -349,10 +346,9 @@ XEEMITTER(ldx, 0x7C00002A, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Integer store (A-14)
|
// Integer store (A-14)
|
||||||
|
|
||||||
XEEMITTER(stb, 0x98000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stb, 0x98000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -364,7 +360,7 @@ XEEMITTER(stb, 0x98000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stbu, 0x9C000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stbu, 0x9C000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// MEM(EA, 1) <- (RS)[56:63]
|
// MEM(EA, 1) <- (RS)[56:63]
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -374,7 +370,7 @@ XEEMITTER(stbu, 0x9C000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stbux, 0x7C0001EE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stbux, 0x7C0001EE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// MEM(EA, 1) <- (RS)[56:63]
|
// MEM(EA, 1) <- (RS)[56:63]
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -384,7 +380,7 @@ XEEMITTER(stbux, 0x7C0001EE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stbx, 0x7C0001AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stbx, 0x7C0001AE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -396,7 +392,7 @@ XEEMITTER(stbx, 0x7C0001AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(sth, 0xB0000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(sth, 0xB0000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -408,7 +404,7 @@ XEEMITTER(sth, 0xB0000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(sthu, 0xB4000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(sthu, 0xB4000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// MEM(EA, 2) <- (RS)[48:63]
|
// MEM(EA, 2) <- (RS)[48:63]
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -418,7 +414,7 @@ XEEMITTER(sthu, 0xB4000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(sthux, 0x7C00036E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(sthux, 0x7C00036E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// MEM(EA, 2) <- (RS)[48:63]
|
// MEM(EA, 2) <- (RS)[48:63]
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -428,7 +424,7 @@ XEEMITTER(sthux, 0x7C00036E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(sthx, 0x7C00032E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(sthx, 0x7C00032E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -440,7 +436,7 @@ XEEMITTER(sthx, 0x7C00032E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stw, 0x90000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stw, 0x90000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -452,7 +448,7 @@ XEEMITTER(stw, 0x90000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stwu, 0x94000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stwu, 0x94000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// MEM(EA, 4) <- (RS)[32:63]
|
// MEM(EA, 4) <- (RS)[32:63]
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -462,7 +458,7 @@ XEEMITTER(stwu, 0x94000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stwux, 0x7C00016E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stwux, 0x7C00016E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// MEM(EA, 4) <- (RS)[32:63]
|
// MEM(EA, 4) <- (RS)[32:63]
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -472,7 +468,7 @@ XEEMITTER(stwux, 0x7C00016E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stwx, 0x7C00012E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stwx, 0x7C00012E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -484,7 +480,7 @@ XEEMITTER(stwx, 0x7C00012E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(std, 0xF8000000, DS )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(std, 0xF8000000, DS)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -496,7 +492,7 @@ XEEMITTER(std, 0xF8000000, DS )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stdu, 0xF8000001, DS )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stdu, 0xF8000001, DS)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(DS || 0b00)
|
// EA <- (RA) + EXTS(DS || 0b00)
|
||||||
// MEM(EA, 8) <- (RS)
|
// MEM(EA, 8) <- (RS)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -506,7 +502,7 @@ XEEMITTER(stdu, 0xF8000001, DS )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stdux, 0x7C00016A, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stdux, 0x7C00016A, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// MEM(EA, 8) <- (RS)
|
// MEM(EA, 8) <- (RS)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -528,10 +524,9 @@ XEEMITTER(stdx, 0x7C00012A, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Integer load and store with byte reverse (A-1
|
// Integer load and store with byte reverse (A-1
|
||||||
|
|
||||||
XEEMITTER(lhbrx, 0x7C00062C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lhbrx, 0x7C00062C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -544,7 +539,7 @@ XEEMITTER(lhbrx, 0x7C00062C, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwbrx, 0x7C00042C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lwbrx, 0x7C00042C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -557,7 +552,7 @@ XEEMITTER(lwbrx, 0x7C00042C, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(ldbrx, 0x7C000428, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(ldbrx, 0x7C000428, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -570,7 +565,7 @@ XEEMITTER(ldbrx, 0x7C000428, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(sthbrx, 0x7C00072C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(sthbrx, 0x7C00072C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -582,7 +577,7 @@ XEEMITTER(sthbrx, 0x7C00072C, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stwbrx, 0x7C00052C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stwbrx, 0x7C00052C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -594,7 +589,7 @@ XEEMITTER(stwbrx, 0x7C00052C, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stdbrx, 0x7C000528, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stdbrx, 0x7C000528, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -606,64 +601,61 @@ XEEMITTER(stdbrx, 0x7C000528, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Integer load and store multiple (A-16)
|
// Integer load and store multiple (A-16)
|
||||||
|
|
||||||
XEEMITTER(lmw, 0xB8000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lmw, 0xB8000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stmw, 0xBC000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stmw, 0xBC000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Integer load and store string (A-17)
|
// Integer load and store string (A-17)
|
||||||
|
|
||||||
XEEMITTER(lswi, 0x7C0004AA, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lswi, 0x7C0004AA, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lswx, 0x7C00042A, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lswx, 0x7C00042A, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stswi, 0x7C0005AA, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stswi, 0x7C0005AA, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stswx, 0x7C00052A, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stswx, 0x7C00052A, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Memory synchronization (A-18)
|
// Memory synchronization (A-18)
|
||||||
|
|
||||||
XEEMITTER(eieio, 0x7C0006AC, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(eieio, 0x7C0006AC, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// XEINSTRNOTIMPLEMENTED();
|
// XEINSTRNOTIMPLEMENTED();
|
||||||
f.Nop();
|
f.Nop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(sync, 0x7C0004AC, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(sync, 0x7C0004AC, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// XEINSTRNOTIMPLEMENTED();
|
// XEINSTRNOTIMPLEMENTED();
|
||||||
f.Nop();
|
f.Nop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(isync, 0x4C00012C, XL )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(isync, 0x4C00012C, XL)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// XEINSTRNOTIMPLEMENTED();
|
// XEINSTRNOTIMPLEMENTED();
|
||||||
f.Nop();
|
f.Nop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(ldarx, 0x7C0000A8, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(ldarx, 0x7C0000A8, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -679,7 +671,7 @@ XEEMITTER(ldarx, 0x7C0000A8, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwarx, 0x7C000028, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lwarx, 0x7C000028, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -690,12 +682,13 @@ XEEMITTER(lwarx, 0x7C000028, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// RESERVE_ADDR <- real_addr(EA)
|
// RESERVE_ADDR <- real_addr(EA)
|
||||||
// RT <- i32.0 || MEM(EA, 4)
|
// RT <- i32.0 || MEM(EA, 4)
|
||||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||||
Value* rt = f.ZeroExtend(f.ByteSwap(f.LoadAcquire(ea, INT32_TYPE)), INT64_TYPE);
|
Value* rt =
|
||||||
|
f.ZeroExtend(f.ByteSwap(f.LoadAcquire(ea, INT32_TYPE)), INT64_TYPE);
|
||||||
f.StoreGPR(i.X.RT, rt);
|
f.StoreGPR(i.X.RT, rt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stdcx, 0x7C0001AD, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stdcx, 0x7C0001AD, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -712,7 +705,7 @@ XEEMITTER(stdcx, 0x7C0001AD, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stwcx, 0x7C00012D, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stwcx, 0x7C00012D, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -729,10 +722,9 @@ XEEMITTER(stwcx, 0x7C00012D, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Floating-point load (A-19)
|
// Floating-point load (A-19)
|
||||||
|
|
||||||
XEEMITTER(lfd, 0xC8000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lfd, 0xC8000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -745,7 +737,7 @@ XEEMITTER(lfd, 0xC8000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lfdu, 0xCC000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lfdu, 0xCC000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// FRT <- MEM(EA, 8)
|
// FRT <- MEM(EA, 8)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -756,7 +748,7 @@ XEEMITTER(lfdu, 0xCC000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lfdux, 0x7C0004EE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lfdux, 0x7C0004EE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// FRT <- MEM(EA, 8)
|
// FRT <- MEM(EA, 8)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -767,7 +759,7 @@ XEEMITTER(lfdux, 0x7C0004EE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lfdx, 0x7C0004AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lfdx, 0x7C0004AE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -780,7 +772,7 @@ XEEMITTER(lfdx, 0x7C0004AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lfs, 0xC0000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lfs, 0xC0000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -789,39 +781,36 @@ XEEMITTER(lfs, 0xC0000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// FRT <- DOUBLE(MEM(EA, 4))
|
// FRT <- DOUBLE(MEM(EA, 4))
|
||||||
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
||||||
Value* rt = f.Convert(
|
Value* rt = f.Convert(
|
||||||
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE),
|
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
FLOAT64_TYPE);
|
|
||||||
f.StoreFPR(i.D.RT, rt);
|
f.StoreFPR(i.D.RT, rt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lfsu, 0xC4000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lfsu, 0xC4000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// FRT <- DOUBLE(MEM(EA, 4))
|
// FRT <- DOUBLE(MEM(EA, 4))
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
||||||
Value* rt = f.Convert(
|
Value* rt = f.Convert(
|
||||||
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE),
|
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
FLOAT64_TYPE);
|
|
||||||
f.StoreFPR(i.D.RT, rt);
|
f.StoreFPR(i.D.RT, rt);
|
||||||
f.StoreGPR(i.D.RA, ea);
|
f.StoreGPR(i.D.RA, ea);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lfsux, 0x7C00046E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lfsux, 0x7C00046E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// FRT <- DOUBLE(MEM(EA, 4))
|
// FRT <- DOUBLE(MEM(EA, 4))
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
||||||
Value* rt = f.Convert(
|
Value* rt = f.Convert(
|
||||||
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE),
|
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
FLOAT64_TYPE);
|
|
||||||
f.StoreFPR(i.X.RT, rt);
|
f.StoreFPR(i.X.RT, rt);
|
||||||
f.StoreGPR(i.X.RA, ea);
|
f.StoreGPR(i.X.RA, ea);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lfsx, 0x7C00042E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(lfsx, 0x7C00042E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -830,16 +819,14 @@ XEEMITTER(lfsx, 0x7C00042E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// FRT <- DOUBLE(MEM(EA, 4))
|
// FRT <- DOUBLE(MEM(EA, 4))
|
||||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||||
Value* rt = f.Convert(
|
Value* rt = f.Convert(
|
||||||
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE),
|
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE), FLOAT64_TYPE);
|
||||||
FLOAT64_TYPE);
|
|
||||||
f.StoreFPR(i.X.RT, rt);
|
f.StoreFPR(i.X.RT, rt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Floating-point store (A-20)
|
// Floating-point store (A-20)
|
||||||
|
|
||||||
XEEMITTER(stfd, 0xD8000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stfd, 0xD8000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -851,7 +838,7 @@ XEEMITTER(stfd, 0xD8000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stfdu, 0xDC000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stfdu, 0xDC000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// MEM(EA, 8) <- (FRS)
|
// MEM(EA, 8) <- (FRS)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -861,7 +848,7 @@ XEEMITTER(stfdu, 0xDC000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stfdux, 0x7C0005EE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stfdux, 0x7C0005EE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// MEM(EA, 8) <- (FRS)
|
// MEM(EA, 8) <- (FRS)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
|
@ -871,7 +858,7 @@ XEEMITTER(stfdux, 0x7C0005EE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stfdx, 0x7C0005AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stfdx, 0x7C0005AE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -883,7 +870,7 @@ XEEMITTER(stfdx, 0x7C0005AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stfiwx, 0x7C0007AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stfiwx, 0x7C0007AE, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -891,12 +878,12 @@ XEEMITTER(stfiwx, 0x7C0007AE, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- b + (RB)
|
// EA <- b + (RB)
|
||||||
// MEM(EA, 4) <- (FRS)[32:63]
|
// MEM(EA, 4) <- (FRS)[32:63]
|
||||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||||
f.Store(ea, f.ByteSwap(
|
f.Store(ea, f.ByteSwap(f.Truncate(f.Cast(f.LoadFPR(i.X.RT), INT64_TYPE),
|
||||||
f.Truncate(f.Cast(f.LoadFPR(i.X.RT), INT64_TYPE), INT32_TYPE)));
|
INT32_TYPE)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stfs, 0xD0000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stfs, 0xD0000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -904,34 +891,34 @@ XEEMITTER(stfs, 0xD0000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- b + EXTS(D)
|
// EA <- b + EXTS(D)
|
||||||
// MEM(EA, 4) <- SINGLE(FRS)
|
// MEM(EA, 4) <- SINGLE(FRS)
|
||||||
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
||||||
f.Store(ea, f.ByteSwap(f.Cast(
|
f.Store(ea, f.ByteSwap(f.Cast(f.Convert(f.LoadFPR(i.D.RT), FLOAT32_TYPE),
|
||||||
f.Convert(f.LoadFPR(i.D.RT), FLOAT32_TYPE), INT32_TYPE)));
|
INT32_TYPE)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stfsu, 0xD4000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stfsu, 0xD4000000, D)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + EXTS(D)
|
// EA <- (RA) + EXTS(D)
|
||||||
// MEM(EA, 4) <- SINGLE(FRS)
|
// MEM(EA, 4) <- SINGLE(FRS)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
||||||
f.Store(ea, f.ByteSwap(f.Cast(
|
f.Store(ea, f.ByteSwap(f.Cast(f.Convert(f.LoadFPR(i.D.RT), FLOAT32_TYPE),
|
||||||
f.Convert(f.LoadFPR(i.D.RT), FLOAT32_TYPE), INT32_TYPE)));
|
INT32_TYPE)));
|
||||||
f.StoreGPR(i.D.RA, ea);
|
f.StoreGPR(i.D.RA, ea);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stfsux, 0x7C00056E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stfsux, 0x7C00056E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- (RA) + (RB)
|
// EA <- (RA) + (RB)
|
||||||
// MEM(EA, 4) <- SINGLE(FRS)
|
// MEM(EA, 4) <- SINGLE(FRS)
|
||||||
// RA <- EA
|
// RA <- EA
|
||||||
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
||||||
f.Store(ea, f.ByteSwap(f.Cast(
|
f.Store(ea, f.ByteSwap(f.Cast(f.Convert(f.LoadFPR(i.X.RT), FLOAT32_TYPE),
|
||||||
f.Convert(f.LoadFPR(i.X.RT), FLOAT32_TYPE), INT32_TYPE)));
|
INT32_TYPE)));
|
||||||
f.StoreGPR(i.X.RA, ea);
|
f.StoreGPR(i.X.RA, ea);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stfsx, 0x7C00052E, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(stfsx, 0x7C00052E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if RA = 0 then
|
// if RA = 0 then
|
||||||
// b <- 0
|
// b <- 0
|
||||||
// else
|
// else
|
||||||
|
@ -939,15 +926,14 @@ XEEMITTER(stfsx, 0x7C00052E, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// EA <- b + (RB)
|
// EA <- b + (RB)
|
||||||
// MEM(EA, 4) <- SINGLE(FRS)
|
// MEM(EA, 4) <- SINGLE(FRS)
|
||||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||||
f.Store(ea, f.ByteSwap(f.Cast(
|
f.Store(ea, f.ByteSwap(f.Cast(f.Convert(f.LoadFPR(i.X.RT), FLOAT32_TYPE),
|
||||||
f.Convert(f.LoadFPR(i.X.RT), FLOAT32_TYPE), INT32_TYPE)));
|
INT32_TYPE)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Cache management (A-27)
|
// Cache management (A-27)
|
||||||
|
|
||||||
XEEMITTER(dcbf, 0x7C0000AC, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(dcbf, 0x7C0000AC, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// No-op for now.
|
// No-op for now.
|
||||||
// TODO(benvanik): use prefetch
|
// TODO(benvanik): use prefetch
|
||||||
// XEINSTRNOTIMPLEMENTED();
|
// XEINSTRNOTIMPLEMENTED();
|
||||||
|
@ -955,7 +941,7 @@ XEEMITTER(dcbf, 0x7C0000AC, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(dcbst, 0x7C00006C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(dcbst, 0x7C00006C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// No-op for now.
|
// No-op for now.
|
||||||
// TODO(benvanik): use prefetch
|
// TODO(benvanik): use prefetch
|
||||||
// XEINSTRNOTIMPLEMENTED();
|
// XEINSTRNOTIMPLEMENTED();
|
||||||
|
@ -963,7 +949,7 @@ XEEMITTER(dcbst, 0x7C00006C, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(dcbt, 0x7C00022C, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(dcbt, 0x7C00022C, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// No-op for now.
|
// No-op for now.
|
||||||
// TODO(benvanik): use prefetch
|
// TODO(benvanik): use prefetch
|
||||||
// XEINSTRNOTIMPLEMENTED();
|
// XEINSTRNOTIMPLEMENTED();
|
||||||
|
@ -971,7 +957,7 @@ XEEMITTER(dcbt, 0x7C00022C, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(dcbtst, 0x7C0001EC, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(dcbtst, 0x7C0001EC, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// No-op for now.
|
// No-op for now.
|
||||||
// TODO(benvanik): use prefetch
|
// TODO(benvanik): use prefetch
|
||||||
// XEINSTRNOTIMPLEMENTED();
|
// XEINSTRNOTIMPLEMENTED();
|
||||||
|
@ -979,7 +965,7 @@ XEEMITTER(dcbtst, 0x7C0001EC, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(dcbz, 0x7C0007EC, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(dcbz, 0x7C0007EC, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// No-op for now.
|
// No-op for now.
|
||||||
// TODO(benvanik): use prefetch
|
// TODO(benvanik): use prefetch
|
||||||
// or dcbz128 0x7C2007EC
|
// or dcbz128 0x7C2007EC
|
||||||
|
@ -988,98 +974,96 @@ XEEMITTER(dcbz, 0x7C0007EC, X )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(icbi, 0x7C0007AC, X )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(icbi, 0x7C0007AC, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// XEINSTRNOTIMPLEMENTED();
|
// XEINSTRNOTIMPLEMENTED();
|
||||||
f.Nop();
|
f.Nop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegisterEmitCategoryMemory() {
|
void RegisterEmitCategoryMemory() {
|
||||||
XEREGISTERINSTR(lbz, 0x88000000);
|
XEREGISTERINSTR(lbz, 0x88000000);
|
||||||
XEREGISTERINSTR(lbzu, 0x8C000000);
|
XEREGISTERINSTR(lbzu, 0x8C000000);
|
||||||
XEREGISTERINSTR(lbzux, 0x7C0000EE);
|
XEREGISTERINSTR(lbzux, 0x7C0000EE);
|
||||||
XEREGISTERINSTR(lbzx, 0x7C0000AE);
|
XEREGISTERINSTR(lbzx, 0x7C0000AE);
|
||||||
XEREGISTERINSTR(lha, 0xA8000000);
|
XEREGISTERINSTR(lha, 0xA8000000);
|
||||||
XEREGISTERINSTR(lhau, 0xAC000000);
|
XEREGISTERINSTR(lhau, 0xAC000000);
|
||||||
XEREGISTERINSTR(lhaux, 0x7C0002EE);
|
XEREGISTERINSTR(lhaux, 0x7C0002EE);
|
||||||
XEREGISTERINSTR(lhax, 0x7C0002AE);
|
XEREGISTERINSTR(lhax, 0x7C0002AE);
|
||||||
XEREGISTERINSTR(lhz, 0xA0000000);
|
XEREGISTERINSTR(lhz, 0xA0000000);
|
||||||
XEREGISTERINSTR(lhzu, 0xA4000000);
|
XEREGISTERINSTR(lhzu, 0xA4000000);
|
||||||
XEREGISTERINSTR(lhzux, 0x7C00026E);
|
XEREGISTERINSTR(lhzux, 0x7C00026E);
|
||||||
XEREGISTERINSTR(lhzx, 0x7C00022E);
|
XEREGISTERINSTR(lhzx, 0x7C00022E);
|
||||||
XEREGISTERINSTR(lwa, 0xE8000002);
|
XEREGISTERINSTR(lwa, 0xE8000002);
|
||||||
XEREGISTERINSTR(lwaux, 0x7C0002EA);
|
XEREGISTERINSTR(lwaux, 0x7C0002EA);
|
||||||
XEREGISTERINSTR(lwax, 0x7C0002AA);
|
XEREGISTERINSTR(lwax, 0x7C0002AA);
|
||||||
XEREGISTERINSTR(lwz, 0x80000000);
|
XEREGISTERINSTR(lwz, 0x80000000);
|
||||||
XEREGISTERINSTR(lwzu, 0x84000000);
|
XEREGISTERINSTR(lwzu, 0x84000000);
|
||||||
XEREGISTERINSTR(lwzux, 0x7C00006E);
|
XEREGISTERINSTR(lwzux, 0x7C00006E);
|
||||||
XEREGISTERINSTR(lwzx, 0x7C00002E);
|
XEREGISTERINSTR(lwzx, 0x7C00002E);
|
||||||
XEREGISTERINSTR(ld, 0xE8000000);
|
XEREGISTERINSTR(ld, 0xE8000000);
|
||||||
XEREGISTERINSTR(ldu, 0xE8000001);
|
XEREGISTERINSTR(ldu, 0xE8000001);
|
||||||
XEREGISTERINSTR(ldux, 0x7C00006A);
|
XEREGISTERINSTR(ldux, 0x7C00006A);
|
||||||
XEREGISTERINSTR(ldx, 0x7C00002A);
|
XEREGISTERINSTR(ldx, 0x7C00002A);
|
||||||
XEREGISTERINSTR(stb, 0x98000000);
|
XEREGISTERINSTR(stb, 0x98000000);
|
||||||
XEREGISTERINSTR(stbu, 0x9C000000);
|
XEREGISTERINSTR(stbu, 0x9C000000);
|
||||||
XEREGISTERINSTR(stbux, 0x7C0001EE);
|
XEREGISTERINSTR(stbux, 0x7C0001EE);
|
||||||
XEREGISTERINSTR(stbx, 0x7C0001AE);
|
XEREGISTERINSTR(stbx, 0x7C0001AE);
|
||||||
XEREGISTERINSTR(sth, 0xB0000000);
|
XEREGISTERINSTR(sth, 0xB0000000);
|
||||||
XEREGISTERINSTR(sthu, 0xB4000000);
|
XEREGISTERINSTR(sthu, 0xB4000000);
|
||||||
XEREGISTERINSTR(sthux, 0x7C00036E);
|
XEREGISTERINSTR(sthux, 0x7C00036E);
|
||||||
XEREGISTERINSTR(sthx, 0x7C00032E);
|
XEREGISTERINSTR(sthx, 0x7C00032E);
|
||||||
XEREGISTERINSTR(stw, 0x90000000);
|
XEREGISTERINSTR(stw, 0x90000000);
|
||||||
XEREGISTERINSTR(stwu, 0x94000000);
|
XEREGISTERINSTR(stwu, 0x94000000);
|
||||||
XEREGISTERINSTR(stwux, 0x7C00016E);
|
XEREGISTERINSTR(stwux, 0x7C00016E);
|
||||||
XEREGISTERINSTR(stwx, 0x7C00012E);
|
XEREGISTERINSTR(stwx, 0x7C00012E);
|
||||||
XEREGISTERINSTR(std, 0xF8000000);
|
XEREGISTERINSTR(std, 0xF8000000);
|
||||||
XEREGISTERINSTR(stdu, 0xF8000001);
|
XEREGISTERINSTR(stdu, 0xF8000001);
|
||||||
XEREGISTERINSTR(stdux, 0x7C00016A);
|
XEREGISTERINSTR(stdux, 0x7C00016A);
|
||||||
XEREGISTERINSTR(stdx, 0x7C00012A);
|
XEREGISTERINSTR(stdx, 0x7C00012A);
|
||||||
XEREGISTERINSTR(lhbrx, 0x7C00062C);
|
XEREGISTERINSTR(lhbrx, 0x7C00062C);
|
||||||
XEREGISTERINSTR(lwbrx, 0x7C00042C);
|
XEREGISTERINSTR(lwbrx, 0x7C00042C);
|
||||||
XEREGISTERINSTR(ldbrx, 0x7C000428);
|
XEREGISTERINSTR(ldbrx, 0x7C000428);
|
||||||
XEREGISTERINSTR(sthbrx, 0x7C00072C);
|
XEREGISTERINSTR(sthbrx, 0x7C00072C);
|
||||||
XEREGISTERINSTR(stwbrx, 0x7C00052C);
|
XEREGISTERINSTR(stwbrx, 0x7C00052C);
|
||||||
XEREGISTERINSTR(stdbrx, 0x7C000528);
|
XEREGISTERINSTR(stdbrx, 0x7C000528);
|
||||||
XEREGISTERINSTR(lmw, 0xB8000000);
|
XEREGISTERINSTR(lmw, 0xB8000000);
|
||||||
XEREGISTERINSTR(stmw, 0xBC000000);
|
XEREGISTERINSTR(stmw, 0xBC000000);
|
||||||
XEREGISTERINSTR(lswi, 0x7C0004AA);
|
XEREGISTERINSTR(lswi, 0x7C0004AA);
|
||||||
XEREGISTERINSTR(lswx, 0x7C00042A);
|
XEREGISTERINSTR(lswx, 0x7C00042A);
|
||||||
XEREGISTERINSTR(stswi, 0x7C0005AA);
|
XEREGISTERINSTR(stswi, 0x7C0005AA);
|
||||||
XEREGISTERINSTR(stswx, 0x7C00052A);
|
XEREGISTERINSTR(stswx, 0x7C00052A);
|
||||||
XEREGISTERINSTR(eieio, 0x7C0006AC);
|
XEREGISTERINSTR(eieio, 0x7C0006AC);
|
||||||
XEREGISTERINSTR(sync, 0x7C0004AC);
|
XEREGISTERINSTR(sync, 0x7C0004AC);
|
||||||
XEREGISTERINSTR(isync, 0x4C00012C);
|
XEREGISTERINSTR(isync, 0x4C00012C);
|
||||||
XEREGISTERINSTR(ldarx, 0x7C0000A8);
|
XEREGISTERINSTR(ldarx, 0x7C0000A8);
|
||||||
XEREGISTERINSTR(lwarx, 0x7C000028);
|
XEREGISTERINSTR(lwarx, 0x7C000028);
|
||||||
XEREGISTERINSTR(stdcx, 0x7C0001AD);
|
XEREGISTERINSTR(stdcx, 0x7C0001AD);
|
||||||
XEREGISTERINSTR(stwcx, 0x7C00012D);
|
XEREGISTERINSTR(stwcx, 0x7C00012D);
|
||||||
XEREGISTERINSTR(lfd, 0xC8000000);
|
XEREGISTERINSTR(lfd, 0xC8000000);
|
||||||
XEREGISTERINSTR(lfdu, 0xCC000000);
|
XEREGISTERINSTR(lfdu, 0xCC000000);
|
||||||
XEREGISTERINSTR(lfdux, 0x7C0004EE);
|
XEREGISTERINSTR(lfdux, 0x7C0004EE);
|
||||||
XEREGISTERINSTR(lfdx, 0x7C0004AE);
|
XEREGISTERINSTR(lfdx, 0x7C0004AE);
|
||||||
XEREGISTERINSTR(lfs, 0xC0000000);
|
XEREGISTERINSTR(lfs, 0xC0000000);
|
||||||
XEREGISTERINSTR(lfsu, 0xC4000000);
|
XEREGISTERINSTR(lfsu, 0xC4000000);
|
||||||
XEREGISTERINSTR(lfsux, 0x7C00046E);
|
XEREGISTERINSTR(lfsux, 0x7C00046E);
|
||||||
XEREGISTERINSTR(lfsx, 0x7C00042E);
|
XEREGISTERINSTR(lfsx, 0x7C00042E);
|
||||||
XEREGISTERINSTR(stfd, 0xD8000000);
|
XEREGISTERINSTR(stfd, 0xD8000000);
|
||||||
XEREGISTERINSTR(stfdu, 0xDC000000);
|
XEREGISTERINSTR(stfdu, 0xDC000000);
|
||||||
XEREGISTERINSTR(stfdux, 0x7C0005EE);
|
XEREGISTERINSTR(stfdux, 0x7C0005EE);
|
||||||
XEREGISTERINSTR(stfdx, 0x7C0005AE);
|
XEREGISTERINSTR(stfdx, 0x7C0005AE);
|
||||||
XEREGISTERINSTR(stfiwx, 0x7C0007AE);
|
XEREGISTERINSTR(stfiwx, 0x7C0007AE);
|
||||||
XEREGISTERINSTR(stfs, 0xD0000000);
|
XEREGISTERINSTR(stfs, 0xD0000000);
|
||||||
XEREGISTERINSTR(stfsu, 0xD4000000);
|
XEREGISTERINSTR(stfsu, 0xD4000000);
|
||||||
XEREGISTERINSTR(stfsux, 0x7C00056E);
|
XEREGISTERINSTR(stfsux, 0x7C00056E);
|
||||||
XEREGISTERINSTR(stfsx, 0x7C00052E);
|
XEREGISTERINSTR(stfsx, 0x7C00052E);
|
||||||
XEREGISTERINSTR(dcbf, 0x7C0000AC);
|
XEREGISTERINSTR(dcbf, 0x7C0000AC);
|
||||||
XEREGISTERINSTR(dcbst, 0x7C00006C);
|
XEREGISTERINSTR(dcbst, 0x7C00006C);
|
||||||
XEREGISTERINSTR(dcbt, 0x7C00022C);
|
XEREGISTERINSTR(dcbt, 0x7C00022C);
|
||||||
XEREGISTERINSTR(dcbtst, 0x7C0001EC);
|
XEREGISTERINSTR(dcbtst, 0x7C0001EC);
|
||||||
XEREGISTERINSTR(dcbz, 0x7C0007EC);
|
XEREGISTERINSTR(dcbz, 0x7C0007EC);
|
||||||
XEREGISTERINSTR(icbi, 0x7C0007AC);
|
XEREGISTERINSTR(icbi, 0x7C0007AC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
|
@ -15,44 +15,40 @@
|
||||||
#include <alloy/frontend/ppc/ppc_emit.h>
|
#include <alloy/frontend/ppc/ppc_emit.h>
|
||||||
#include <alloy/frontend/ppc/ppc_translator.h>
|
#include <alloy/frontend/ppc/ppc_translator.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::frontend;
|
namespace frontend {
|
||||||
using namespace alloy::frontend::ppc;
|
namespace ppc {
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::runtime::Function;
|
||||||
|
using alloy::runtime::FunctionInfo;
|
||||||
|
using alloy::runtime::Runtime;
|
||||||
|
|
||||||
namespace {
|
void InitializeIfNeeded();
|
||||||
void InitializeIfNeeded();
|
void CleanupOnShutdown();
|
||||||
void CleanupOnShutdown();
|
|
||||||
|
|
||||||
void InitializeIfNeeded() {
|
void InitializeIfNeeded() {
|
||||||
static bool has_initialized = false;
|
static bool has_initialized = false;
|
||||||
if (has_initialized) {
|
if (has_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
has_initialized = true;
|
|
||||||
|
|
||||||
RegisterEmitCategoryAltivec();
|
|
||||||
RegisterEmitCategoryALU();
|
|
||||||
RegisterEmitCategoryControl();
|
|
||||||
RegisterEmitCategoryFPU();
|
|
||||||
RegisterEmitCategoryMemory();
|
|
||||||
|
|
||||||
atexit(CleanupOnShutdown);
|
|
||||||
}
|
}
|
||||||
|
has_initialized = true;
|
||||||
|
|
||||||
void CleanupOnShutdown() {
|
RegisterEmitCategoryAltivec();
|
||||||
}
|
RegisterEmitCategoryALU();
|
||||||
|
RegisterEmitCategoryControl();
|
||||||
|
RegisterEmitCategoryFPU();
|
||||||
|
RegisterEmitCategoryMemory();
|
||||||
|
|
||||||
|
atexit(CleanupOnShutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CleanupOnShutdown() {}
|
||||||
|
|
||||||
PPCFrontend::PPCFrontend(Runtime* runtime) :
|
PPCFrontend::PPCFrontend(Runtime* runtime) : Frontend(runtime) {
|
||||||
Frontend(runtime) {
|
|
||||||
InitializeIfNeeded();
|
InitializeIfNeeded();
|
||||||
|
|
||||||
ContextInfo* info = new ContextInfo(
|
ContextInfo* info =
|
||||||
sizeof(PPCContext),
|
new ContextInfo(sizeof(PPCContext), offsetof(PPCContext, thread_state));
|
||||||
offsetof(PPCContext, thread_state));
|
|
||||||
// Add fields/etc.
|
// Add fields/etc.
|
||||||
context_info_ = info;
|
context_info_ = info;
|
||||||
}
|
}
|
||||||
|
@ -61,8 +57,7 @@ PPCFrontend::~PPCFrontend() {
|
||||||
// Force cleanup now before we deinit.
|
// Force cleanup now before we deinit.
|
||||||
translator_pool_.Reset();
|
translator_pool_.Reset();
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::Deinit({
|
alloy::tracing::WriteEvent(EventType::Deinit({}));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PPCFrontend::Initialize() {
|
int PPCFrontend::Initialize() {
|
||||||
|
@ -71,14 +66,12 @@ int PPCFrontend::Initialize() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::Init({
|
alloy::tracing::WriteEvent(EventType::Init({}));
|
||||||
}));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PPCFrontend::DeclareFunction(
|
int PPCFrontend::DeclareFunction(FunctionInfo* symbol_info) {
|
||||||
FunctionInfo* symbol_info) {
|
|
||||||
// Could scan or something here.
|
// Could scan or something here.
|
||||||
// Could also check to see if it's a well-known function type and classify
|
// Could also check to see if it's a well-known function type and classify
|
||||||
// for later.
|
// for later.
|
||||||
|
@ -87,12 +80,16 @@ int PPCFrontend::DeclareFunction(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PPCFrontend::DefineFunction(
|
int PPCFrontend::DefineFunction(FunctionInfo* symbol_info,
|
||||||
FunctionInfo* symbol_info, uint32_t debug_info_flags,
|
uint32_t debug_info_flags,
|
||||||
Function** out_function) {
|
Function** out_function) {
|
||||||
PPCTranslator* translator = translator_pool_.Allocate(this);
|
PPCTranslator* translator = translator_pool_.Allocate(this);
|
||||||
int result = translator->Translate(
|
int result =
|
||||||
symbol_info, debug_info_flags, out_function);
|
translator->Translate(symbol_info, debug_info_flags, out_function);
|
||||||
translator_pool_.Release(translator);
|
translator_pool_.Release(translator);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ppc
|
||||||
|
} // namespace frontend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
#include <alloy/frontend/frontend.h>
|
#include <alloy/frontend/frontend.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
@ -23,26 +22,23 @@ namespace ppc {
|
||||||
class PPCTranslator;
|
class PPCTranslator;
|
||||||
|
|
||||||
class PPCFrontend : public Frontend {
|
class PPCFrontend : public Frontend {
|
||||||
public:
|
public:
|
||||||
PPCFrontend(runtime::Runtime* runtime);
|
PPCFrontend(runtime::Runtime* runtime);
|
||||||
virtual ~PPCFrontend();
|
virtual ~PPCFrontend();
|
||||||
|
|
||||||
virtual int Initialize();
|
virtual int Initialize();
|
||||||
|
|
||||||
virtual int DeclareFunction(
|
virtual int DeclareFunction(runtime::FunctionInfo* symbol_info);
|
||||||
runtime::FunctionInfo* symbol_info);
|
virtual int DefineFunction(runtime::FunctionInfo* symbol_info,
|
||||||
virtual int DefineFunction(
|
uint32_t debug_info_flags,
|
||||||
runtime::FunctionInfo* symbol_info, uint32_t debug_info_flags,
|
runtime::Function** out_function);
|
||||||
runtime::Function** out_function);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TypePool<PPCTranslator, PPCFrontend*> translator_pool_;
|
TypePool<PPCTranslator, PPCFrontend*> translator_pool_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_PPC_PPC_FRONTEND_H_
|
#endif // ALLOY_FRONTEND_PPC_PPC_FRONTEND_H_
|
||||||
|
|
|
@ -18,22 +18,25 @@
|
||||||
#include <alloy/hir/label.h>
|
#include <alloy/hir/label.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::frontend;
|
namespace frontend {
|
||||||
using namespace alloy::frontend::ppc;
|
namespace ppc {
|
||||||
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::hir::Label;
|
||||||
|
using alloy::hir::TypeName;
|
||||||
|
using alloy::hir::Value;
|
||||||
|
using alloy::runtime::Runtime;
|
||||||
|
using alloy::runtime::FunctionInfo;
|
||||||
|
|
||||||
PPCHIRBuilder::PPCHIRBuilder(PPCFrontend* frontend) :
|
PPCHIRBuilder::PPCHIRBuilder(PPCFrontend* frontend)
|
||||||
frontend_(frontend),
|
: frontend_(frontend), HIRBuilder() {
|
||||||
HIRBuilder() {
|
|
||||||
comment_buffer_ = new StringBuffer(4096);
|
comment_buffer_ = new StringBuffer(4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
PPCHIRBuilder::~PPCHIRBuilder() {
|
PPCHIRBuilder::~PPCHIRBuilder() { delete comment_buffer_; }
|
||||||
delete comment_buffer_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PPCHIRBuilder::Reset() {
|
void PPCHIRBuilder::Reset() {
|
||||||
start_address_ = 0;
|
start_address_ = 0;
|
||||||
|
@ -51,13 +54,11 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, bool with_debug_info) {
|
||||||
|
|
||||||
symbol_info_ = symbol_info;
|
symbol_info_ = symbol_info;
|
||||||
start_address_ = symbol_info->address();
|
start_address_ = symbol_info->address();
|
||||||
instr_count_ =
|
instr_count_ = (symbol_info->end_address() - symbol_info->address()) / 4 + 1;
|
||||||
(symbol_info->end_address() - symbol_info->address()) / 4 + 1;
|
|
||||||
|
|
||||||
with_debug_info_ = with_debug_info;
|
with_debug_info_ = with_debug_info;
|
||||||
if (with_debug_info_) {
|
if (with_debug_info_) {
|
||||||
Comment("%s fn %.8X-%.8X %s",
|
Comment("%s fn %.8X-%.8X %s", symbol_info->module()->name(),
|
||||||
symbol_info->module()->name(),
|
|
||||||
symbol_info->address(), symbol_info->end_address(),
|
symbol_info->address(), symbol_info->end_address(),
|
||||||
symbol_info->name());
|
symbol_info->name());
|
||||||
}
|
}
|
||||||
|
@ -121,7 +122,7 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, bool with_debug_info) {
|
||||||
if (!i.type) {
|
if (!i.type) {
|
||||||
XELOGCPU("Invalid instruction %.8X %.8X", i.address, i.code);
|
XELOGCPU("Invalid instruction %.8X %.8X", i.address, i.code);
|
||||||
Comment("INVALID!");
|
Comment("INVALID!");
|
||||||
//TraceInvalidInstruction(i);
|
// TraceInvalidInstruction(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,11 +135,11 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, bool with_debug_info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!i.type->emit || emit(*this, i)) {
|
if (!i.type->emit || emit(*this, i)) {
|
||||||
XELOGCPU("Unimplemented instr %.8X %.8X %s",
|
XELOGCPU("Unimplemented instr %.8X %.8X %s", i.address, i.code,
|
||||||
i.address, i.code, i.type->name);
|
i.type->name);
|
||||||
Comment("UNIMPLEMENTED!");
|
Comment("UNIMPLEMENTED!");
|
||||||
//DebugBreak();
|
// DebugBreak();
|
||||||
//TraceInvalidInstruction(i);
|
// TraceInvalidInstruction(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,8 +148,7 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, bool with_debug_info) {
|
||||||
|
|
||||||
void PPCHIRBuilder::AnnotateLabel(uint64_t address, Label* label) {
|
void PPCHIRBuilder::AnnotateLabel(uint64_t address, Label* label) {
|
||||||
char name_buffer[13];
|
char name_buffer[13];
|
||||||
xesnprintfa(name_buffer, XECOUNT(name_buffer),
|
xesnprintfa(name_buffer, XECOUNT(name_buffer), "loc_%.8X", (uint32_t)address);
|
||||||
"loc_%.8X", (uint32_t)address);
|
|
||||||
label->name = (char*)arena_->Alloc(sizeof(name_buffer));
|
label->name = (char*)arena_->Alloc(sizeof(name_buffer));
|
||||||
xe_copy_struct(label->name, name_buffer, sizeof(name_buffer));
|
xe_copy_struct(label->name, name_buffer, sizeof(name_buffer));
|
||||||
}
|
}
|
||||||
|
@ -197,10 +197,10 @@ Label* PPCHIRBuilder::LookupLabel(uint64_t address) {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Value* PPCHIRBuilder::LoadXER() {
|
// Value* PPCHIRBuilder::LoadXER() {
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
//void PPCHIRBuilder::StoreXER(Value* value) {
|
// void PPCHIRBuilder::StoreXER(Value* value) {
|
||||||
//}
|
//}
|
||||||
|
|
||||||
Value* PPCHIRBuilder::LoadLR() {
|
Value* PPCHIRBuilder::LoadLR() {
|
||||||
|
@ -235,13 +235,12 @@ void PPCHIRBuilder::StoreCR(uint32_t n, Value* value) {
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCHIRBuilder::UpdateCR(
|
void PPCHIRBuilder::UpdateCR(uint32_t n, Value* lhs, bool is_signed) {
|
||||||
uint32_t n, Value* lhs, bool is_signed) {
|
|
||||||
UpdateCR(n, lhs, LoadZero(lhs->type), is_signed);
|
UpdateCR(n, lhs, LoadZero(lhs->type), is_signed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCHIRBuilder::UpdateCR(
|
void PPCHIRBuilder::UpdateCR(uint32_t n, Value* lhs, Value* rhs,
|
||||||
uint32_t n, Value* lhs, Value* rhs, bool is_signed) {
|
bool is_signed) {
|
||||||
if (is_signed) {
|
if (is_signed) {
|
||||||
Value* lt = CompareSLT(lhs, rhs);
|
Value* lt = CompareSLT(lhs, rhs);
|
||||||
StoreContext(offsetof(PPCContext, cr0) + (4 * n) + 0, lt);
|
StoreContext(offsetof(PPCContext, cr0) + (4 * n) + 0, lt);
|
||||||
|
@ -264,7 +263,8 @@ void PPCHIRBuilder::UpdateCR6(Value* src_value) {
|
||||||
// Testing for all 1's and all 0's.
|
// Testing for all 1's and all 0's.
|
||||||
// if (Rc) CR6 = all_equal | 0 | none_equal | 0
|
// if (Rc) CR6 = all_equal | 0 | none_equal | 0
|
||||||
// TODO(benvanik): efficient instruction?
|
// TODO(benvanik): efficient instruction?
|
||||||
StoreContext(offsetof(PPCContext, cr6.cr6_all_equal), IsFalse(Not(src_value)));
|
StoreContext(offsetof(PPCContext, cr6.cr6_all_equal),
|
||||||
|
IsFalse(Not(src_value)));
|
||||||
StoreContext(offsetof(PPCContext, cr6.cr6_none_equal), IsFalse(src_value));
|
StoreContext(offsetof(PPCContext, cr6.cr6_none_equal), IsFalse(src_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,9 +282,7 @@ Value* PPCHIRBuilder::LoadXER() {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCHIRBuilder::StoreXER(Value* value) {
|
void PPCHIRBuilder::StoreXER(Value* value) { XEASSERTALWAYS(); }
|
||||||
XEASSERTALWAYS();
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* PPCHIRBuilder::LoadCA() {
|
Value* PPCHIRBuilder::LoadCA() {
|
||||||
return LoadContext(offsetof(PPCContext, xer_ca), INT8_TYPE);
|
return LoadContext(offsetof(PPCContext, xer_ca), INT8_TYPE);
|
||||||
|
@ -305,48 +303,41 @@ void PPCHIRBuilder::StoreSAT(Value* value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* PPCHIRBuilder::LoadGPR(uint32_t reg) {
|
Value* PPCHIRBuilder::LoadGPR(uint32_t reg) {
|
||||||
return LoadContext(
|
return LoadContext(offsetof(PPCContext, r) + reg * 8, INT64_TYPE);
|
||||||
offsetof(PPCContext, r) + reg * 8, INT64_TYPE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCHIRBuilder::StoreGPR(uint32_t reg, Value* value) {
|
void PPCHIRBuilder::StoreGPR(uint32_t reg, Value* value) {
|
||||||
XEASSERT(value->type == INT64_TYPE);
|
XEASSERT(value->type == INT64_TYPE);
|
||||||
StoreContext(
|
StoreContext(offsetof(PPCContext, r) + reg * 8, value);
|
||||||
offsetof(PPCContext, r) + reg * 8, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* PPCHIRBuilder::LoadFPR(uint32_t reg) {
|
Value* PPCHIRBuilder::LoadFPR(uint32_t reg) {
|
||||||
return LoadContext(
|
return LoadContext(offsetof(PPCContext, f) + reg * 8, FLOAT64_TYPE);
|
||||||
offsetof(PPCContext, f) + reg * 8, FLOAT64_TYPE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCHIRBuilder::StoreFPR(uint32_t reg, Value* value) {
|
void PPCHIRBuilder::StoreFPR(uint32_t reg, Value* value) {
|
||||||
XEASSERT(value->type == FLOAT64_TYPE);
|
XEASSERT(value->type == FLOAT64_TYPE);
|
||||||
StoreContext(
|
StoreContext(offsetof(PPCContext, f) + reg * 8, value);
|
||||||
offsetof(PPCContext, f) + reg * 8, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* PPCHIRBuilder::LoadVR(uint32_t reg) {
|
Value* PPCHIRBuilder::LoadVR(uint32_t reg) {
|
||||||
return LoadContext(
|
return LoadContext(offsetof(PPCContext, v) + reg * 16, VEC128_TYPE);
|
||||||
offsetof(PPCContext, v) + reg * 16, VEC128_TYPE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCHIRBuilder::StoreVR(uint32_t reg, Value* value) {
|
void PPCHIRBuilder::StoreVR(uint32_t reg, Value* value) {
|
||||||
XEASSERT(value->type == VEC128_TYPE);
|
XEASSERT(value->type == VEC128_TYPE);
|
||||||
StoreContext(
|
StoreContext(offsetof(PPCContext, v) + reg * 16, value);
|
||||||
offsetof(PPCContext, v) + reg * 16, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* PPCHIRBuilder::LoadAcquire(
|
Value* PPCHIRBuilder::LoadAcquire(Value* address, TypeName type,
|
||||||
Value* address, TypeName type, uint32_t load_flags) {
|
uint32_t load_flags) {
|
||||||
AtomicExchange(
|
AtomicExchange(LoadContext(offsetof(PPCContext, reserve_address), INT64_TYPE),
|
||||||
LoadContext(offsetof(PPCContext, reserve_address), INT64_TYPE),
|
Truncate(address, INT32_TYPE));
|
||||||
Truncate(address, INT32_TYPE));
|
|
||||||
return Load(address, type, load_flags);
|
return Load(address, type, load_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* PPCHIRBuilder::StoreRelease(
|
Value* PPCHIRBuilder::StoreRelease(Value* address, Value* value,
|
||||||
Value* address, Value* value, uint32_t store_flags) {
|
uint32_t store_flags) {
|
||||||
Value* old_address = AtomicExchange(
|
Value* old_address = AtomicExchange(
|
||||||
LoadContext(offsetof(PPCContext, reserve_address), INT64_TYPE),
|
LoadContext(offsetof(PPCContext, reserve_address), INT64_TYPE),
|
||||||
LoadZero(INT32_TYPE));
|
LoadZero(INT32_TYPE));
|
||||||
|
@ -357,3 +348,7 @@ Value* PPCHIRBuilder::StoreRelease(
|
||||||
MarkLabel(skip_label);
|
MarkLabel(skip_label);
|
||||||
return eq;
|
return eq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ppc
|
||||||
|
} // namespace frontend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -15,19 +15,18 @@
|
||||||
#include <alloy/runtime/function.h>
|
#include <alloy/runtime/function.h>
|
||||||
#include <alloy/runtime/symbol_info.h>
|
#include <alloy/runtime/symbol_info.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
|
||||||
class PPCFrontend;
|
class PPCFrontend;
|
||||||
|
|
||||||
|
|
||||||
class PPCHIRBuilder : public hir::HIRBuilder {
|
class PPCHIRBuilder : public hir::HIRBuilder {
|
||||||
using Instr = alloy::hir::Instr;
|
using Instr = alloy::hir::Instr;
|
||||||
using Label = alloy::hir::Label;
|
using Label = alloy::hir::Label;
|
||||||
using Value = alloy::hir::Value;
|
using Value = alloy::hir::Value;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
PPCHIRBuilder(PPCFrontend* frontend);
|
PPCHIRBuilder(PPCFrontend* frontend);
|
||||||
virtual ~PPCHIRBuilder();
|
virtual ~PPCHIRBuilder();
|
||||||
|
|
||||||
|
@ -53,9 +52,9 @@ public:
|
||||||
void StoreFPSCR(Value* value);
|
void StoreFPSCR(Value* value);
|
||||||
Value* LoadXER();
|
Value* LoadXER();
|
||||||
void StoreXER(Value* value);
|
void StoreXER(Value* value);
|
||||||
//void UpdateXERWithOverflow();
|
// void UpdateXERWithOverflow();
|
||||||
//void UpdateXERWithOverflowAndCarry();
|
// void UpdateXERWithOverflowAndCarry();
|
||||||
//void StoreOV(Value* value);
|
// void StoreOV(Value* value);
|
||||||
Value* LoadCA();
|
Value* LoadCA();
|
||||||
void StoreCA(Value* value);
|
void StoreCA(Value* value);
|
||||||
Value* LoadSAT();
|
Value* LoadSAT();
|
||||||
|
@ -68,31 +67,30 @@ public:
|
||||||
Value* LoadVR(uint32_t reg);
|
Value* LoadVR(uint32_t reg);
|
||||||
void StoreVR(uint32_t reg, Value* value);
|
void StoreVR(uint32_t reg, Value* value);
|
||||||
|
|
||||||
Value* LoadAcquire(Value* address, hir::TypeName type, uint32_t load_flags = 0);
|
Value* LoadAcquire(Value* address, hir::TypeName type,
|
||||||
|
uint32_t load_flags = 0);
|
||||||
Value* StoreRelease(Value* address, Value* value, uint32_t store_flags = 0);
|
Value* StoreRelease(Value* address, Value* value, uint32_t store_flags = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AnnotateLabel(uint64_t address, Label* label);
|
void AnnotateLabel(uint64_t address, Label* label);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PPCFrontend* frontend_;
|
PPCFrontend* frontend_;
|
||||||
|
|
||||||
// Reset whenever needed:
|
// Reset whenever needed:
|
||||||
StringBuffer* comment_buffer_;
|
StringBuffer* comment_buffer_;
|
||||||
|
|
||||||
// Reset each Emit:
|
// Reset each Emit:
|
||||||
bool with_debug_info_;
|
bool with_debug_info_;
|
||||||
runtime::FunctionInfo* symbol_info_;
|
runtime::FunctionInfo* symbol_info_;
|
||||||
uint64_t start_address_;
|
uint64_t start_address_;
|
||||||
uint64_t instr_count_;
|
uint64_t instr_count_;
|
||||||
Instr** instr_offset_list_;
|
Instr** instr_offset_list_;
|
||||||
Label** label_list_;
|
Label** label_list_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_PPC_PPC_HIR_BUILDER_H_
|
#endif // ALLOY_FRONTEND_PPC_PPC_HIR_BUILDER_H_
|
||||||
|
|
|
@ -13,11 +13,9 @@
|
||||||
|
|
||||||
#include <alloy/frontend/ppc/ppc_instr_tables.h>
|
#include <alloy/frontend/ppc/ppc_instr_tables.h>
|
||||||
|
|
||||||
|
namespace alloy {
|
||||||
using namespace alloy;
|
namespace frontend {
|
||||||
using namespace alloy::frontend;
|
namespace ppc {
|
||||||
using namespace alloy::frontend::ppc;
|
|
||||||
|
|
||||||
|
|
||||||
void InstrOperand::Dump(std::string& out_str) {
|
void InstrOperand::Dump(std::string& out_str) {
|
||||||
if (display) {
|
if (display) {
|
||||||
|
@ -92,21 +90,18 @@ void InstrOperand::Dump(std::string& out_str) {
|
||||||
out_str += buffer;
|
out_str += buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstrAccessBits::Clear() { spr = cr = gpr = fpr = 0; }
|
||||||
void InstrAccessBits::Clear() {
|
|
||||||
spr = cr = gpr = fpr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstrAccessBits::Extend(InstrAccessBits& other) {
|
void InstrAccessBits::Extend(InstrAccessBits& other) {
|
||||||
spr |= other.spr;
|
spr |= other.spr;
|
||||||
cr |= other.cr;
|
cr |= other.cr;
|
||||||
gpr |= other.gpr;
|
gpr |= other.gpr;
|
||||||
fpr |= other.fpr;
|
fpr |= other.fpr;
|
||||||
vr31_0 |= other.vr31_0;
|
vr31_0 |= other.vr31_0;
|
||||||
vr63_32 |= other.vr63_32;
|
vr63_32 |= other.vr63_32;
|
||||||
vr95_64 |= other.vr95_64;
|
vr95_64 |= other.vr95_64;
|
||||||
vr127_96 |= other.vr127_96;
|
vr127_96 |= other.vr127_96;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstrAccessBits::MarkAccess(InstrRegister& reg) {
|
void InstrAccessBits::MarkAccess(InstrRegister& reg) {
|
||||||
uint64_t bits = 0;
|
uint64_t bits = 0;
|
||||||
|
@ -128,7 +123,7 @@ void InstrAccessBits::MarkAccess(InstrRegister& reg) {
|
||||||
spr |= bits << (2 * 2);
|
spr |= bits << (2 * 2);
|
||||||
break;
|
break;
|
||||||
case InstrRegister::kCR:
|
case InstrRegister::kCR:
|
||||||
cr |= bits << (2 * reg.ordinal);
|
cr |= bits << (2 * reg.ordinal);
|
||||||
break;
|
break;
|
||||||
case InstrRegister::kFPSCR:
|
case InstrRegister::kFPSCR:
|
||||||
spr |= bits << (2 * 3);
|
spr |= bits << (2 * 3);
|
||||||
|
@ -281,41 +276,31 @@ void InstrAccessBits::Dump(std::string& out_str) {
|
||||||
out_str = str.str();
|
out_str = str.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InstrDisasm::Init(const char* name, const char* info, uint32_t flags) {
|
void InstrDisasm::Init(const char* name, const char* info, uint32_t flags) {
|
||||||
this->name = name;
|
this->name = name;
|
||||||
this->info = info;
|
this->info = info;
|
||||||
this->flags = flags;
|
this->flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstrDisasm::AddLR(InstrRegister::Access access) {
|
void InstrDisasm::AddLR(InstrRegister::Access access) {}
|
||||||
}
|
|
||||||
|
|
||||||
void InstrDisasm::AddCTR(InstrRegister::Access access) {
|
void InstrDisasm::AddCTR(InstrRegister::Access access) {}
|
||||||
}
|
|
||||||
|
|
||||||
void InstrDisasm::AddCR(uint32_t bf, InstrRegister::Access access) {
|
void InstrDisasm::AddCR(uint32_t bf, InstrRegister::Access access) {}
|
||||||
}
|
|
||||||
|
|
||||||
void InstrDisasm::AddFPSCR(InstrRegister::Access access) {
|
void InstrDisasm::AddFPSCR(InstrRegister::Access access) {}
|
||||||
}
|
|
||||||
|
|
||||||
void InstrDisasm::AddRegOperand(
|
void InstrDisasm::AddRegOperand(InstrRegister::RegisterSet set,
|
||||||
InstrRegister::RegisterSet set, uint32_t ordinal,
|
uint32_t ordinal, InstrRegister::Access access,
|
||||||
InstrRegister::Access access, const char* display) {
|
const char* display) {}
|
||||||
}
|
|
||||||
|
|
||||||
void InstrDisasm::AddSImmOperand(uint64_t value, size_t width,
|
void InstrDisasm::AddSImmOperand(uint64_t value, size_t width,
|
||||||
const char* display) {
|
const char* display) {}
|
||||||
}
|
|
||||||
|
|
||||||
void InstrDisasm::AddUImmOperand(uint64_t value, size_t width,
|
void InstrDisasm::AddUImmOperand(uint64_t value, size_t width,
|
||||||
const char* display) {
|
const char* display) {}
|
||||||
}
|
|
||||||
|
|
||||||
int InstrDisasm::Finish() {
|
int InstrDisasm::Finish() { return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstrDisasm::Dump(std::string& out_str, size_t pad) {
|
void InstrDisasm::Dump(std::string& out_str, size_t pad) {
|
||||||
out_str = name;
|
out_str = name;
|
||||||
|
@ -330,47 +315,55 @@ void InstrDisasm::Dump(std::string& out_str, size_t pad) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InstrType* GetInstrType(uint32_t code) {
|
||||||
InstrType* alloy::frontend::ppc::GetInstrType(uint32_t code) {
|
|
||||||
// Fast lookup via tables.
|
// Fast lookup via tables.
|
||||||
InstrType* slot = NULL;
|
InstrType* slot = NULL;
|
||||||
switch (code >> 26) {
|
switch (code >> 26) {
|
||||||
case 4:
|
case 4:
|
||||||
// Opcode = 4, index = bits 10-0 (10)
|
// Opcode = 4, index = bits 10-0 (10)
|
||||||
slot = alloy::frontend::ppc::tables::instr_table_4[XESELECTBITS(code, 0, 10)];
|
slot = alloy::frontend::ppc::tables::instr_table_4[XESELECTBITS(code, 0,
|
||||||
break;
|
10)];
|
||||||
case 19:
|
break;
|
||||||
// Opcode = 19, index = bits 10-1 (10)
|
case 19:
|
||||||
slot = alloy::frontend::ppc::tables::instr_table_19[XESELECTBITS(code, 1, 10)];
|
// Opcode = 19, index = bits 10-1 (10)
|
||||||
break;
|
slot = alloy::frontend::ppc::tables::instr_table_19[XESELECTBITS(code, 1,
|
||||||
case 30:
|
10)];
|
||||||
// Opcode = 30, index = bits 4-1 (4)
|
break;
|
||||||
// Special cased to an uber instruction.
|
case 30:
|
||||||
slot = alloy::frontend::ppc::tables::instr_table_30[XESELECTBITS(code, 0, 0)];
|
// Opcode = 30, index = bits 4-1 (4)
|
||||||
break;
|
// Special cased to an uber instruction.
|
||||||
case 31:
|
slot = alloy::frontend::ppc::tables::instr_table_30[XESELECTBITS(code, 0,
|
||||||
// Opcode = 31, index = bits 10-1 (10)
|
0)];
|
||||||
slot = alloy::frontend::ppc::tables::instr_table_31[XESELECTBITS(code, 1, 10)];
|
break;
|
||||||
break;
|
case 31:
|
||||||
case 58:
|
// Opcode = 31, index = bits 10-1 (10)
|
||||||
// Opcode = 58, index = bits 1-0 (2)
|
slot = alloy::frontend::ppc::tables::instr_table_31[XESELECTBITS(code, 1,
|
||||||
slot = alloy::frontend::ppc::tables::instr_table_58[XESELECTBITS(code, 0, 1)];
|
10)];
|
||||||
break;
|
break;
|
||||||
case 59:
|
case 58:
|
||||||
// Opcode = 59, index = bits 5-1 (5)
|
// Opcode = 58, index = bits 1-0 (2)
|
||||||
slot = alloy::frontend::ppc::tables::instr_table_59[XESELECTBITS(code, 1, 5)];
|
slot = alloy::frontend::ppc::tables::instr_table_58[XESELECTBITS(code, 0,
|
||||||
break;
|
1)];
|
||||||
case 62:
|
break;
|
||||||
// Opcode = 62, index = bits 1-0 (2)
|
case 59:
|
||||||
slot = alloy::frontend::ppc::tables::instr_table_62[XESELECTBITS(code, 0, 1)];
|
// Opcode = 59, index = bits 5-1 (5)
|
||||||
break;
|
slot = alloy::frontend::ppc::tables::instr_table_59[XESELECTBITS(code, 1,
|
||||||
case 63:
|
5)];
|
||||||
// Opcode = 63, index = bits 10-1 (10)
|
break;
|
||||||
slot = alloy::frontend::ppc::tables::instr_table_63[XESELECTBITS(code, 1, 10)];
|
case 62:
|
||||||
break;
|
// Opcode = 62, index = bits 1-0 (2)
|
||||||
default:
|
slot = alloy::frontend::ppc::tables::instr_table_62[XESELECTBITS(code, 0,
|
||||||
slot = alloy::frontend::ppc::tables::instr_table[XESELECTBITS(code, 26, 31)];
|
1)];
|
||||||
break;
|
break;
|
||||||
|
case 63:
|
||||||
|
// Opcode = 63, index = bits 10-1 (10)
|
||||||
|
slot = alloy::frontend::ppc::tables::instr_table_63[XESELECTBITS(code, 1,
|
||||||
|
10)];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
slot =
|
||||||
|
alloy::frontend::ppc::tables::instr_table[XESELECTBITS(code, 26, 31)];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (slot && slot->opcode) {
|
if (slot && slot->opcode) {
|
||||||
return slot;
|
return slot;
|
||||||
|
@ -379,8 +372,7 @@ InstrType* alloy::frontend::ppc::GetInstrType(uint32_t code) {
|
||||||
// Slow lookup via linear scan.
|
// Slow lookup via linear scan.
|
||||||
// This is primarily due to laziness. It could be made fast like the others.
|
// This is primarily due to laziness. It could be made fast like the others.
|
||||||
for (size_t n = 0;
|
for (size_t n = 0;
|
||||||
n < XECOUNT(alloy::frontend::ppc::tables::instr_table_scan);
|
n < XECOUNT(alloy::frontend::ppc::tables::instr_table_scan); n++) {
|
||||||
n++) {
|
|
||||||
slot = &(alloy::frontend::ppc::tables::instr_table_scan[n]);
|
slot = &(alloy::frontend::ppc::tables::instr_table_scan[n]);
|
||||||
if (slot->opcode == (code & slot->opcode_mask)) {
|
if (slot->opcode == (code & slot->opcode_mask)) {
|
||||||
return slot;
|
return slot;
|
||||||
|
@ -390,7 +382,7 @@ InstrType* alloy::frontend::ppc::GetInstrType(uint32_t code) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int alloy::frontend::ppc::RegisterInstrEmit(uint32_t code, InstrEmitFn emit) {
|
int RegisterInstrEmit(uint32_t code, InstrEmitFn emit) {
|
||||||
InstrType* instr_type = GetInstrType(code);
|
InstrType* instr_type = GetInstrType(code);
|
||||||
XEASSERTNOTNULL(instr_type);
|
XEASSERTNOTNULL(instr_type);
|
||||||
if (!instr_type) {
|
if (!instr_type) {
|
||||||
|
@ -400,3 +392,7 @@ int alloy::frontend::ppc::RegisterInstrEmit(uint32_t code, InstrEmitFn emit) {
|
||||||
instr_type->emit = emit;
|
instr_type->emit = emit;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ppc
|
||||||
|
} // namespace frontend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -15,81 +15,73 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
|
||||||
|
|
||||||
// TODO(benvanik): rename these
|
// TODO(benvanik): rename these
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kXEPPCInstrFormatI = 0,
|
kXEPPCInstrFormatI = 0,
|
||||||
kXEPPCInstrFormatB = 1,
|
kXEPPCInstrFormatB = 1,
|
||||||
kXEPPCInstrFormatSC = 2,
|
kXEPPCInstrFormatSC = 2,
|
||||||
kXEPPCInstrFormatD = 3,
|
kXEPPCInstrFormatD = 3,
|
||||||
kXEPPCInstrFormatDS = 4,
|
kXEPPCInstrFormatDS = 4,
|
||||||
kXEPPCInstrFormatX = 5,
|
kXEPPCInstrFormatX = 5,
|
||||||
kXEPPCInstrFormatXL = 6,
|
kXEPPCInstrFormatXL = 6,
|
||||||
kXEPPCInstrFormatXFX = 7,
|
kXEPPCInstrFormatXFX = 7,
|
||||||
kXEPPCInstrFormatXFL = 8,
|
kXEPPCInstrFormatXFL = 8,
|
||||||
kXEPPCInstrFormatXS = 9,
|
kXEPPCInstrFormatXS = 9,
|
||||||
kXEPPCInstrFormatXO = 10,
|
kXEPPCInstrFormatXO = 10,
|
||||||
kXEPPCInstrFormatA = 11,
|
kXEPPCInstrFormatA = 11,
|
||||||
kXEPPCInstrFormatM = 12,
|
kXEPPCInstrFormatM = 12,
|
||||||
kXEPPCInstrFormatMD = 13,
|
kXEPPCInstrFormatMD = 13,
|
||||||
kXEPPCInstrFormatMDS = 14,
|
kXEPPCInstrFormatMDS = 14,
|
||||||
kXEPPCInstrFormatVXA = 15,
|
kXEPPCInstrFormatVXA = 15,
|
||||||
kXEPPCInstrFormatVX = 16,
|
kXEPPCInstrFormatVX = 16,
|
||||||
kXEPPCInstrFormatVXR = 17,
|
kXEPPCInstrFormatVXR = 17,
|
||||||
kXEPPCInstrFormatVX128 = 18,
|
kXEPPCInstrFormatVX128 = 18,
|
||||||
kXEPPCInstrFormatVX128_1 = 19,
|
kXEPPCInstrFormatVX128_1 = 19,
|
||||||
kXEPPCInstrFormatVX128_2 = 20,
|
kXEPPCInstrFormatVX128_2 = 20,
|
||||||
kXEPPCInstrFormatVX128_3 = 21,
|
kXEPPCInstrFormatVX128_3 = 21,
|
||||||
kXEPPCInstrFormatVX128_4 = 22,
|
kXEPPCInstrFormatVX128_4 = 22,
|
||||||
kXEPPCInstrFormatVX128_5 = 23,
|
kXEPPCInstrFormatVX128_5 = 23,
|
||||||
kXEPPCInstrFormatVX128_P = 24,
|
kXEPPCInstrFormatVX128_P = 24,
|
||||||
kXEPPCInstrFormatVX128_R = 25,
|
kXEPPCInstrFormatVX128_R = 25,
|
||||||
kXEPPCInstrFormatXDSS = 26,
|
kXEPPCInstrFormatXDSS = 26,
|
||||||
} xe_ppc_instr_format_e;
|
} xe_ppc_instr_format_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kXEPPCInstrMaskVXR = 0xFC0003FF,
|
kXEPPCInstrMaskVXR = 0xFC0003FF,
|
||||||
kXEPPCInstrMaskVXA = 0xFC00003F,
|
kXEPPCInstrMaskVXA = 0xFC00003F,
|
||||||
kXEPPCInstrMaskVX128 = 0xFC0003D0,
|
kXEPPCInstrMaskVX128 = 0xFC0003D0,
|
||||||
kXEPPCInstrMaskVX128_1 = 0xFC0007F3,
|
kXEPPCInstrMaskVX128_1 = 0xFC0007F3,
|
||||||
kXEPPCInstrMaskVX128_2 = 0xFC000210,
|
kXEPPCInstrMaskVX128_2 = 0xFC000210,
|
||||||
kXEPPCInstrMaskVX128_3 = 0xFC0007F0,
|
kXEPPCInstrMaskVX128_3 = 0xFC0007F0,
|
||||||
kXEPPCInstrMaskVX128_4 = 0xFC000730,
|
kXEPPCInstrMaskVX128_4 = 0xFC000730,
|
||||||
kXEPPCInstrMaskVX128_5 = 0xFC000010,
|
kXEPPCInstrMaskVX128_5 = 0xFC000010,
|
||||||
kXEPPCInstrMaskVX128_P = 0xFC000630,
|
kXEPPCInstrMaskVX128_P = 0xFC000630,
|
||||||
kXEPPCInstrMaskVX128_R = 0xFC000390,
|
kXEPPCInstrMaskVX128_R = 0xFC000390,
|
||||||
} xe_ppc_instr_mask_e;
|
} xe_ppc_instr_mask_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kXEPPCInstrTypeGeneral = (1 << 0),
|
kXEPPCInstrTypeGeneral = (1 << 0),
|
||||||
kXEPPCInstrTypeBranch = (1 << 1),
|
kXEPPCInstrTypeBranch = (1 << 1),
|
||||||
kXEPPCInstrTypeBranchCond = kXEPPCInstrTypeBranch | (1 << 2),
|
kXEPPCInstrTypeBranchCond = kXEPPCInstrTypeBranch | (1 << 2),
|
||||||
kXEPPCInstrTypeBranchAlways = kXEPPCInstrTypeBranch | (1 << 3),
|
kXEPPCInstrTypeBranchAlways = kXEPPCInstrTypeBranch | (1 << 3),
|
||||||
kXEPPCInstrTypeSyscall = (1 << 4),
|
kXEPPCInstrTypeSyscall = (1 << 4),
|
||||||
} xe_ppc_instr_type_e;
|
} xe_ppc_instr_type_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kXEPPCInstrFlagReserved = 0,
|
kXEPPCInstrFlagReserved = 0,
|
||||||
} xe_ppc_instr_flag_e;
|
} xe_ppc_instr_flag_e;
|
||||||
|
|
||||||
|
|
||||||
class InstrType;
|
class InstrType;
|
||||||
|
|
||||||
|
static inline int64_t XEEXTS16(uint32_t v) { return (int64_t)((int16_t)v); }
|
||||||
static inline int64_t XEEXTS16(uint32_t v) {
|
|
||||||
return (int64_t)((int16_t)v);
|
|
||||||
}
|
|
||||||
static inline int64_t XEEXTS26(uint32_t v) {
|
static inline int64_t XEEXTS26(uint32_t v) {
|
||||||
return (int64_t)(v & 0x02000000 ? (int32_t)v | 0xFC000000 : (int32_t)(v));
|
return (int64_t)(v & 0x02000000 ? (int32_t)v | 0xFC000000 : (int32_t)(v));
|
||||||
}
|
}
|
||||||
static inline uint64_t XEEXTZ16(uint32_t v) {
|
static inline uint64_t XEEXTZ16(uint32_t v) { return (uint64_t)((uint16_t)v); }
|
||||||
return (uint64_t)((uint16_t)v);
|
|
||||||
}
|
|
||||||
static inline uint64_t XEMASK(uint32_t mstart, uint32_t mstop) {
|
static inline uint64_t XEMASK(uint32_t mstart, uint32_t mstop) {
|
||||||
// if mstart ≤ mstop then
|
// if mstart ≤ mstop then
|
||||||
// mask[mstart:mstop] = ones
|
// mask[mstart:mstop] = ones
|
||||||
|
@ -105,289 +97,338 @@ static inline uint64_t XEMASK(uint32_t mstart, uint32_t mstop) {
|
||||||
return mstart <= mstop ? value : ~value;
|
return mstart <= mstop ? value : ~value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
InstrType* type;
|
InstrType* type;
|
||||||
uint64_t address;
|
uint64_t address;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
uint32_t code;
|
uint32_t code;
|
||||||
|
|
||||||
// kXEPPCInstrFormatI
|
// kXEPPCInstrFormatI
|
||||||
struct {
|
struct {
|
||||||
uint32_t LK : 1;
|
uint32_t LK : 1;
|
||||||
uint32_t AA : 1;
|
uint32_t AA : 1;
|
||||||
uint32_t LI : 24;
|
uint32_t LI : 24;
|
||||||
uint32_t : 6;
|
uint32_t:
|
||||||
|
6;
|
||||||
} I;
|
} I;
|
||||||
// kXEPPCInstrFormatB
|
// kXEPPCInstrFormatB
|
||||||
struct {
|
struct {
|
||||||
uint32_t LK : 1;
|
uint32_t LK : 1;
|
||||||
uint32_t AA : 1;
|
uint32_t AA : 1;
|
||||||
uint32_t BD : 14;
|
uint32_t BD : 14;
|
||||||
uint32_t BI : 5;
|
uint32_t BI : 5;
|
||||||
uint32_t BO : 5;
|
uint32_t BO : 5;
|
||||||
uint32_t : 6;
|
uint32_t:
|
||||||
|
6;
|
||||||
} B;
|
} B;
|
||||||
|
|
||||||
// kXEPPCInstrFormatSC
|
// kXEPPCInstrFormatSC
|
||||||
// kXEPPCInstrFormatD
|
// kXEPPCInstrFormatD
|
||||||
struct {
|
struct {
|
||||||
uint32_t DS : 16;
|
uint32_t DS : 16;
|
||||||
uint32_t RA : 5;
|
uint32_t RA : 5;
|
||||||
uint32_t RT : 5;
|
uint32_t RT : 5;
|
||||||
uint32_t : 6;
|
uint32_t:
|
||||||
|
6;
|
||||||
} D;
|
} D;
|
||||||
// kXEPPCInstrFormatDS
|
// kXEPPCInstrFormatDS
|
||||||
struct {
|
struct {
|
||||||
uint32_t : 2;
|
uint32_t:
|
||||||
uint32_t DS : 14;
|
2;
|
||||||
uint32_t RA : 5;
|
uint32_t DS : 14;
|
||||||
uint32_t RT : 5;
|
uint32_t RA : 5;
|
||||||
uint32_t : 6;
|
uint32_t RT : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} DS;
|
} DS;
|
||||||
// kXEPPCInstrFormatX
|
// kXEPPCInstrFormatX
|
||||||
struct {
|
struct {
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t : 10;
|
uint32_t:
|
||||||
uint32_t RB : 5;
|
10;
|
||||||
uint32_t RA : 5;
|
uint32_t RB : 5;
|
||||||
uint32_t RT : 5;
|
uint32_t RA : 5;
|
||||||
uint32_t : 6;
|
uint32_t RT : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} X;
|
} X;
|
||||||
// kXEPPCInstrFormatXL
|
// kXEPPCInstrFormatXL
|
||||||
struct {
|
struct {
|
||||||
uint32_t LK : 1;
|
uint32_t LK : 1;
|
||||||
uint32_t : 10;
|
uint32_t:
|
||||||
uint32_t BB : 5;
|
10;
|
||||||
uint32_t BI : 5;
|
uint32_t BB : 5;
|
||||||
uint32_t BO : 5;
|
uint32_t BI : 5;
|
||||||
uint32_t : 6;
|
uint32_t BO : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} XL;
|
} XL;
|
||||||
// kXEPPCInstrFormatXFX
|
// kXEPPCInstrFormatXFX
|
||||||
struct {
|
struct {
|
||||||
uint32_t : 1;
|
uint32_t:
|
||||||
uint32_t : 10;
|
1;
|
||||||
uint32_t spr : 10;
|
uint32_t:
|
||||||
uint32_t RT : 5;
|
10;
|
||||||
uint32_t : 6;
|
uint32_t spr : 10;
|
||||||
|
uint32_t RT : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} XFX;
|
} XFX;
|
||||||
// kXEPPCInstrFormatXFL
|
// kXEPPCInstrFormatXFL
|
||||||
struct {
|
struct {
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t : 10;
|
uint32_t:
|
||||||
uint32_t RB : 5;
|
10;
|
||||||
uint32_t W : 1;
|
uint32_t RB : 5;
|
||||||
uint32_t FM : 8;
|
uint32_t W : 1;
|
||||||
uint32_t L : 1;
|
uint32_t FM : 8;
|
||||||
uint32_t : 6;
|
uint32_t L : 1;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} XFL;
|
} XFL;
|
||||||
// kXEPPCInstrFormatXS
|
// kXEPPCInstrFormatXS
|
||||||
struct {
|
struct {
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t SH5 : 1;
|
uint32_t SH5 : 1;
|
||||||
uint32_t : 9;
|
uint32_t:
|
||||||
uint32_t SH : 5;
|
9;
|
||||||
uint32_t RA : 5;
|
uint32_t SH : 5;
|
||||||
uint32_t RT : 5;
|
uint32_t RA : 5;
|
||||||
uint32_t : 6;
|
uint32_t RT : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} XS;
|
} XS;
|
||||||
// kXEPPCInstrFormatXO
|
// kXEPPCInstrFormatXO
|
||||||
struct {
|
struct {
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t : 9;
|
uint32_t:
|
||||||
uint32_t OE : 1;
|
9;
|
||||||
uint32_t RB : 5;
|
uint32_t OE : 1;
|
||||||
uint32_t RA : 5;
|
uint32_t RB : 5;
|
||||||
uint32_t RT : 5;
|
uint32_t RA : 5;
|
||||||
uint32_t : 6;
|
uint32_t RT : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} XO;
|
} XO;
|
||||||
// kXEPPCInstrFormatA
|
// kXEPPCInstrFormatA
|
||||||
struct {
|
struct {
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t XO : 5;
|
uint32_t XO : 5;
|
||||||
uint32_t FRC : 5;
|
uint32_t FRC : 5;
|
||||||
uint32_t FRB : 5;
|
uint32_t FRB : 5;
|
||||||
uint32_t FRA : 5;
|
uint32_t FRA : 5;
|
||||||
uint32_t FRT : 5;
|
uint32_t FRT : 5;
|
||||||
uint32_t : 6;
|
uint32_t:
|
||||||
|
6;
|
||||||
} A;
|
} A;
|
||||||
// kXEPPCInstrFormatM
|
// kXEPPCInstrFormatM
|
||||||
struct {
|
struct {
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t ME : 5;
|
uint32_t ME : 5;
|
||||||
uint32_t MB : 5;
|
uint32_t MB : 5;
|
||||||
uint32_t SH : 5;
|
uint32_t SH : 5;
|
||||||
uint32_t RA : 5;
|
uint32_t RA : 5;
|
||||||
uint32_t RT : 5;
|
uint32_t RT : 5;
|
||||||
uint32_t : 6;
|
uint32_t:
|
||||||
|
6;
|
||||||
} M;
|
} M;
|
||||||
// kXEPPCInstrFormatMD
|
// kXEPPCInstrFormatMD
|
||||||
struct {
|
struct {
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t SH5 : 1;
|
uint32_t SH5 : 1;
|
||||||
uint32_t idx : 3;
|
uint32_t idx : 3;
|
||||||
uint32_t MB5 : 1;
|
uint32_t MB5 : 1;
|
||||||
uint32_t MB : 5;
|
uint32_t MB : 5;
|
||||||
uint32_t SH : 5;
|
uint32_t SH : 5;
|
||||||
uint32_t RA : 5;
|
uint32_t RA : 5;
|
||||||
uint32_t RT : 5;
|
uint32_t RT : 5;
|
||||||
uint32_t : 6;
|
uint32_t:
|
||||||
|
6;
|
||||||
} MD;
|
} MD;
|
||||||
// kXEPPCInstrFormatMDS
|
// kXEPPCInstrFormatMDS
|
||||||
struct {
|
struct {
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t idx : 4;
|
uint32_t idx : 4;
|
||||||
uint32_t MB5 : 1;
|
uint32_t MB5 : 1;
|
||||||
uint32_t MB : 5;
|
uint32_t MB : 5;
|
||||||
uint32_t RB : 5;
|
uint32_t RB : 5;
|
||||||
uint32_t RA : 5;
|
uint32_t RA : 5;
|
||||||
uint32_t RT : 5;
|
uint32_t RT : 5;
|
||||||
uint32_t : 6;
|
uint32_t:
|
||||||
|
6;
|
||||||
} MDS;
|
} MDS;
|
||||||
// kXEPPCInstrFormatVXA
|
// kXEPPCInstrFormatVXA
|
||||||
struct {
|
struct {
|
||||||
uint32_t : 6;
|
uint32_t:
|
||||||
uint32_t VC : 5;
|
6;
|
||||||
uint32_t VB : 5;
|
uint32_t VC : 5;
|
||||||
uint32_t VA : 5;
|
uint32_t VB : 5;
|
||||||
uint32_t VD : 5;
|
uint32_t VA : 5;
|
||||||
uint32_t : 6;
|
uint32_t VD : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VXA;
|
} VXA;
|
||||||
// kXEPPCInstrFormatVX
|
// kXEPPCInstrFormatVX
|
||||||
struct {
|
struct {
|
||||||
uint32_t : 11;
|
uint32_t:
|
||||||
uint32_t VB : 5;
|
11;
|
||||||
uint32_t VA : 5;
|
uint32_t VB : 5;
|
||||||
uint32_t VD : 5;
|
uint32_t VA : 5;
|
||||||
uint32_t : 6;
|
uint32_t VD : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VX;
|
} VX;
|
||||||
// kXEPPCInstrFormatVXR
|
// kXEPPCInstrFormatVXR
|
||||||
struct {
|
struct {
|
||||||
uint32_t : 10;
|
uint32_t:
|
||||||
uint32_t Rc : 1;
|
10;
|
||||||
uint32_t VB : 5;
|
uint32_t Rc : 1;
|
||||||
uint32_t VA : 5;
|
uint32_t VB : 5;
|
||||||
uint32_t VD : 5;
|
uint32_t VA : 5;
|
||||||
uint32_t : 6;
|
uint32_t VD : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VXR;
|
} VXR;
|
||||||
// kXEPPCInstrFormatVX128
|
// kXEPPCInstrFormatVX128
|
||||||
struct {
|
struct {
|
||||||
// VD128 = VD128l | (VD128h << 5)
|
// VD128 = VD128l | (VD128h << 5)
|
||||||
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
||||||
// VB128 = VB128l | (VB128h << 5)
|
// VB128 = VB128l | (VB128h << 5)
|
||||||
uint32_t VB128h : 2;
|
uint32_t VB128h : 2;
|
||||||
uint32_t VD128h : 2;
|
uint32_t VD128h : 2;
|
||||||
uint32_t : 1;
|
uint32_t:
|
||||||
uint32_t VA128h : 1;
|
1;
|
||||||
uint32_t : 4;
|
uint32_t VA128h : 1;
|
||||||
uint32_t VA128H : 1;
|
uint32_t:
|
||||||
uint32_t VB128l : 5;
|
4;
|
||||||
uint32_t VA128l : 5;
|
uint32_t VA128H : 1;
|
||||||
uint32_t VD128l : 5;
|
uint32_t VB128l : 5;
|
||||||
uint32_t : 6;
|
uint32_t VA128l : 5;
|
||||||
|
uint32_t VD128l : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VX128;
|
} VX128;
|
||||||
// kXEPPCInstrFormatVX128_1
|
// kXEPPCInstrFormatVX128_1
|
||||||
struct {
|
struct {
|
||||||
// VD128 = VD128l | (VD128h << 5)
|
// VD128 = VD128l | (VD128h << 5)
|
||||||
uint32_t : 2;
|
uint32_t:
|
||||||
uint32_t VD128h : 2;
|
2;
|
||||||
uint32_t : 7;
|
uint32_t VD128h : 2;
|
||||||
uint32_t RB : 5;
|
uint32_t:
|
||||||
uint32_t RA : 5;
|
7;
|
||||||
uint32_t VD128l : 5;
|
uint32_t RB : 5;
|
||||||
uint32_t : 6;
|
uint32_t RA : 5;
|
||||||
|
uint32_t VD128l : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VX128_1;
|
} VX128_1;
|
||||||
// kXEPPCInstrFormatVX128_2
|
// kXEPPCInstrFormatVX128_2
|
||||||
struct {
|
struct {
|
||||||
// VD128 = VD128l | (VD128h << 5)
|
// VD128 = VD128l | (VD128h << 5)
|
||||||
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
||||||
// VB128 = VB128l | (VB128h << 5)
|
// VB128 = VB128l | (VB128h << 5)
|
||||||
uint32_t VB128h : 2;
|
uint32_t VB128h : 2;
|
||||||
uint32_t VD128h : 2;
|
uint32_t VD128h : 2;
|
||||||
uint32_t : 1;
|
uint32_t:
|
||||||
uint32_t VA128h : 1;
|
1;
|
||||||
uint32_t VC : 3;
|
uint32_t VA128h : 1;
|
||||||
uint32_t : 1;
|
uint32_t VC : 3;
|
||||||
uint32_t VA128H : 1;
|
uint32_t:
|
||||||
uint32_t VB128l : 5;
|
1;
|
||||||
uint32_t VA128l : 5;
|
uint32_t VA128H : 1;
|
||||||
uint32_t VD128l : 5;
|
uint32_t VB128l : 5;
|
||||||
uint32_t : 6;
|
uint32_t VA128l : 5;
|
||||||
|
uint32_t VD128l : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VX128_2;
|
} VX128_2;
|
||||||
// kXEPPCInstrFormatVX128_3
|
// kXEPPCInstrFormatVX128_3
|
||||||
struct {
|
struct {
|
||||||
// VD128 = VD128l | (VD128h << 5)
|
// VD128 = VD128l | (VD128h << 5)
|
||||||
// VB128 = VB128l | (VB128h << 5)
|
// VB128 = VB128l | (VB128h << 5)
|
||||||
uint32_t VB128h : 2;
|
uint32_t VB128h : 2;
|
||||||
uint32_t VD128h : 2;
|
uint32_t VD128h : 2;
|
||||||
uint32_t : 7;
|
uint32_t:
|
||||||
uint32_t VB128l : 5;
|
7;
|
||||||
uint32_t IMM : 5;
|
uint32_t VB128l : 5;
|
||||||
uint32_t VD128l : 5;
|
uint32_t IMM : 5;
|
||||||
uint32_t : 6;
|
uint32_t VD128l : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VX128_3;
|
} VX128_3;
|
||||||
// kXEPPCInstrFormatVX128_4
|
// kXEPPCInstrFormatVX128_4
|
||||||
struct {
|
struct {
|
||||||
// VD128 = VD128l | (VD128h << 5)
|
// VD128 = VD128l | (VD128h << 5)
|
||||||
// VB128 = VB128l | (VB128h << 5)
|
// VB128 = VB128l | (VB128h << 5)
|
||||||
uint32_t VB128h : 2;
|
uint32_t VB128h : 2;
|
||||||
uint32_t VD128h : 2;
|
uint32_t VD128h : 2;
|
||||||
uint32_t : 2;
|
uint32_t:
|
||||||
uint32_t z : 2;
|
2;
|
||||||
uint32_t : 3;
|
uint32_t z : 2;
|
||||||
uint32_t VB128l : 5;
|
uint32_t:
|
||||||
uint32_t IMM : 5;
|
3;
|
||||||
uint32_t VD128l : 5;
|
uint32_t VB128l : 5;
|
||||||
uint32_t : 6;
|
uint32_t IMM : 5;
|
||||||
|
uint32_t VD128l : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VX128_4;
|
} VX128_4;
|
||||||
// kXEPPCInstrFormatVX128_5
|
// kXEPPCInstrFormatVX128_5
|
||||||
struct {
|
struct {
|
||||||
// VD128 = VD128l | (VD128h << 5)
|
// VD128 = VD128l | (VD128h << 5)
|
||||||
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
||||||
// VB128 = VB128l | (VB128h << 5)
|
// VB128 = VB128l | (VB128h << 5)
|
||||||
uint32_t VB128h : 2;
|
uint32_t VB128h : 2;
|
||||||
uint32_t VD128h : 2;
|
uint32_t VD128h : 2;
|
||||||
uint32_t : 1;
|
uint32_t:
|
||||||
uint32_t VA128h : 1;
|
1;
|
||||||
uint32_t SH : 4;
|
uint32_t VA128h : 1;
|
||||||
uint32_t VA128H : 1;
|
uint32_t SH : 4;
|
||||||
uint32_t VB128l : 5;
|
uint32_t VA128H : 1;
|
||||||
uint32_t VA128l : 5;
|
uint32_t VB128l : 5;
|
||||||
uint32_t VD128l : 5;
|
uint32_t VA128l : 5;
|
||||||
uint32_t : 6;
|
uint32_t VD128l : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VX128_5;
|
} VX128_5;
|
||||||
// kXEPPCInstrFormatVX128_P
|
// kXEPPCInstrFormatVX128_P
|
||||||
struct {
|
struct {
|
||||||
// VD128 = VD128l | (VD128h << 5)
|
// VD128 = VD128l | (VD128h << 5)
|
||||||
// VB128 = VB128l | (VB128h << 5)
|
// VB128 = VB128l | (VB128h << 5)
|
||||||
// PERM = PERMl | (PERMh << 5)
|
// PERM = PERMl | (PERMh << 5)
|
||||||
uint32_t VB128h : 2;
|
uint32_t VB128h : 2;
|
||||||
uint32_t VD128h : 2;
|
uint32_t VD128h : 2;
|
||||||
uint32_t : 2;
|
uint32_t:
|
||||||
uint32_t PERMh : 3;
|
2;
|
||||||
uint32_t : 2;
|
uint32_t PERMh : 3;
|
||||||
uint32_t VB128l : 5;
|
uint32_t:
|
||||||
uint32_t PERMl : 5;
|
2;
|
||||||
uint32_t VD128l : 5;
|
uint32_t VB128l : 5;
|
||||||
uint32_t : 6;
|
uint32_t PERMl : 5;
|
||||||
|
uint32_t VD128l : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VX128_P;
|
} VX128_P;
|
||||||
// kXEPPCInstrFormatVX128_R
|
// kXEPPCInstrFormatVX128_R
|
||||||
struct {
|
struct {
|
||||||
// VD128 = VD128l | (VD128h << 5)
|
// VD128 = VD128l | (VD128h << 5)
|
||||||
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
||||||
// VB128 = VB128l | (VB128h << 5)
|
// VB128 = VB128l | (VB128h << 5)
|
||||||
uint32_t VB128h : 2;
|
uint32_t VB128h : 2;
|
||||||
uint32_t VD128h : 2;
|
uint32_t VD128h : 2;
|
||||||
uint32_t : 1;
|
uint32_t:
|
||||||
uint32_t VA128h : 1;
|
1;
|
||||||
uint32_t Rc : 1;
|
uint32_t VA128h : 1;
|
||||||
uint32_t : 3;
|
uint32_t Rc : 1;
|
||||||
uint32_t VA128H : 1;
|
uint32_t:
|
||||||
uint32_t VB128l : 5;
|
3;
|
||||||
uint32_t VA128l : 5;
|
uint32_t VA128H : 1;
|
||||||
uint32_t VD128l : 5;
|
uint32_t VB128l : 5;
|
||||||
uint32_t : 6;
|
uint32_t VA128l : 5;
|
||||||
|
uint32_t VD128l : 5;
|
||||||
|
uint32_t:
|
||||||
|
6;
|
||||||
} VX128_R;
|
} VX128_R;
|
||||||
// kXEPPCInstrFormatXDSS
|
// kXEPPCInstrFormatXDSS
|
||||||
struct {
|
struct {
|
||||||
|
@ -395,31 +436,29 @@ typedef struct {
|
||||||
};
|
};
|
||||||
} InstrData;
|
} InstrData;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum RegisterSet {
|
enum RegisterSet {
|
||||||
kXER,
|
kXER,
|
||||||
kLR,
|
kLR,
|
||||||
kCTR,
|
kCTR,
|
||||||
kCR, // 0-7
|
kCR, // 0-7
|
||||||
kFPSCR,
|
kFPSCR,
|
||||||
kGPR, // 0-31
|
kGPR, // 0-31
|
||||||
kFPR, // 0-31
|
kFPR, // 0-31
|
||||||
kVMX, // 0-127
|
kVMX, // 0-127
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Access {
|
enum Access {
|
||||||
kRead = 1 << 0,
|
kRead = 1 << 0,
|
||||||
kWrite = 1 << 1,
|
kWrite = 1 << 1,
|
||||||
kReadWrite = kRead | kWrite,
|
kReadWrite = kRead | kWrite,
|
||||||
};
|
};
|
||||||
|
|
||||||
RegisterSet set;
|
RegisterSet set;
|
||||||
uint32_t ordinal;
|
uint32_t ordinal;
|
||||||
Access access;
|
Access access;
|
||||||
} InstrRegister;
|
} InstrRegister;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum OperandType {
|
enum OperandType {
|
||||||
kRegister,
|
kRegister,
|
||||||
|
@ -431,30 +470,34 @@ typedef struct {
|
||||||
union {
|
union {
|
||||||
InstrRegister reg;
|
InstrRegister reg;
|
||||||
struct {
|
struct {
|
||||||
bool is_signed;
|
bool is_signed;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
size_t width;
|
size_t width;
|
||||||
} imm;
|
} imm;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Dump(std::string& out_str);
|
void Dump(std::string& out_str);
|
||||||
} InstrOperand;
|
} InstrOperand;
|
||||||
|
|
||||||
|
|
||||||
class InstrAccessBits {
|
class InstrAccessBits {
|
||||||
public:
|
public:
|
||||||
InstrAccessBits() :
|
InstrAccessBits()
|
||||||
spr(0), cr(0), gpr(0), fpr(0),
|
: spr(0),
|
||||||
vr31_0(0), vr63_32(0), vr95_64(0), vr127_96(0) {
|
cr(0),
|
||||||
}
|
gpr(0),
|
||||||
|
fpr(0),
|
||||||
|
vr31_0(0),
|
||||||
|
vr63_32(0),
|
||||||
|
vr95_64(0),
|
||||||
|
vr127_96(0) {}
|
||||||
|
|
||||||
// Bitmasks derived from the accesses to registers.
|
// Bitmasks derived from the accesses to registers.
|
||||||
// Format is 2 bits for each register, even bits indicating reads and odds
|
// Format is 2 bits for each register, even bits indicating reads and odds
|
||||||
// indicating writes.
|
// indicating writes.
|
||||||
uint64_t spr; // fpcsr/ctr/lr/xer
|
uint64_t spr; // fpcsr/ctr/lr/xer
|
||||||
uint64_t cr; // cr7/6/5/4/3/2/1/0
|
uint64_t cr; // cr7/6/5/4/3/2/1/0
|
||||||
uint64_t gpr; // r31-0
|
uint64_t gpr; // r31-0
|
||||||
uint64_t fpr; // f31-0
|
uint64_t fpr; // f31-0
|
||||||
uint64_t vr31_0;
|
uint64_t vr31_0;
|
||||||
uint64_t vr63_32;
|
uint64_t vr63_32;
|
||||||
uint64_t vr95_64;
|
uint64_t vr95_64;
|
||||||
|
@ -466,21 +509,20 @@ public:
|
||||||
void Dump(std::string& out_str);
|
void Dump(std::string& out_str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class InstrDisasm {
|
class InstrDisasm {
|
||||||
public:
|
public:
|
||||||
enum Flags {
|
enum Flags {
|
||||||
kOE = 1 << 0,
|
kOE = 1 << 0,
|
||||||
kRc = 1 << 1,
|
kRc = 1 << 1,
|
||||||
kCA = 1 << 2,
|
kCA = 1 << 2,
|
||||||
kLR = 1 << 4,
|
kLR = 1 << 4,
|
||||||
kFP = 1 << 5,
|
kFP = 1 << 5,
|
||||||
kVMX = 1 << 6,
|
kVMX = 1 << 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* info;
|
const char* info;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
||||||
void Init(const char* name, const char* info, uint32_t flags);
|
void Init(const char* name, const char* info, uint32_t flags);
|
||||||
void AddLR(InstrRegister::Access access);
|
void AddLR(InstrRegister::Access access);
|
||||||
|
@ -496,32 +538,27 @@ public:
|
||||||
void Dump(std::string& out_str, size_t pad = 13);
|
void Dump(std::string& out_str, size_t pad = 13);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef void (*InstrDisasmFn)(InstrData& i, StringBuffer* str);
|
typedef void (*InstrDisasmFn)(InstrData& i, StringBuffer* str);
|
||||||
typedef void* InstrEmitFn;
|
typedef void* InstrEmitFn;
|
||||||
|
|
||||||
|
|
||||||
class InstrType {
|
class InstrType {
|
||||||
public:
|
public:
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
uint32_t opcode_mask; // Only used for certain opcodes (altivec, etc).
|
uint32_t opcode_mask; // Only used for certain opcodes (altivec, etc).
|
||||||
uint32_t format; // xe_ppc_instr_format_e
|
uint32_t format; // xe_ppc_instr_format_e
|
||||||
uint32_t type; // xe_ppc_instr_type_e
|
uint32_t type; // xe_ppc_instr_type_e
|
||||||
uint32_t flags; // xe_ppc_instr_flag_e
|
uint32_t flags; // xe_ppc_instr_flag_e
|
||||||
InstrDisasmFn disasm;
|
InstrDisasmFn disasm;
|
||||||
char name[16];
|
char name[16];
|
||||||
|
|
||||||
InstrEmitFn emit;
|
InstrEmitFn emit;
|
||||||
};
|
};
|
||||||
|
|
||||||
InstrType* GetInstrType(uint32_t code);
|
InstrType* GetInstrType(uint32_t code);
|
||||||
int RegisterInstrEmit(uint32_t code, InstrEmitFn emit);
|
int RegisterInstrEmit(uint32_t code, InstrEmitFn emit);
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_PPC_PPC_INSTR_H_
|
#endif // ALLOY_FRONTEND_PPC_PPC_INSTR_H_
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,18 +16,15 @@
|
||||||
#include <alloy/frontend/ppc/ppc_instr.h>
|
#include <alloy/frontend/ppc/ppc_instr.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::frontend;
|
namespace frontend {
|
||||||
using namespace alloy::frontend::ppc;
|
namespace ppc {
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
using alloy::runtime::FunctionInfo;
|
||||||
|
|
||||||
PPCScanner::PPCScanner(PPCFrontend* frontend) :
|
PPCScanner::PPCScanner(PPCFrontend* frontend) : frontend_(frontend) {}
|
||||||
frontend_(frontend) {
|
|
||||||
}
|
|
||||||
|
|
||||||
PPCScanner::~PPCScanner() {
|
PPCScanner::~PPCScanner() {}
|
||||||
}
|
|
||||||
|
|
||||||
bool PPCScanner::IsRestGprLr(uint64_t address) {
|
bool PPCScanner::IsRestGprLr(uint64_t address) {
|
||||||
FunctionInfo* symbol_info;
|
FunctionInfo* symbol_info;
|
||||||
|
@ -80,9 +77,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
// Check if the function starts with a mfspr lr, as that's a good indication
|
// Check if the function starts with a mfspr lr, as that's a good indication
|
||||||
// of whether or not this is a normal function with a prolog/epilog.
|
// of whether or not this is a normal function with a prolog/epilog.
|
||||||
// Some valid leaf functions won't have this, but most will.
|
// Some valid leaf functions won't have this, but most will.
|
||||||
if (address == start_address &&
|
if (address == start_address && i.type && i.type->opcode == 0x7C0002A6 &&
|
||||||
i.type &&
|
|
||||||
i.type->opcode == 0x7C0002A6 &&
|
|
||||||
(((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F)) == 8) {
|
(((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F)) == 8) {
|
||||||
starts_with_mfspr_lr = true;
|
starts_with_mfspr_lr = true;
|
||||||
}
|
}
|
||||||
|
@ -104,8 +99,8 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
// This is generally a return.
|
// This is generally a return.
|
||||||
if (furthest_target > address) {
|
if (furthest_target > address) {
|
||||||
// Remaining targets within function, not end.
|
// Remaining targets within function, not end.
|
||||||
XELOGSDB("ignoring blr %.8X (branch to %.8X)",
|
XELOGSDB("ignoring blr %.8X (branch to %.8X)", address,
|
||||||
address, furthest_target);
|
furthest_target);
|
||||||
} else {
|
} else {
|
||||||
// Function end point.
|
// Function end point.
|
||||||
XELOGSDB("function end %.8X", address);
|
XELOGSDB("function end %.8X", address);
|
||||||
|
@ -131,7 +126,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
// b/ba/bl/bla
|
// b/ba/bl/bla
|
||||||
uint32_t target =
|
uint32_t target =
|
||||||
(uint32_t)XEEXTS26(i.I.LI << 2) + (i.I.AA ? 0 : (int32_t)address);
|
(uint32_t)XEEXTS26(i.I.LI << 2) + (i.I.AA ? 0 : (int32_t)address);
|
||||||
|
|
||||||
if (i.I.LK) {
|
if (i.I.LK) {
|
||||||
XELOGSDB("bl %.8X -> %.8X", address, target);
|
XELOGSDB("bl %.8X -> %.8X", address, target);
|
||||||
// Queue call target if needed.
|
// Queue call target if needed.
|
||||||
|
@ -142,16 +137,15 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
// If the target is back into the function and there's no further target
|
// If the target is back into the function and there's no further target
|
||||||
// we are at the end of a function.
|
// we are at the end of a function.
|
||||||
// (Indirect branches may still go beyond, but no way of knowing).
|
// (Indirect branches may still go beyond, but no way of knowing).
|
||||||
if (target >= start_address &&
|
if (target >= start_address && target < address &&
|
||||||
target < address && furthest_target <= address) {
|
furthest_target <= address) {
|
||||||
XELOGSDB("function end %.8X (back b)", address);
|
XELOGSDB("function end %.8X (back b)", address);
|
||||||
ends_fn = true;
|
ends_fn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the target is not a branch and it goes to before the current
|
// If the target is not a branch and it goes to before the current
|
||||||
// address it's definitely a tail call.
|
// address it's definitely a tail call.
|
||||||
if (!ends_fn &&
|
if (!ends_fn && target < start_address && furthest_target <= address) {
|
||||||
target < start_address && furthest_target <= address) {
|
|
||||||
XELOGSDB("function end %.8X (back b before addr)", address);
|
XELOGSDB("function end %.8X (back b before addr)", address);
|
||||||
ends_fn = true;
|
ends_fn = true;
|
||||||
}
|
}
|
||||||
|
@ -160,9 +154,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
// Note that sometimes functions stick this in a basic block *inside*
|
// Note that sometimes functions stick this in a basic block *inside*
|
||||||
// of the function somewhere, so ensure we don't have any branches over
|
// of the function somewhere, so ensure we don't have any branches over
|
||||||
// it.
|
// it.
|
||||||
if (!ends_fn &&
|
if (!ends_fn && furthest_target <= address && IsRestGprLr(target)) {
|
||||||
furthest_target <= address &&
|
|
||||||
IsRestGprLr(target)) {
|
|
||||||
XELOGSDB("function end %.8X (__restgprlr_*)", address);
|
XELOGSDB("function end %.8X (__restgprlr_*)", address);
|
||||||
ends_fn = true;
|
ends_fn = true;
|
||||||
}
|
}
|
||||||
|
@ -174,9 +166,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
// b KeBugCheck
|
// b KeBugCheck
|
||||||
// This check may hit on functions that jump over data code, so only
|
// This check may hit on functions that jump over data code, so only
|
||||||
// trigger this check in leaf functions (no mfspr lr/prolog).
|
// trigger this check in leaf functions (no mfspr lr/prolog).
|
||||||
if (!ends_fn &&
|
if (!ends_fn && !starts_with_mfspr_lr && blocks_found == 1) {
|
||||||
!starts_with_mfspr_lr &&
|
|
||||||
blocks_found == 1) {
|
|
||||||
XELOGSDB("HEURISTIC: ending at simple leaf thunk %.8X", address);
|
XELOGSDB("HEURISTIC: ending at simple leaf thunk %.8X", address);
|
||||||
ends_fn = true;
|
ends_fn = true;
|
||||||
}
|
}
|
||||||
|
@ -206,7 +196,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
// TODO(benvanik): perhaps queue up for a speculative check? I think
|
// TODO(benvanik): perhaps queue up for a speculative check? I think
|
||||||
// we are running over tail-call functions here that branch to
|
// we are running over tail-call functions here that branch to
|
||||||
// somewhere else.
|
// somewhere else.
|
||||||
//GetOrInsertFunction(target);
|
// GetOrInsertFunction(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ends_block = true;
|
ends_block = true;
|
||||||
|
@ -220,7 +210,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
// Queue call target if needed.
|
// Queue call target if needed.
|
||||||
// TODO(benvanik): see if this is correct - not sure anyone makes
|
// TODO(benvanik): see if this is correct - not sure anyone makes
|
||||||
// function calls with bcl.
|
// function calls with bcl.
|
||||||
//GetOrInsertFunction(target);
|
// GetOrInsertFunction(target);
|
||||||
} else {
|
} else {
|
||||||
XELOGSDB("bc %.8X -> %.8X", address, target);
|
XELOGSDB("bc %.8X -> %.8X", address, target);
|
||||||
|
|
||||||
|
@ -259,8 +249,8 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
address += 4;
|
address += 4;
|
||||||
if (end_address && address > end_address) {
|
if (end_address && address > end_address) {
|
||||||
// Hmm....
|
// Hmm....
|
||||||
XELOGSDB("Ran over function bounds! %.8X-%.8X",
|
XELOGSDB("Ran over function bounds! %.8X-%.8X", start_address,
|
||||||
start_address, end_address);
|
end_address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,8 +260,8 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
// from someplace valid (like method hints) this may indicate an error.
|
// from someplace valid (like method hints) this may indicate an error.
|
||||||
// It's also possible that we guessed in hole-filling and there's another
|
// It's also possible that we guessed in hole-filling and there's another
|
||||||
// function below this one.
|
// function below this one.
|
||||||
XELOGSDB("Function ran under: %.8X-%.8X ended at %.8X",
|
XELOGSDB("Function ran under: %.8X-%.8X ended at %.8X", start_address,
|
||||||
start_address, end_address, address + 4);
|
end_address, address + 4);
|
||||||
}
|
}
|
||||||
symbol_info->set_end_address(address);
|
symbol_info->set_end_address(address);
|
||||||
|
|
||||||
|
@ -300,8 +290,7 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
||||||
bool in_block = false;
|
bool in_block = false;
|
||||||
uint64_t block_start = 0;
|
uint64_t block_start = 0;
|
||||||
InstrData i;
|
InstrData i;
|
||||||
for (uint64_t address = start_address;
|
for (uint64_t address = start_address; address <= end_address; address += 4) {
|
||||||
address <= end_address; address += 4) {
|
|
||||||
i.address = address;
|
i.address = address;
|
||||||
i.code = XEGETUINT32BE(p + address);
|
i.code = XEGETUINT32BE(p + address);
|
||||||
if (!i.code) {
|
if (!i.code) {
|
||||||
|
@ -330,12 +319,12 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
||||||
ends_block = true;
|
ends_block = true;
|
||||||
} else if (i.type->opcode == 0x48000000) {
|
} else if (i.type->opcode == 0x48000000) {
|
||||||
// b/ba/bl/bla
|
// b/ba/bl/bla
|
||||||
//uint32_t target =
|
// uint32_t target =
|
||||||
// (uint32_t)XEEXTS26(i.I.LI << 2) + (i.I.AA ? 0 : (int32_t)address);
|
// (uint32_t)XEEXTS26(i.I.LI << 2) + (i.I.AA ? 0 : (int32_t)address);
|
||||||
ends_block = true;
|
ends_block = true;
|
||||||
} else if (i.type->opcode == 0x40000000) {
|
} else if (i.type->opcode == 0x40000000) {
|
||||||
// bc/bca/bcl/bcla
|
// bc/bca/bcl/bcla
|
||||||
//uint32_t target =
|
// uint32_t target =
|
||||||
// (uint32_t)XEEXTS16(i.B.BD << 2) + (i.B.AA ? 0 : (int32_t)address);
|
// (uint32_t)XEEXTS16(i.B.BD << 2) + (i.B.AA ? 0 : (int32_t)address);
|
||||||
ends_block = true;
|
ends_block = true;
|
||||||
} else if (i.type->opcode == 0x4C000020) {
|
} else if (i.type->opcode == 0x4C000020) {
|
||||||
|
@ -349,16 +338,14 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
||||||
if (ends_block) {
|
if (ends_block) {
|
||||||
in_block = false;
|
in_block = false;
|
||||||
block_map[block_start] = {
|
block_map[block_start] = {
|
||||||
block_start,
|
block_start, address,
|
||||||
address,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_block) {
|
if (in_block) {
|
||||||
block_map[block_start] = {
|
block_map[block_start] = {
|
||||||
block_start,
|
block_start, end_address,
|
||||||
end_address,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,3 +355,7 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
||||||
}
|
}
|
||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ppc
|
||||||
|
} // namespace frontend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
#include <alloy/runtime/symbol_info.h>
|
#include <alloy/runtime/symbol_info.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
@ -25,9 +24,8 @@ typedef struct BlockInfo_t {
|
||||||
uint64_t end_address;
|
uint64_t end_address;
|
||||||
} BlockInfo;
|
} BlockInfo;
|
||||||
|
|
||||||
|
|
||||||
class PPCScanner {
|
class PPCScanner {
|
||||||
public:
|
public:
|
||||||
PPCScanner(PPCFrontend* frontend);
|
PPCScanner(PPCFrontend* frontend);
|
||||||
~PPCScanner();
|
~PPCScanner();
|
||||||
|
|
||||||
|
@ -35,17 +33,15 @@ public:
|
||||||
|
|
||||||
std::vector<BlockInfo> FindBlocks(runtime::FunctionInfo* symbol_info);
|
std::vector<BlockInfo> FindBlocks(runtime::FunctionInfo* symbol_info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsRestGprLr(uint64_t address);
|
bool IsRestGprLr(uint64_t address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PPCFrontend* frontend_;
|
PPCFrontend* frontend_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_PPC_PPC_SCANNER_H_
|
#endif // ALLOY_FRONTEND_PPC_PPC_SCANNER_H_
|
||||||
|
|
|
@ -19,17 +19,20 @@
|
||||||
#include <alloy/frontend/ppc/ppc_scanner.h>
|
#include <alloy/frontend/ppc/ppc_scanner.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::backend;
|
namespace frontend {
|
||||||
using namespace alloy::compiler;
|
namespace ppc {
|
||||||
using namespace alloy::frontend;
|
|
||||||
using namespace alloy::frontend::ppc;
|
// TODO(benvanik): remove when enums redefined.
|
||||||
using namespace alloy::hir;
|
|
||||||
using namespace alloy::runtime;
|
using namespace alloy::runtime;
|
||||||
|
|
||||||
|
using alloy::backend::Backend;
|
||||||
|
using alloy::compiler::Compiler;
|
||||||
|
using alloy::runtime::Function;
|
||||||
|
using alloy::runtime::FunctionInfo;
|
||||||
|
namespace passes = alloy::compiler::passes;
|
||||||
|
|
||||||
PPCTranslator::PPCTranslator(PPCFrontend* frontend) :
|
PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) {
|
||||||
frontend_(frontend) {
|
|
||||||
Backend* backend = frontend->runtime()->backend();
|
Backend* backend = frontend->runtime()->backend();
|
||||||
|
|
||||||
scanner_ = new PPCScanner(frontend);
|
scanner_ = new PPCScanner(frontend);
|
||||||
|
@ -54,21 +57,21 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) :
|
||||||
if (validate) compiler_->AddPass(new passes::ValidationPass());
|
if (validate) compiler_->AddPass(new passes::ValidationPass());
|
||||||
compiler_->AddPass(new passes::SimplificationPass());
|
compiler_->AddPass(new passes::SimplificationPass());
|
||||||
if (validate) compiler_->AddPass(new passes::ValidationPass());
|
if (validate) compiler_->AddPass(new passes::ValidationPass());
|
||||||
//compiler_->AddPass(new passes::DeadStoreEliminationPass());
|
// compiler_->AddPass(new passes::DeadStoreEliminationPass());
|
||||||
//if (validate) compiler_->AddPass(new passes::ValidationPass());
|
// if (validate) compiler_->AddPass(new passes::ValidationPass());
|
||||||
compiler_->AddPass(new passes::DeadCodeEliminationPass());
|
compiler_->AddPass(new passes::DeadCodeEliminationPass());
|
||||||
if (validate) compiler_->AddPass(new passes::ValidationPass());
|
if (validate) compiler_->AddPass(new passes::ValidationPass());
|
||||||
|
|
||||||
//// Removes all unneeded variables. Try not to add new ones after this.
|
//// Removes all unneeded variables. Try not to add new ones after this.
|
||||||
//compiler_->AddPass(new passes::ValueReductionPass());
|
// compiler_->AddPass(new passes::ValueReductionPass());
|
||||||
//if (validate) compiler_->AddPass(new passes::ValidationPass());
|
// if (validate) compiler_->AddPass(new passes::ValidationPass());
|
||||||
|
|
||||||
// Register allocation for the target backend.
|
// Register allocation for the target backend.
|
||||||
// Will modify the HIR to add loads/stores.
|
// Will modify the HIR to add loads/stores.
|
||||||
// This should be the last pass before finalization, as after this all
|
// This should be the last pass before finalization, as after this all
|
||||||
// registers are assigned and ready to be emitted.
|
// registers are assigned and ready to be emitted.
|
||||||
compiler_->AddPass(new passes::RegisterAllocationPass(
|
compiler_->AddPass(
|
||||||
backend->machine_info()));
|
new passes::RegisterAllocationPass(backend->machine_info()));
|
||||||
if (validate) compiler_->AddPass(new passes::ValidationPass());
|
if (validate) compiler_->AddPass(new passes::ValidationPass());
|
||||||
|
|
||||||
// Must come last. The HIR is not really HIR after this.
|
// Must come last. The HIR is not really HIR after this.
|
||||||
|
@ -82,10 +85,9 @@ PPCTranslator::~PPCTranslator() {
|
||||||
delete scanner_;
|
delete scanner_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PPCTranslator::Translate(
|
int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
||||||
FunctionInfo* symbol_info,
|
uint32_t debug_info_flags,
|
||||||
uint32_t debug_info_flags,
|
Function** out_function) {
|
||||||
Function** out_function) {
|
|
||||||
SCOPE_profile_cpu_f("alloy");
|
SCOPE_profile_cpu_f("alloy");
|
||||||
|
|
||||||
// Scan the function to find its extents. We only need to do this if we
|
// Scan the function to find its extents. We only need to do this if we
|
||||||
|
@ -139,10 +141,8 @@ int PPCTranslator::Translate(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assemble to backend machine code.
|
// Assemble to backend machine code.
|
||||||
result = assembler_->Assemble(
|
result = assembler_->Assemble(symbol_info, builder_, debug_info_flags,
|
||||||
symbol_info, builder_,
|
debug_info, out_function);
|
||||||
debug_info_flags, debug_info,
|
|
||||||
out_function);
|
|
||||||
XEEXPECTZERO(result);
|
XEEXPECTZERO(result);
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
|
@ -158,15 +158,14 @@ XECLEANUP:
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
void PPCTranslator::DumpSource(
|
void PPCTranslator::DumpSource(runtime::FunctionInfo* symbol_info,
|
||||||
runtime::FunctionInfo* symbol_info, StringBuffer* string_buffer) {
|
StringBuffer* string_buffer) {
|
||||||
Memory* memory = frontend_->memory();
|
Memory* memory = frontend_->memory();
|
||||||
const uint8_t* p = memory->membase();
|
const uint8_t* p = memory->membase();
|
||||||
|
|
||||||
string_buffer->Append("%s fn %.8X-%.8X %s\n",
|
string_buffer->Append("%s fn %.8X-%.8X %s\n", symbol_info->module()->name(),
|
||||||
symbol_info->module()->name(),
|
symbol_info->address(), symbol_info->end_address(),
|
||||||
symbol_info->address(), symbol_info->end_address(),
|
symbol_info->name());
|
||||||
symbol_info->name());
|
|
||||||
|
|
||||||
auto blocks = scanner_->FindBlocks(symbol_info);
|
auto blocks = scanner_->FindBlocks(symbol_info);
|
||||||
|
|
||||||
|
@ -182,10 +181,8 @@ void PPCTranslator::DumpSource(
|
||||||
i.type = GetInstrType(i.code);
|
i.type = GetInstrType(i.code);
|
||||||
|
|
||||||
// Check labels.
|
// Check labels.
|
||||||
if (block_it != blocks.end() &&
|
if (block_it != blocks.end() && block_it->start_address == address) {
|
||||||
block_it->start_address == address) {
|
string_buffer->Append("%.8X loc_%.8X:\n", address, address);
|
||||||
string_buffer->Append(
|
|
||||||
"%.8X loc_%.8X:\n", address, address);
|
|
||||||
++block_it;
|
++block_it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,3 +191,7 @@ void PPCTranslator::DumpSource(
|
||||||
string_buffer->Append("\n");
|
string_buffer->Append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ppc
|
||||||
|
} // namespace frontend
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include <alloy/compiler/compiler.h>
|
#include <alloy/compiler/compiler.h>
|
||||||
#include <alloy/runtime/symbol_info.h>
|
#include <alloy/runtime/symbol_info.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
namespace ppc {
|
namespace ppc {
|
||||||
|
@ -24,34 +23,30 @@ class PPCFrontend;
|
||||||
class PPCHIRBuilder;
|
class PPCHIRBuilder;
|
||||||
class PPCScanner;
|
class PPCScanner;
|
||||||
|
|
||||||
|
|
||||||
class PPCTranslator {
|
class PPCTranslator {
|
||||||
public:
|
public:
|
||||||
PPCTranslator(PPCFrontend* frontend);
|
PPCTranslator(PPCFrontend* frontend);
|
||||||
~PPCTranslator();
|
~PPCTranslator();
|
||||||
|
|
||||||
int Translate(runtime::FunctionInfo* symbol_info,
|
int Translate(runtime::FunctionInfo* symbol_info, uint32_t debug_info_flags,
|
||||||
uint32_t debug_info_flags,
|
|
||||||
runtime::Function** out_function);
|
runtime::Function** out_function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DumpSource(runtime::FunctionInfo* symbol_info,
|
void DumpSource(runtime::FunctionInfo* symbol_info,
|
||||||
StringBuffer* string_buffer);
|
StringBuffer* string_buffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PPCFrontend* frontend_;
|
PPCFrontend* frontend_;
|
||||||
PPCScanner* scanner_;
|
PPCScanner* scanner_;
|
||||||
PPCHIRBuilder* builder_;
|
PPCHIRBuilder* builder_;
|
||||||
compiler::Compiler* compiler_;
|
compiler::Compiler* compiler_;
|
||||||
backend::Assembler* assembler_;
|
backend::Assembler* assembler_;
|
||||||
|
|
||||||
StringBuffer string_buffer_;
|
StringBuffer string_buffer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
} // namespace ppc
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_PPC_PPC_TRANSLATOR_H_
|
#endif // ALLOY_FRONTEND_PPC_PPC_TRANSLATOR_H_
|
||||||
|
|
|
@ -13,18 +13,16 @@
|
||||||
#include <alloy/tracing/tracing.h>
|
#include <alloy/tracing/tracing.h>
|
||||||
#include <alloy/tracing/event_type.h>
|
#include <alloy/tracing/event_type.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
|
|
||||||
const uint32_t ALLOY_FRONTEND = alloy::tracing::EventType::ALLOY_FRONTEND;
|
const uint32_t ALLOY_FRONTEND = alloy::tracing::EventType::ALLOY_FRONTEND;
|
||||||
|
|
||||||
|
|
||||||
class EventType {
|
class EventType {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
ALLOY_FRONTEND_INIT = ALLOY_FRONTEND | (1),
|
ALLOY_FRONTEND_INIT = ALLOY_FRONTEND | (1),
|
||||||
ALLOY_FRONTEND_DEINIT = ALLOY_FRONTEND | (2),
|
ALLOY_FRONTEND_DEINIT = ALLOY_FRONTEND | (2),
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Init_s {
|
typedef struct Init_s {
|
||||||
|
@ -35,9 +33,7 @@ public:
|
||||||
} Deinit;
|
} Deinit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_FRONTEND_TRACING_H_
|
#endif // ALLOY_FRONTEND_TRACING_H_
|
||||||
|
|
|
@ -11,9 +11,8 @@
|
||||||
|
|
||||||
#include <alloy/hir/instr.h>
|
#include <alloy/hir/instr.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::hir;
|
namespace hir {
|
||||||
|
|
||||||
|
|
||||||
void Block::AssertNoCycles() {
|
void Block::AssertNoCycles() {
|
||||||
Instr* hare = instr_head;
|
Instr* hare = instr_head;
|
||||||
|
@ -37,3 +36,6 @@ void Block::AssertNoCycles() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace hir
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
XEDECLARECLASS1(llvm, BitVector);
|
XEDECLARECLASS1(llvm, BitVector);
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace hir {
|
namespace hir {
|
||||||
|
|
||||||
|
@ -23,14 +22,14 @@ class HIRBuilder;
|
||||||
class Instr;
|
class Instr;
|
||||||
class Label;
|
class Label;
|
||||||
|
|
||||||
|
|
||||||
class Edge {
|
class Edge {
|
||||||
public:
|
public:
|
||||||
enum EdgeFlags {
|
enum EdgeFlags {
|
||||||
UNCONDITIONAL = (1 << 0),
|
UNCONDITIONAL = (1 << 0),
|
||||||
DOMINATES = (1 << 1),
|
DOMINATES = (1 << 1),
|
||||||
};
|
};
|
||||||
public:
|
|
||||||
|
public:
|
||||||
Edge* outgoing_next;
|
Edge* outgoing_next;
|
||||||
Edge* outgoing_prev;
|
Edge* outgoing_prev;
|
||||||
Edge* incoming_next;
|
Edge* incoming_next;
|
||||||
|
@ -42,9 +41,8 @@ public:
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Block {
|
class Block {
|
||||||
public:
|
public:
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
|
|
||||||
Block* next;
|
Block* next;
|
||||||
|
@ -65,9 +63,7 @@ public:
|
||||||
void AssertNoCycles();
|
void AssertNoCycles();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace hir
|
} // namespace hir
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_HIR_BLOCK_H_
|
#endif // ALLOY_HIR_BLOCK_H_
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,17 +17,15 @@
|
||||||
#include <alloy/hir/opcodes.h>
|
#include <alloy/hir/opcodes.h>
|
||||||
#include <alloy/hir/value.h>
|
#include <alloy/hir/value.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace hir {
|
namespace hir {
|
||||||
|
|
||||||
enum FunctionAttributes {
|
enum FunctionAttributes {
|
||||||
FUNCTION_ATTRIB_INLINE = (1 << 1),
|
FUNCTION_ATTRIB_INLINE = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class HIRBuilder {
|
class HIRBuilder {
|
||||||
public:
|
public:
|
||||||
HIRBuilder();
|
HIRBuilder();
|
||||||
virtual ~HIRBuilder();
|
virtual ~HIRBuilder();
|
||||||
|
|
||||||
|
@ -86,10 +84,8 @@ public:
|
||||||
|
|
||||||
void Branch(Label* label, uint32_t branch_flags = 0);
|
void Branch(Label* label, uint32_t branch_flags = 0);
|
||||||
void Branch(Block* block, uint32_t branch_flags = 0);
|
void Branch(Block* block, uint32_t branch_flags = 0);
|
||||||
void BranchTrue(Value* cond, Label* label,
|
void BranchTrue(Value* cond, Label* label, uint32_t branch_flags = 0);
|
||||||
uint32_t branch_flags = 0);
|
void BranchFalse(Value* cond, Label* label, uint32_t branch_flags = 0);
|
||||||
void BranchFalse(Value* cond, Label* label,
|
|
||||||
uint32_t branch_flags = 0);
|
|
||||||
|
|
||||||
// phi type_name, Block* b1, Value* v1, Block* b2, Value* v2, etc
|
// phi type_name, Block* b1, Value* v1, Block* b2, Value* v2, etc
|
||||||
|
|
||||||
|
@ -162,13 +158,12 @@ public:
|
||||||
uint32_t arithmetic_flags = 0);
|
uint32_t arithmetic_flags = 0);
|
||||||
Value* VectorAdd(Value* value1, Value* value2, TypeName part_type,
|
Value* VectorAdd(Value* value1, Value* value2, TypeName part_type,
|
||||||
uint32_t arithmetic_flags = 0);
|
uint32_t arithmetic_flags = 0);
|
||||||
Value* Sub(Value* value1, Value* value2,
|
Value* Sub(Value* value1, Value* value2, uint32_t arithmetic_flags = 0);
|
||||||
uint32_t arithmetic_flags = 0);
|
|
||||||
Value* Mul(Value* value1, Value* value2, uint32_t arithmetic_flags = 0);
|
Value* Mul(Value* value1, Value* value2, uint32_t arithmetic_flags = 0);
|
||||||
Value* MulHi(Value* value1, Value* value2, uint32_t arithmetic_flags = 0);
|
Value* MulHi(Value* value1, Value* value2, uint32_t arithmetic_flags = 0);
|
||||||
Value* Div(Value* value1, Value* value2, uint32_t arithmetic_flags = 0);
|
Value* Div(Value* value1, Value* value2, uint32_t arithmetic_flags = 0);
|
||||||
Value* MulAdd(Value* value1, Value* value2, Value* value3); // (1 * 2) + 3
|
Value* MulAdd(Value* value1, Value* value2, Value* value3); // (1 * 2) + 3
|
||||||
Value* MulSub(Value* value1, Value* value2, Value* value3); // (1 * 2) - 3
|
Value* MulSub(Value* value1, Value* value2, Value* value3); // (1 * 2) - 3
|
||||||
Value* Neg(Value* value);
|
Value* Neg(Value* value);
|
||||||
Value* Abs(Value* value);
|
Value* Abs(Value* value);
|
||||||
Value* Sqrt(Value* value);
|
Value* Sqrt(Value* value);
|
||||||
|
@ -208,48 +203,44 @@ public:
|
||||||
Value* Pack(Value* value, uint32_t pack_flags = 0);
|
Value* Pack(Value* value, uint32_t pack_flags = 0);
|
||||||
Value* Unpack(Value* value, uint32_t pack_flags = 0);
|
Value* Unpack(Value* value, uint32_t pack_flags = 0);
|
||||||
|
|
||||||
Value* CompareExchange(Value* address,
|
Value* CompareExchange(Value* address, Value* compare_value,
|
||||||
Value* compare_value, Value* exchange_value);
|
Value* exchange_value);
|
||||||
Value* AtomicExchange(Value* address, Value* new_value);
|
Value* AtomicExchange(Value* address, Value* new_value);
|
||||||
Value* AtomicAdd(Value* address, Value* value);
|
Value* AtomicAdd(Value* address, Value* value);
|
||||||
Value* AtomicSub(Value* address, Value* value);
|
Value* AtomicSub(Value* address, Value* value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DumpValue(StringBuffer* str, Value* value);
|
void DumpValue(StringBuffer* str, Value* value);
|
||||||
void DumpOp(
|
void DumpOp(StringBuffer* str, OpcodeSignatureType sig_type, Instr::Op* op);
|
||||||
StringBuffer* str, OpcodeSignatureType sig_type, Instr::Op* op);
|
|
||||||
|
|
||||||
Value* AllocValue(TypeName type = INT64_TYPE);
|
Value* AllocValue(TypeName type = INT64_TYPE);
|
||||||
Value* CloneValue(Value* source);
|
Value* CloneValue(Value* source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Block* AppendBlock();
|
Block* AppendBlock();
|
||||||
void EndBlock();
|
void EndBlock();
|
||||||
bool IsUnconditionalJump(Instr* instr);
|
bool IsUnconditionalJump(Instr* instr);
|
||||||
Instr* AppendInstr(const OpcodeInfo& opcode, uint16_t flags,
|
Instr* AppendInstr(const OpcodeInfo& opcode, uint16_t flags, Value* dest = 0);
|
||||||
Value* dest = 0);
|
|
||||||
Value* CompareXX(const OpcodeInfo& opcode, Value* value1, Value* value2);
|
Value* CompareXX(const OpcodeInfo& opcode, Value* value1, Value* value2);
|
||||||
Value* VectorCompareXX(
|
Value* VectorCompareXX(const OpcodeInfo& opcode, Value* value1, Value* value2,
|
||||||
const OpcodeInfo& opcode, Value* value1, Value* value2, TypeName part_type);
|
TypeName part_type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Arena* arena_;
|
Arena* arena_;
|
||||||
|
|
||||||
uint32_t attributes_;
|
uint32_t attributes_;
|
||||||
|
|
||||||
uint32_t next_label_id_;
|
uint32_t next_label_id_;
|
||||||
uint32_t next_value_ordinal_;
|
uint32_t next_value_ordinal_;
|
||||||
|
|
||||||
std::vector<Value*> locals_;
|
std::vector<Value*> locals_;
|
||||||
|
|
||||||
Block* block_head_;
|
Block* block_head_;
|
||||||
Block* block_tail_;
|
Block* block_tail_;
|
||||||
Block* current_block_;
|
Block* current_block_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace hir
|
} // namespace hir
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_HIR_HIR_BUILDER_H_
|
#endif // ALLOY_HIR_HIR_BUILDER_H_
|
||||||
|
|
|
@ -11,9 +11,8 @@
|
||||||
|
|
||||||
#include <alloy/hir/block.h>
|
#include <alloy/hir/block.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::hir;
|
namespace hir {
|
||||||
|
|
||||||
|
|
||||||
void Instr::set_src1(Value* value) {
|
void Instr::set_src1(Value* value) {
|
||||||
if (src1.value == value) {
|
if (src1.value == value) {
|
||||||
|
@ -114,3 +113,6 @@ void Instr::Remove() {
|
||||||
block->instr_tail = prev;
|
block->instr_tail = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace hir
|
||||||
|
} // namespace alloy
|
||||||
|
|
|
@ -14,9 +14,11 @@
|
||||||
#include <alloy/hir/opcodes.h>
|
#include <alloy/hir/opcodes.h>
|
||||||
#include <alloy/hir/value.h>
|
#include <alloy/hir/value.h>
|
||||||
|
|
||||||
|
namespace alloy {
|
||||||
namespace alloy { namespace runtime { class FunctionInfo; } }
|
namespace runtime {
|
||||||
|
class FunctionInfo;
|
||||||
|
} // namespace runtime
|
||||||
|
} // namespace alloy
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace hir {
|
namespace hir {
|
||||||
|
@ -25,26 +27,26 @@ class Block;
|
||||||
class Label;
|
class Label;
|
||||||
|
|
||||||
class Instr {
|
class Instr {
|
||||||
public:
|
public:
|
||||||
Block* block;
|
Block* block;
|
||||||
Instr* next;
|
Instr* next;
|
||||||
Instr* prev;
|
Instr* prev;
|
||||||
|
|
||||||
const OpcodeInfo* opcode;
|
const OpcodeInfo* opcode;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
uint32_t ordinal;
|
uint32_t ordinal;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
runtime::FunctionInfo* symbol_info;
|
runtime::FunctionInfo* symbol_info;
|
||||||
Label* label;
|
Label* label;
|
||||||
Value* value;
|
Value* value;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
} Op;
|
} Op;
|
||||||
|
|
||||||
Value* dest;
|
Value* dest;
|
||||||
Op src1;
|
Op src1;
|
||||||
Op src2;
|
Op src2;
|
||||||
Op src3;
|
Op src3;
|
||||||
|
|
||||||
Value::Use* src1_use;
|
Value::Use* src1_use;
|
||||||
Value::Use* src2_use;
|
Value::Use* src2_use;
|
||||||
|
@ -59,9 +61,7 @@ public:
|
||||||
void Remove();
|
void Remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace hir
|
} // namespace hir
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_HIR_INSTR_H_
|
#endif // ALLOY_HIR_INSTR_H_
|
||||||
|
|
|
@ -12,28 +12,24 @@
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace hir {
|
namespace hir {
|
||||||
|
|
||||||
class Block;
|
class Block;
|
||||||
|
|
||||||
|
|
||||||
class Label {
|
class Label {
|
||||||
public:
|
public:
|
||||||
Block* block;
|
Block* block;
|
||||||
Label* next;
|
Label* next;
|
||||||
Label* prev;
|
Label* prev;
|
||||||
|
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
char* name;
|
char* name;
|
||||||
|
|
||||||
void* tag;
|
void* tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace hir
|
} // namespace hir
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_HIR_LABEL_H_
|
#endif // ALLOY_HIR_LABEL_H_
|
||||||
|
|
|
@ -9,15 +9,13 @@
|
||||||
|
|
||||||
#include <alloy/hir/opcodes.h>
|
#include <alloy/hir/opcodes.h>
|
||||||
|
|
||||||
using namespace alloy;
|
|
||||||
using namespace alloy::hir;
|
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace hir {
|
namespace hir {
|
||||||
|
|
||||||
#define DEFINE_OPCODE(num, name, sig, flags) \
|
#define DEFINE_OPCODE(num, name, sig, flags) \
|
||||||
static const OpcodeInfo num##_info = { flags, sig, name, num, };
|
static const OpcodeInfo num##_info = { \
|
||||||
|
flags, sig, name, num, \
|
||||||
|
};
|
||||||
#include <alloy/hir/opcodes.inl>
|
#include <alloy/hir/opcodes.inl>
|
||||||
#undef DEFINE_OPCODE
|
#undef DEFINE_OPCODE
|
||||||
|
|
||||||
|
|
|
@ -12,17 +12,15 @@
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace hir {
|
namespace hir {
|
||||||
|
|
||||||
|
|
||||||
enum CallFlags {
|
enum CallFlags {
|
||||||
CALL_TAIL = (1 << 1),
|
CALL_TAIL = (1 << 1),
|
||||||
CALL_POSSIBLE_RETURN = (1 << 2),
|
CALL_POSSIBLE_RETURN = (1 << 2),
|
||||||
};
|
};
|
||||||
enum BranchFlags {
|
enum BranchFlags {
|
||||||
BRANCH_LIKELY = (1 << 1),
|
BRANCH_LIKELY = (1 << 1),
|
||||||
BRANCH_UNLIKELY = (1 << 2),
|
BRANCH_UNLIKELY = (1 << 2),
|
||||||
};
|
};
|
||||||
enum RoundMode {
|
enum RoundMode {
|
||||||
|
@ -33,20 +31,20 @@ enum RoundMode {
|
||||||
ROUND_TO_POSITIVE_INFINITY,
|
ROUND_TO_POSITIVE_INFINITY,
|
||||||
};
|
};
|
||||||
enum LoadFlags {
|
enum LoadFlags {
|
||||||
LOAD_NO_ALIAS = (1 << 1),
|
LOAD_NO_ALIAS = (1 << 1),
|
||||||
LOAD_ALIGNED = (1 << 2),
|
LOAD_ALIGNED = (1 << 2),
|
||||||
LOAD_UNALIGNED = (1 << 3),
|
LOAD_UNALIGNED = (1 << 3),
|
||||||
LOAD_VOLATILE = (1 << 4),
|
LOAD_VOLATILE = (1 << 4),
|
||||||
};
|
};
|
||||||
enum StoreFlags {
|
enum StoreFlags {
|
||||||
STORE_NO_ALIAS = (1 << 1),
|
STORE_NO_ALIAS = (1 << 1),
|
||||||
STORE_ALIGNED = (1 << 2),
|
STORE_ALIGNED = (1 << 2),
|
||||||
STORE_UNALIGNED = (1 << 3),
|
STORE_UNALIGNED = (1 << 3),
|
||||||
STORE_VOLATILE = (1 << 4),
|
STORE_VOLATILE = (1 << 4),
|
||||||
};
|
};
|
||||||
enum PrefetchFlags {
|
enum PrefetchFlags {
|
||||||
PREFETCH_LOAD = (1 << 1),
|
PREFETCH_LOAD = (1 << 1),
|
||||||
PREFETCH_STORE = (1 << 2),
|
PREFETCH_STORE = (1 << 2),
|
||||||
};
|
};
|
||||||
enum ArithmeticFlags {
|
enum ArithmeticFlags {
|
||||||
ARITHMETIC_SET_CARRY = (1 << 1),
|
ARITHMETIC_SET_CARRY = (1 << 1),
|
||||||
|
@ -56,11 +54,8 @@ enum ArithmeticFlags {
|
||||||
enum Permutes {
|
enum Permutes {
|
||||||
PERMUTE_XY_ZW = 0x00010405,
|
PERMUTE_XY_ZW = 0x00010405,
|
||||||
};
|
};
|
||||||
#define SWIZZLE_MASK(x, y, z, w) ( \
|
#define SWIZZLE_MASK(x, y, z, w) \
|
||||||
(((x) & 0x3) << 6) | \
|
((((x)&0x3) << 6) | (((y)&0x3) << 4) | (((z)&0x3) << 2) | (((w)&0x3)))
|
||||||
(((y) & 0x3) << 4) | \
|
|
||||||
(((z) & 0x3) << 2) | \
|
|
||||||
(((w) & 0x3)))
|
|
||||||
enum Swizzles {
|
enum Swizzles {
|
||||||
SWIZZLE_XYZW_TO_XYZW = SWIZZLE_MASK(0, 1, 2, 3),
|
SWIZZLE_XYZW_TO_XYZW = SWIZZLE_MASK(0, 1, 2, 3),
|
||||||
SWIZZLE_XYZW_TO_YZWX = SWIZZLE_MASK(1, 2, 3, 0),
|
SWIZZLE_XYZW_TO_YZWX = SWIZZLE_MASK(1, 2, 3, 0),
|
||||||
|
@ -78,19 +73,14 @@ enum PackType {
|
||||||
PACK_TYPE_S16_IN_32_HI = 7,
|
PACK_TYPE_S16_IN_32_HI = 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum Opcode {
|
enum Opcode {
|
||||||
OPCODE_COMMENT,
|
OPCODE_COMMENT,
|
||||||
OPCODE_NOP,
|
OPCODE_NOP,
|
||||||
|
|
||||||
OPCODE_SOURCE_OFFSET,
|
OPCODE_SOURCE_OFFSET,
|
||||||
|
|
||||||
OPCODE_DEBUG_BREAK,
|
OPCODE_DEBUG_BREAK,
|
||||||
OPCODE_DEBUG_BREAK_TRUE,
|
OPCODE_DEBUG_BREAK_TRUE,
|
||||||
|
|
||||||
OPCODE_TRAP,
|
OPCODE_TRAP,
|
||||||
OPCODE_TRAP_TRUE,
|
OPCODE_TRAP_TRUE,
|
||||||
|
|
||||||
OPCODE_CALL,
|
OPCODE_CALL,
|
||||||
OPCODE_CALL_TRUE,
|
OPCODE_CALL_TRUE,
|
||||||
OPCODE_CALL_INDIRECT,
|
OPCODE_CALL_INDIRECT,
|
||||||
|
@ -99,11 +89,9 @@ enum Opcode {
|
||||||
OPCODE_RETURN,
|
OPCODE_RETURN,
|
||||||
OPCODE_RETURN_TRUE,
|
OPCODE_RETURN_TRUE,
|
||||||
OPCODE_SET_RETURN_ADDRESS,
|
OPCODE_SET_RETURN_ADDRESS,
|
||||||
|
|
||||||
OPCODE_BRANCH,
|
OPCODE_BRANCH,
|
||||||
OPCODE_BRANCH_TRUE,
|
OPCODE_BRANCH_TRUE,
|
||||||
OPCODE_BRANCH_FALSE,
|
OPCODE_BRANCH_FALSE,
|
||||||
|
|
||||||
OPCODE_ASSIGN,
|
OPCODE_ASSIGN,
|
||||||
OPCODE_CAST,
|
OPCODE_CAST,
|
||||||
OPCODE_ZERO_EXTEND,
|
OPCODE_ZERO_EXTEND,
|
||||||
|
@ -113,22 +101,16 @@ enum Opcode {
|
||||||
OPCODE_ROUND,
|
OPCODE_ROUND,
|
||||||
OPCODE_VECTOR_CONVERT_I2F,
|
OPCODE_VECTOR_CONVERT_I2F,
|
||||||
OPCODE_VECTOR_CONVERT_F2I,
|
OPCODE_VECTOR_CONVERT_F2I,
|
||||||
|
|
||||||
OPCODE_LOAD_VECTOR_SHL,
|
OPCODE_LOAD_VECTOR_SHL,
|
||||||
OPCODE_LOAD_VECTOR_SHR,
|
OPCODE_LOAD_VECTOR_SHR,
|
||||||
|
|
||||||
OPCODE_LOAD_CLOCK,
|
OPCODE_LOAD_CLOCK,
|
||||||
|
|
||||||
OPCODE_LOAD_LOCAL,
|
OPCODE_LOAD_LOCAL,
|
||||||
OPCODE_STORE_LOCAL,
|
OPCODE_STORE_LOCAL,
|
||||||
|
|
||||||
OPCODE_LOAD_CONTEXT,
|
OPCODE_LOAD_CONTEXT,
|
||||||
OPCODE_STORE_CONTEXT,
|
OPCODE_STORE_CONTEXT,
|
||||||
|
|
||||||
OPCODE_LOAD,
|
OPCODE_LOAD,
|
||||||
OPCODE_STORE,
|
OPCODE_STORE,
|
||||||
OPCODE_PREFETCH,
|
OPCODE_PREFETCH,
|
||||||
|
|
||||||
OPCODE_MAX,
|
OPCODE_MAX,
|
||||||
OPCODE_MIN,
|
OPCODE_MIN,
|
||||||
OPCODE_SELECT,
|
OPCODE_SELECT,
|
||||||
|
@ -152,13 +134,12 @@ enum Opcode {
|
||||||
OPCODE_VECTOR_COMPARE_SGE,
|
OPCODE_VECTOR_COMPARE_SGE,
|
||||||
OPCODE_VECTOR_COMPARE_UGT,
|
OPCODE_VECTOR_COMPARE_UGT,
|
||||||
OPCODE_VECTOR_COMPARE_UGE,
|
OPCODE_VECTOR_COMPARE_UGE,
|
||||||
|
|
||||||
OPCODE_ADD,
|
OPCODE_ADD,
|
||||||
OPCODE_ADD_CARRY,
|
OPCODE_ADD_CARRY,
|
||||||
OPCODE_VECTOR_ADD,
|
OPCODE_VECTOR_ADD,
|
||||||
OPCODE_SUB,
|
OPCODE_SUB,
|
||||||
OPCODE_MUL,
|
OPCODE_MUL,
|
||||||
OPCODE_MUL_HI, // TODO(benvanik): remove this and add INT128 type.
|
OPCODE_MUL_HI, // TODO(benvanik): remove this and add INT128 type.
|
||||||
OPCODE_DIV,
|
OPCODE_DIV,
|
||||||
OPCODE_MUL_ADD,
|
OPCODE_MUL_ADD,
|
||||||
OPCODE_MUL_SUB,
|
OPCODE_MUL_SUB,
|
||||||
|
@ -170,7 +151,6 @@ enum Opcode {
|
||||||
OPCODE_LOG2,
|
OPCODE_LOG2,
|
||||||
OPCODE_DOT_PRODUCT_3,
|
OPCODE_DOT_PRODUCT_3,
|
||||||
OPCODE_DOT_PRODUCT_4,
|
OPCODE_DOT_PRODUCT_4,
|
||||||
|
|
||||||
OPCODE_AND,
|
OPCODE_AND,
|
||||||
OPCODE_OR,
|
OPCODE_OR,
|
||||||
OPCODE_XOR,
|
OPCODE_XOR,
|
||||||
|
@ -191,22 +171,20 @@ enum Opcode {
|
||||||
OPCODE_SWIZZLE,
|
OPCODE_SWIZZLE,
|
||||||
OPCODE_PACK,
|
OPCODE_PACK,
|
||||||
OPCODE_UNPACK,
|
OPCODE_UNPACK,
|
||||||
|
|
||||||
OPCODE_COMPARE_EXCHANGE,
|
OPCODE_COMPARE_EXCHANGE,
|
||||||
OPCODE_ATOMIC_EXCHANGE,
|
OPCODE_ATOMIC_EXCHANGE,
|
||||||
OPCODE_ATOMIC_ADD,
|
OPCODE_ATOMIC_ADD,
|
||||||
OPCODE_ATOMIC_SUB,
|
OPCODE_ATOMIC_SUB,
|
||||||
|
__OPCODE_MAX_VALUE, // Keep at end.
|
||||||
__OPCODE_MAX_VALUE, // Keep at end.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum OpcodeFlags {
|
enum OpcodeFlags {
|
||||||
OPCODE_FLAG_BRANCH = (1 << 1),
|
OPCODE_FLAG_BRANCH = (1 << 1),
|
||||||
OPCODE_FLAG_MEMORY = (1 << 2),
|
OPCODE_FLAG_MEMORY = (1 << 2),
|
||||||
OPCODE_FLAG_COMMUNATIVE = (1 << 3),
|
OPCODE_FLAG_COMMUNATIVE = (1 << 3),
|
||||||
OPCODE_FLAG_VOLATILE = (1 << 4),
|
OPCODE_FLAG_VOLATILE = (1 << 4),
|
||||||
OPCODE_FLAG_IGNORE = (1 << 5),
|
OPCODE_FLAG_IGNORE = (1 << 5),
|
||||||
OPCODE_FLAG_HIDE = (1 << 6),
|
OPCODE_FLAG_HIDE = (1 << 6),
|
||||||
OPCODE_FLAG_PAIRED_PREV = (1 << 7),
|
OPCODE_FLAG_PAIRED_PREV = (1 << 7),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -220,26 +198,38 @@ enum OpcodeSignatureType {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum OpcodeSignature {
|
enum OpcodeSignature {
|
||||||
OPCODE_SIG_X = (OPCODE_SIG_TYPE_X),
|
OPCODE_SIG_X = (OPCODE_SIG_TYPE_X),
|
||||||
OPCODE_SIG_X_L = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_L << 3),
|
OPCODE_SIG_X_L = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_L << 3),
|
||||||
OPCODE_SIG_X_O = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_O << 3),
|
OPCODE_SIG_X_O = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_O << 3),
|
||||||
OPCODE_SIG_X_O_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_O << 3) | (OPCODE_SIG_TYPE_V << 6),
|
OPCODE_SIG_X_O_V =
|
||||||
OPCODE_SIG_X_S = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_S << 3),
|
(OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_O << 3) | (OPCODE_SIG_TYPE_V << 6),
|
||||||
OPCODE_SIG_X_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3),
|
OPCODE_SIG_X_S = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_S << 3),
|
||||||
OPCODE_SIG_X_V_L = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_L << 6),
|
OPCODE_SIG_X_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3),
|
||||||
OPCODE_SIG_X_V_L_L = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_L << 6) | (OPCODE_SIG_TYPE_L << 9),
|
OPCODE_SIG_X_V_L =
|
||||||
OPCODE_SIG_X_V_O = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_O << 6),
|
(OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_L << 6),
|
||||||
OPCODE_SIG_X_V_S = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_S << 6),
|
OPCODE_SIG_X_V_L_L = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) |
|
||||||
OPCODE_SIG_X_V_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6),
|
(OPCODE_SIG_TYPE_L << 6) | (OPCODE_SIG_TYPE_L << 9),
|
||||||
OPCODE_SIG_X_V_V_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6) | (OPCODE_SIG_TYPE_V << 9),
|
OPCODE_SIG_X_V_O =
|
||||||
OPCODE_SIG_V = (OPCODE_SIG_TYPE_V),
|
(OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_O << 6),
|
||||||
OPCODE_SIG_V_O = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_O << 3),
|
OPCODE_SIG_X_V_S =
|
||||||
OPCODE_SIG_V_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3),
|
(OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_S << 6),
|
||||||
OPCODE_SIG_V_V_O = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_O << 6),
|
OPCODE_SIG_X_V_V =
|
||||||
OPCODE_SIG_V_V_O_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_O << 6) | (OPCODE_SIG_TYPE_V << 9),
|
(OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6),
|
||||||
OPCODE_SIG_V_V_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6),
|
OPCODE_SIG_X_V_V_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) |
|
||||||
OPCODE_SIG_V_V_V_O = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6) | (OPCODE_SIG_TYPE_O << 9),
|
(OPCODE_SIG_TYPE_V << 6) | (OPCODE_SIG_TYPE_V << 9),
|
||||||
OPCODE_SIG_V_V_V_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6) | (OPCODE_SIG_TYPE_V << 9),
|
OPCODE_SIG_V = (OPCODE_SIG_TYPE_V),
|
||||||
|
OPCODE_SIG_V_O = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_O << 3),
|
||||||
|
OPCODE_SIG_V_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3),
|
||||||
|
OPCODE_SIG_V_V_O =
|
||||||
|
(OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_O << 6),
|
||||||
|
OPCODE_SIG_V_V_O_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) |
|
||||||
|
(OPCODE_SIG_TYPE_O << 6) | (OPCODE_SIG_TYPE_V << 9),
|
||||||
|
OPCODE_SIG_V_V_V =
|
||||||
|
(OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6),
|
||||||
|
OPCODE_SIG_V_V_V_O = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) |
|
||||||
|
(OPCODE_SIG_TYPE_V << 6) | (OPCODE_SIG_TYPE_O << 9),
|
||||||
|
OPCODE_SIG_V_V_V_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) |
|
||||||
|
(OPCODE_SIG_TYPE_V << 6) | (OPCODE_SIG_TYPE_V << 9),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GET_OPCODE_SIG_TYPE_DEST(sig) (OpcodeSignatureType)(sig & 0x7)
|
#define GET_OPCODE_SIG_TYPE_DEST(sig) (OpcodeSignatureType)(sig & 0x7)
|
||||||
|
@ -248,21 +238,17 @@ enum OpcodeSignature {
|
||||||
#define GET_OPCODE_SIG_TYPE_SRC3(sig) (OpcodeSignatureType)((sig >> 9) & 0x7)
|
#define GET_OPCODE_SIG_TYPE_SRC3(sig) (OpcodeSignatureType)((sig >> 9) & 0x7)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t signature;
|
uint32_t signature;
|
||||||
const char* name;
|
const char* name;
|
||||||
Opcode num;
|
Opcode num;
|
||||||
} OpcodeInfo;
|
} OpcodeInfo;
|
||||||
|
|
||||||
|
#define DEFINE_OPCODE(num, name, sig, flags) extern const OpcodeInfo num##_info;
|
||||||
#define DEFINE_OPCODE(num, name, sig, flags) \
|
|
||||||
extern const OpcodeInfo num##_info;
|
|
||||||
#include <alloy/hir/opcodes.inl>
|
#include <alloy/hir/opcodes.inl>
|
||||||
#undef DEFINE_OPCODE
|
#undef DEFINE_OPCODE
|
||||||
|
|
||||||
|
|
||||||
} // namespace hir
|
} // namespace hir
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_HIR_OPCODES_H_
|
#endif // ALLOY_HIR_OPCODES_H_
|
||||||
|
|
|
@ -13,23 +13,19 @@
|
||||||
#include <alloy/tracing/tracing.h>
|
#include <alloy/tracing/tracing.h>
|
||||||
#include <alloy/tracing/event_type.h>
|
#include <alloy/tracing/event_type.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace hir {
|
namespace hir {
|
||||||
|
|
||||||
const uint32_t ALLOY_HIR = alloy::tracing::EventType::ALLOY_HIR;
|
const uint32_t ALLOY_HIR = alloy::tracing::EventType::ALLOY_HIR;
|
||||||
|
|
||||||
|
|
||||||
class EventType {
|
class EventType {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
ALLOY_HIR_FOO = ALLOY_HIR | (0),
|
ALLOY_HIR_FOO = ALLOY_HIR | (0),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace hir
|
} // namespace hir
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_HIR_TRACING_H_
|
#endif // ALLOY_HIR_TRACING_H_
|
||||||
|
|
|
@ -9,9 +9,8 @@
|
||||||
|
|
||||||
#include <alloy/hir/value.h>
|
#include <alloy/hir/value.h>
|
||||||
|
|
||||||
using namespace alloy;
|
namespace alloy {
|
||||||
using namespace alloy::hir;
|
namespace hir {
|
||||||
|
|
||||||
|
|
||||||
Value::Use* Value::AddUse(Arena* arena, Instr* instr) {
|
Value::Use* Value::AddUse(Arena* arena, Instr* instr) {
|
||||||
Use* use = arena->Alloc<Use>();
|
Use* use = arena->Alloc<Use>();
|
||||||
|
@ -39,34 +38,34 @@ void Value::RemoveUse(Use* use) {
|
||||||
uint32_t Value::AsUint32() {
|
uint32_t Value::AsUint32() {
|
||||||
XEASSERT(IsConstant());
|
XEASSERT(IsConstant());
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
return constant.i8;
|
return constant.i8;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
return constant.i16;
|
return constant.i16;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
return constant.i32;
|
return constant.i32;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
return (uint32_t)constant.i64;
|
return (uint32_t)constant.i64;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Value::AsUint64() {
|
uint64_t Value::AsUint64() {
|
||||||
XEASSERT(IsConstant());
|
XEASSERT(IsConstant());
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
return constant.i8;
|
return constant.i8;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
return constant.i16;
|
return constant.i16;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
return constant.i32;
|
return constant.i32;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
return constant.i64;
|
return constant.i64;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,87 +76,6 @@ void Value::Cast(TypeName target_type) {
|
||||||
|
|
||||||
void Value::ZeroExtend(TypeName target_type) {
|
void Value::ZeroExtend(TypeName target_type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
|
||||||
type = target_type;
|
|
||||||
constant.i64 = constant.i64 & 0xFF;
|
|
||||||
return;
|
|
||||||
case INT16_TYPE:
|
|
||||||
type = target_type;
|
|
||||||
constant.i64 = constant.i64 & 0xFFFF;
|
|
||||||
return;
|
|
||||||
case INT32_TYPE:
|
|
||||||
type = target_type;
|
|
||||||
constant.i64 = constant.i64 & 0xFFFFFFFF;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Unsupported types.
|
|
||||||
XEASSERTALWAYS();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Value::SignExtend(TypeName target_type) {
|
|
||||||
switch (type) {
|
|
||||||
case INT8_TYPE:
|
|
||||||
type = target_type;
|
|
||||||
switch (target_type) {
|
|
||||||
case INT16_TYPE:
|
|
||||||
constant.i16 = constant.i8;
|
|
||||||
break;
|
|
||||||
case INT32_TYPE:
|
|
||||||
constant.i32 = constant.i8;
|
|
||||||
break;
|
|
||||||
case INT64_TYPE:
|
|
||||||
constant.i64 = constant.i8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case INT16_TYPE:
|
|
||||||
type = target_type;
|
|
||||||
switch (target_type) {
|
|
||||||
case INT32_TYPE:
|
|
||||||
constant.i32 = constant.i16;
|
|
||||||
break;
|
|
||||||
case INT64_TYPE:
|
|
||||||
constant.i64 = constant.i16;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case INT32_TYPE:
|
|
||||||
type = target_type;
|
|
||||||
switch (target_type) {
|
|
||||||
case INT64_TYPE:
|
|
||||||
constant.i64 = constant.i32;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Unsupported types.
|
|
||||||
XEASSERTALWAYS();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Value::Truncate(TypeName target_type) {
|
|
||||||
switch (type) {
|
|
||||||
case INT16_TYPE:
|
|
||||||
switch (target_type) {
|
|
||||||
case INT8_TYPE:
|
|
||||||
type = target_type;
|
|
||||||
constant.i64 = constant.i64 & 0xFF;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case INT32_TYPE:
|
|
||||||
switch (target_type) {
|
|
||||||
case INT8_TYPE:
|
|
||||||
type = target_type;
|
|
||||||
constant.i64 = constant.i64 & 0xFF;
|
|
||||||
return;
|
|
||||||
case INT16_TYPE:
|
|
||||||
type = target_type;
|
|
||||||
constant.i64 = constant.i64 & 0xFFFF;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case INT64_TYPE:
|
|
||||||
switch (target_type) {
|
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
type = target_type;
|
type = target_type;
|
||||||
constant.i64 = constant.i64 & 0xFF;
|
constant.i64 = constant.i64 & 0xFF;
|
||||||
|
@ -170,8 +88,89 @@ void Value::Truncate(TypeName target_type) {
|
||||||
type = target_type;
|
type = target_type;
|
||||||
constant.i64 = constant.i64 & 0xFFFFFFFF;
|
constant.i64 = constant.i64 & 0xFFFFFFFF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
// Unsupported types.
|
||||||
|
XEASSERTALWAYS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::SignExtend(TypeName target_type) {
|
||||||
|
switch (type) {
|
||||||
|
case INT8_TYPE:
|
||||||
|
type = target_type;
|
||||||
|
switch (target_type) {
|
||||||
|
case INT16_TYPE:
|
||||||
|
constant.i16 = constant.i8;
|
||||||
|
break;
|
||||||
|
case INT32_TYPE:
|
||||||
|
constant.i32 = constant.i8;
|
||||||
|
break;
|
||||||
|
case INT64_TYPE:
|
||||||
|
constant.i64 = constant.i8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case INT16_TYPE:
|
||||||
|
type = target_type;
|
||||||
|
switch (target_type) {
|
||||||
|
case INT32_TYPE:
|
||||||
|
constant.i32 = constant.i16;
|
||||||
|
break;
|
||||||
|
case INT64_TYPE:
|
||||||
|
constant.i64 = constant.i16;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case INT32_TYPE:
|
||||||
|
type = target_type;
|
||||||
|
switch (target_type) {
|
||||||
|
case INT64_TYPE:
|
||||||
|
constant.i64 = constant.i32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Unsupported types.
|
||||||
|
XEASSERTALWAYS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::Truncate(TypeName target_type) {
|
||||||
|
switch (type) {
|
||||||
|
case INT16_TYPE:
|
||||||
|
switch (target_type) {
|
||||||
|
case INT8_TYPE:
|
||||||
|
type = target_type;
|
||||||
|
constant.i64 = constant.i64 & 0xFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INT32_TYPE:
|
||||||
|
switch (target_type) {
|
||||||
|
case INT8_TYPE:
|
||||||
|
type = target_type;
|
||||||
|
constant.i64 = constant.i64 & 0xFF;
|
||||||
|
return;
|
||||||
|
case INT16_TYPE:
|
||||||
|
type = target_type;
|
||||||
|
constant.i64 = constant.i64 & 0xFFFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INT64_TYPE:
|
||||||
|
switch (target_type) {
|
||||||
|
case INT8_TYPE:
|
||||||
|
type = target_type;
|
||||||
|
constant.i64 = constant.i64 & 0xFF;
|
||||||
|
return;
|
||||||
|
case INT16_TYPE:
|
||||||
|
type = target_type;
|
||||||
|
constant.i64 = constant.i64 & 0xFFFF;
|
||||||
|
return;
|
||||||
|
case INT32_TYPE:
|
||||||
|
type = target_type;
|
||||||
|
constant.i64 = constant.i64 & 0xFFFFFFFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// Unsupported types.
|
// Unsupported types.
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
|
@ -188,70 +187,70 @@ void Value::Round(RoundMode round_mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::Add(Value* other) {
|
bool Value::Add(Value* other) {
|
||||||
#define CHECK_DID_CARRY(v1, v2) (((uint64_t)v2) > ~((uint64_t)v1))
|
#define CHECK_DID_CARRY(v1, v2) (((uint64_t)v2) > ~((uint64_t)v1))
|
||||||
#define ADD_DID_CARRY(a, b) CHECK_DID_CARRY(a, b)
|
#define ADD_DID_CARRY(a, b) CHECK_DID_CARRY(a, b)
|
||||||
XEASSERT(type == other->type);
|
XEASSERT(type == other->type);
|
||||||
bool did_carry = false;
|
bool did_carry = false;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
did_carry = ADD_DID_CARRY(constant.i8, other->constant.i8);
|
did_carry = ADD_DID_CARRY(constant.i8, other->constant.i8);
|
||||||
constant.i8 += other->constant.i8;
|
constant.i8 += other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
did_carry = ADD_DID_CARRY(constant.i16, other->constant.i16);
|
did_carry = ADD_DID_CARRY(constant.i16, other->constant.i16);
|
||||||
constant.i16 += other->constant.i16;
|
constant.i16 += other->constant.i16;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
did_carry = ADD_DID_CARRY(constant.i32, other->constant.i32);
|
did_carry = ADD_DID_CARRY(constant.i32, other->constant.i32);
|
||||||
constant.i32 += other->constant.i32;
|
constant.i32 += other->constant.i32;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
did_carry = ADD_DID_CARRY(constant.i64, other->constant.i64);
|
did_carry = ADD_DID_CARRY(constant.i64, other->constant.i64);
|
||||||
constant.i64 += other->constant.i64;
|
constant.i64 += other->constant.i64;
|
||||||
break;
|
break;
|
||||||
case FLOAT32_TYPE:
|
case FLOAT32_TYPE:
|
||||||
constant.f32 += other->constant.f32;
|
constant.f32 += other->constant.f32;
|
||||||
break;
|
break;
|
||||||
case FLOAT64_TYPE:
|
case FLOAT64_TYPE:
|
||||||
constant.f64 += other->constant.f64;
|
constant.f64 += other->constant.f64;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return did_carry;
|
return did_carry;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::Sub(Value* other) {
|
bool Value::Sub(Value* other) {
|
||||||
#define SUB_DID_CARRY(a, b) (b > a)
|
#define SUB_DID_CARRY(a, b) (b > a)
|
||||||
XEASSERT(type == other->type);
|
XEASSERT(type == other->type);
|
||||||
bool did_carry = false;
|
bool did_carry = false;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
did_carry = SUB_DID_CARRY(constant.i8, other->constant.i8);
|
did_carry = SUB_DID_CARRY(constant.i8, other->constant.i8);
|
||||||
constant.i8 -= other->constant.i8;
|
constant.i8 -= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
did_carry = SUB_DID_CARRY(constant.i16, other->constant.i16);
|
did_carry = SUB_DID_CARRY(constant.i16, other->constant.i16);
|
||||||
constant.i16 -= other->constant.i16;
|
constant.i16 -= other->constant.i16;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
did_carry = SUB_DID_CARRY(constant.i32, other->constant.i32);
|
did_carry = SUB_DID_CARRY(constant.i32, other->constant.i32);
|
||||||
constant.i32 -= other->constant.i32;
|
constant.i32 -= other->constant.i32;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
did_carry = SUB_DID_CARRY(constant.i64, other->constant.i64);
|
did_carry = SUB_DID_CARRY(constant.i64, other->constant.i64);
|
||||||
constant.i64 -= other->constant.i64;
|
constant.i64 -= other->constant.i64;
|
||||||
break;
|
break;
|
||||||
case FLOAT32_TYPE:
|
case FLOAT32_TYPE:
|
||||||
constant.f32 -= other->constant.f32;
|
constant.f32 -= other->constant.f32;
|
||||||
break;
|
break;
|
||||||
case FLOAT64_TYPE:
|
case FLOAT64_TYPE:
|
||||||
constant.f64 -= other->constant.f64;
|
constant.f64 -= other->constant.f64;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return did_carry;
|
return did_carry;
|
||||||
}
|
}
|
||||||
|
@ -259,54 +258,54 @@ bool Value::Sub(Value* other) {
|
||||||
void Value::Mul(Value* other) {
|
void Value::Mul(Value* other) {
|
||||||
XEASSERT(type == other->type);
|
XEASSERT(type == other->type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 *= other->constant.i8;
|
constant.i8 *= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 *= other->constant.i16;
|
constant.i16 *= other->constant.i16;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 *= other->constant.i32;
|
constant.i32 *= other->constant.i32;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 *= other->constant.i64;
|
constant.i64 *= other->constant.i64;
|
||||||
break;
|
break;
|
||||||
case FLOAT32_TYPE:
|
case FLOAT32_TYPE:
|
||||||
constant.f32 *= other->constant.f32;
|
constant.f32 *= other->constant.f32;
|
||||||
break;
|
break;
|
||||||
case FLOAT64_TYPE:
|
case FLOAT64_TYPE:
|
||||||
constant.f64 *= other->constant.f64;
|
constant.f64 *= other->constant.f64;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::Div(Value* other) {
|
void Value::Div(Value* other) {
|
||||||
XEASSERT(type == other->type);
|
XEASSERT(type == other->type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 /= other->constant.i8;
|
constant.i8 /= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 /= other->constant.i16;
|
constant.i16 /= other->constant.i16;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 /= other->constant.i32;
|
constant.i32 /= other->constant.i32;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 /= other->constant.i64;
|
constant.i64 /= other->constant.i64;
|
||||||
break;
|
break;
|
||||||
case FLOAT32_TYPE:
|
case FLOAT32_TYPE:
|
||||||
constant.f32 /= other->constant.f32;
|
constant.f32 /= other->constant.f32;
|
||||||
break;
|
break;
|
||||||
case FLOAT64_TYPE:
|
case FLOAT64_TYPE:
|
||||||
constant.f64 /= other->constant.f64;
|
constant.f64 /= other->constant.f64;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,276 +321,276 @@ void Value::MulSub(Value* dest, Value* value1, Value* value2, Value* value3) {
|
||||||
|
|
||||||
void Value::Neg() {
|
void Value::Neg() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 = -constant.i8;
|
constant.i8 = -constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 = -constant.i16;
|
constant.i16 = -constant.i16;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 = -constant.i32;
|
constant.i32 = -constant.i32;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 = -constant.i64;
|
constant.i64 = -constant.i64;
|
||||||
break;
|
break;
|
||||||
case FLOAT32_TYPE:
|
case FLOAT32_TYPE:
|
||||||
constant.f32 = -constant.f32;
|
constant.f32 = -constant.f32;
|
||||||
break;
|
break;
|
||||||
case FLOAT64_TYPE:
|
case FLOAT64_TYPE:
|
||||||
constant.f64 = -constant.f64;
|
constant.f64 = -constant.f64;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::Abs() {
|
void Value::Abs() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 = abs(constant.i8);
|
constant.i8 = abs(constant.i8);
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 = abs(constant.i16);
|
constant.i16 = abs(constant.i16);
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 = abs(constant.i32);
|
constant.i32 = abs(constant.i32);
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 = abs(constant.i64);
|
constant.i64 = abs(constant.i64);
|
||||||
break;
|
break;
|
||||||
case FLOAT32_TYPE:
|
case FLOAT32_TYPE:
|
||||||
constant.f32 = abs(constant.f32);
|
constant.f32 = abs(constant.f32);
|
||||||
break;
|
break;
|
||||||
case FLOAT64_TYPE:
|
case FLOAT64_TYPE:
|
||||||
constant.f64 = abs(constant.f64);
|
constant.f64 = abs(constant.f64);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::Sqrt() {
|
void Value::Sqrt() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case FLOAT32_TYPE:
|
case FLOAT32_TYPE:
|
||||||
constant.f32 = 1.0f / sqrtf(constant.f32);
|
constant.f32 = 1.0f / sqrtf(constant.f32);
|
||||||
break;
|
break;
|
||||||
case FLOAT64_TYPE:
|
case FLOAT64_TYPE:
|
||||||
constant.f64 = 1.0 / sqrt(constant.f64);
|
constant.f64 = 1.0 / sqrt(constant.f64);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::RSqrt() {
|
void Value::RSqrt() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case FLOAT32_TYPE:
|
case FLOAT32_TYPE:
|
||||||
constant.f32 = sqrt(constant.f32);
|
constant.f32 = sqrt(constant.f32);
|
||||||
break;
|
break;
|
||||||
case FLOAT64_TYPE:
|
case FLOAT64_TYPE:
|
||||||
constant.f64 = sqrt(constant.f64);
|
constant.f64 = sqrt(constant.f64);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::And(Value* other) {
|
void Value::And(Value* other) {
|
||||||
XEASSERT(type == other->type);
|
XEASSERT(type == other->type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 &= other->constant.i8;
|
constant.i8 &= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 &= other->constant.i16;
|
constant.i16 &= other->constant.i16;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 &= other->constant.i32;
|
constant.i32 &= other->constant.i32;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 &= other->constant.i64;
|
constant.i64 &= other->constant.i64;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::Or(Value* other) {
|
void Value::Or(Value* other) {
|
||||||
XEASSERT(type == other->type);
|
XEASSERT(type == other->type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 |= other->constant.i8;
|
constant.i8 |= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 |= other->constant.i16;
|
constant.i16 |= other->constant.i16;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 |= other->constant.i32;
|
constant.i32 |= other->constant.i32;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 |= other->constant.i64;
|
constant.i64 |= other->constant.i64;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::Xor(Value* other) {
|
void Value::Xor(Value* other) {
|
||||||
XEASSERT(type == other->type);
|
XEASSERT(type == other->type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 ^= other->constant.i8;
|
constant.i8 ^= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 ^= other->constant.i16;
|
constant.i16 ^= other->constant.i16;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 ^= other->constant.i32;
|
constant.i32 ^= other->constant.i32;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 ^= other->constant.i64;
|
constant.i64 ^= other->constant.i64;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::Not() {
|
void Value::Not() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 = ~constant.i8;
|
constant.i8 = ~constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 = ~constant.i16;
|
constant.i16 = ~constant.i16;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 = ~constant.i32;
|
constant.i32 = ~constant.i32;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 = ~constant.i64;
|
constant.i64 = ~constant.i64;
|
||||||
break;
|
break;
|
||||||
case VEC128_TYPE:
|
case VEC128_TYPE:
|
||||||
constant.v128.low = ~constant.v128.low;
|
constant.v128.low = ~constant.v128.low;
|
||||||
constant.v128.high = ~constant.v128.high;
|
constant.v128.high = ~constant.v128.high;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::Shl(Value* other) {
|
void Value::Shl(Value* other) {
|
||||||
XEASSERT(other->type == INT8_TYPE);
|
XEASSERT(other->type == INT8_TYPE);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 <<= other->constant.i8;
|
constant.i8 <<= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 <<= other->constant.i8;
|
constant.i16 <<= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 <<= other->constant.i8;
|
constant.i32 <<= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 <<= other->constant.i8;
|
constant.i64 <<= other->constant.i8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::Shr(Value* other) {
|
void Value::Shr(Value* other) {
|
||||||
XEASSERT(other->type == INT8_TYPE);
|
XEASSERT(other->type == INT8_TYPE);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 = (uint8_t)constant.i8 >> other->constant.i8;
|
constant.i8 = (uint8_t)constant.i8 >> other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 = (uint16_t)constant.i16 >> other->constant.i8;
|
constant.i16 = (uint16_t)constant.i16 >> other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 = (uint32_t)constant.i32 >> other->constant.i8;
|
constant.i32 = (uint32_t)constant.i32 >> other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 = (uint16_t)constant.i64 >> other->constant.i8;
|
constant.i64 = (uint16_t)constant.i64 >> other->constant.i8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::Sha(Value* other) {
|
void Value::Sha(Value* other) {
|
||||||
XEASSERT(other->type == INT8_TYPE);
|
XEASSERT(other->type == INT8_TYPE);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 = constant.i8 >> other->constant.i8;
|
constant.i8 = constant.i8 >> other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 = constant.i16 >> other->constant.i8;
|
constant.i16 = constant.i16 >> other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 = constant.i32 >> other->constant.i8;
|
constant.i32 = constant.i32 >> other->constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 = constant.i64 >> other->constant.i8;
|
constant.i64 = constant.i64 >> other->constant.i8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::ByteSwap() {
|
void Value::ByteSwap() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 = constant.i8;
|
constant.i8 = constant.i8;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i16 = XESWAP16(constant.i16);
|
constant.i16 = XESWAP16(constant.i16);
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i32 = XESWAP32(constant.i32);
|
constant.i32 = XESWAP32(constant.i32);
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i64 = XESWAP64(constant.i64);
|
constant.i64 = XESWAP64(constant.i64);
|
||||||
break;
|
break;
|
||||||
case VEC128_TYPE:
|
case VEC128_TYPE:
|
||||||
for (int n = 0; n < 4; n++) {
|
for (int n = 0; n < 4; n++) {
|
||||||
constant.v128.i4[n] = XESWAP32(constant.v128.i4[n]);
|
constant.v128.i4[n] = XESWAP32(constant.v128.i4[n]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::CountLeadingZeros(const Value* other) {
|
void Value::CountLeadingZeros(const Value* other) {
|
||||||
switch (other->type) {
|
switch (other->type) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
constant.i8 = static_cast<uint8_t>(__lzcnt16(other->constant.i8) - 8);
|
constant.i8 = static_cast<uint8_t>(__lzcnt16(other->constant.i8) - 8);
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
constant.i8 = static_cast<uint8_t>(__lzcnt16(other->constant.i16));
|
constant.i8 = static_cast<uint8_t>(__lzcnt16(other->constant.i16));
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
constant.i8 = static_cast<uint8_t>(__lzcnt(other->constant.i32));
|
constant.i8 = static_cast<uint8_t>(__lzcnt(other->constant.i32));
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
constant.i8 = static_cast<uint8_t>(__lzcnt64(other->constant.i64));
|
constant.i8 = static_cast<uint8_t>(__lzcnt64(other->constant.i64));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,3 +599,6 @@ bool Value::Compare(Opcode opcode, Value* other) {
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace hir
|
||||||
|
} // namespace alloy
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue