Ugh. Replacing the fancy templates with hand coded sequences for now.
This commit is contained in:
parent
3e4f93a6a9
commit
125e7278c6
|
@ -49,10 +49,18 @@ void LIRBuilder::Dump(StringBuffer* str) {
|
||||||
|
|
||||||
auto label = block->label_head;
|
auto label = block->label_head;
|
||||||
while (label) {
|
while (label) {
|
||||||
if (label->name) {
|
if (label->local) {
|
||||||
str->Append("%s:\n", label->name);
|
if (label->name) {
|
||||||
|
str->Append(".%s:\n", label->name);
|
||||||
|
} else {
|
||||||
|
str->Append(".label%d:\n", label->id);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
str->Append("label%d:\n", label->id);
|
if (label->name) {
|
||||||
|
str->Append("%s:\n", label->name);
|
||||||
|
} else {
|
||||||
|
str->Append("label%d:\n", label->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
label = label->next;
|
label = label->next;
|
||||||
}
|
}
|
||||||
|
@ -63,8 +71,11 @@ void LIRBuilder::Dump(StringBuffer* str) {
|
||||||
i = i->next;
|
i = i->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (i->opcode == &LIR_OPCODE_COMMENT_info) {
|
||||||
// TODO(benvanik): handle comment
|
str->Append(" ; %s\n", (char*)i->arg[0].i64);
|
||||||
|
i = i->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const LIROpcodeInfo* info = i->opcode;
|
const LIROpcodeInfo* info = i->opcode;
|
||||||
str->Append(" ");
|
str->Append(" ");
|
||||||
|
@ -95,12 +106,14 @@ LIRInstr* LIRBuilder::last_instr() const {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIRLabel* LIRBuilder::NewLabel() {
|
LIRLabel* LIRBuilder::NewLabel(bool local) {
|
||||||
LIRLabel* label = arena_->Alloc<LIRLabel>();
|
LIRLabel* label = arena_->Alloc<LIRLabel>();
|
||||||
label->next = label->prev = NULL;
|
label->next = label->prev = NULL;
|
||||||
label->block = NULL;
|
label->block = NULL;
|
||||||
label->id = next_label_id_++;
|
label->id = next_label_id_++;
|
||||||
label->name = NULL;
|
label->name = NULL;
|
||||||
|
label->local = local;
|
||||||
|
label->tag = NULL;
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,3 +187,51 @@ LIRInstr* LIRBuilder::AppendInstr(
|
||||||
instr->flags = flags;
|
instr->flags = flags;
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Comment(const char* format, ...) {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_COMMENT_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Nop() {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_NOP_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::SourceOffset(uint64_t offset) {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_SOURCE_OFFSET_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::DebugBreak() {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_DEBUG_BREAK_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Trap() {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_TRAP_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Test(int8_t a, int8_t b) {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_TEST_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Test(int16_t a, int16_t b) {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_TEST_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Test(int32_t a, int32_t b) {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_TEST_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Test(int64_t a, int64_t b) {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_TEST_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Test(hir::Value* a, hir::Value* b) {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_TEST_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::JumpEQ(LIRLabel* label) {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_JUMP_EQ_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::JumpNE(LIRLabel* label) {
|
||||||
|
auto instr = AppendInstr(LIR_OPCODE_JUMP_NE_info);
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <alloy/backend/x64/lir/lir_instr.h>
|
#include <alloy/backend/x64/lir/lir_instr.h>
|
||||||
#include <alloy/backend/x64/lir/lir_label.h>
|
#include <alloy/backend/x64/lir/lir_label.h>
|
||||||
#include <alloy/backend/x64/lir/lir_opcodes.h>
|
#include <alloy/backend/x64/lir/lir_opcodes.h>
|
||||||
|
#include <alloy/hir/value.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
|
@ -40,16 +41,37 @@ public:
|
||||||
LIRBlock* current_block() const;
|
LIRBlock* current_block() const;
|
||||||
LIRInstr* last_instr() const;
|
LIRInstr* last_instr() const;
|
||||||
|
|
||||||
LIRLabel* NewLabel();
|
LIRLabel* NewLabel(bool local = false);
|
||||||
|
LIRLabel* NewLocalLabel() { return NewLabel(true); }
|
||||||
void MarkLabel(LIRLabel* label, LIRBlock* block = 0);
|
void MarkLabel(LIRLabel* label, LIRBlock* block = 0);
|
||||||
|
|
||||||
// TODO(benvanik): allocations
|
// TODO(benvanik): allocations
|
||||||
|
|
||||||
LIRBlock* AppendBlock();
|
LIRBlock* AppendBlock();
|
||||||
void EndBlock();
|
void EndBlock();
|
||||||
LIRInstr* AppendInstr(const LIROpcodeInfo& opcode, uint16_t flags);
|
|
||||||
|
|
||||||
protected:
|
void Comment(const char* format, ...);
|
||||||
|
void Nop();
|
||||||
|
void SourceOffset(uint64_t offset);
|
||||||
|
|
||||||
|
void DebugBreak();
|
||||||
|
void Trap();
|
||||||
|
|
||||||
|
void Mov();
|
||||||
|
|
||||||
|
void Test(int8_t a, int8_t b);
|
||||||
|
void Test(int16_t a, int16_t b);
|
||||||
|
void Test(int32_t a, int32_t b);
|
||||||
|
void Test(int64_t a, int64_t b);
|
||||||
|
void Test(hir::Value* a, hir::Value* b);
|
||||||
|
|
||||||
|
void JumpEQ(LIRLabel* label);
|
||||||
|
void JumpNE(LIRLabel* label);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LIRInstr* AppendInstr(const LIROpcodeInfo& opcode, uint16_t flags = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
X64Backend* backend_;
|
X64Backend* backend_;
|
||||||
Arena* arena_;
|
Arena* arena_;
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,19 @@ enum LIRRegister {
|
||||||
XMM15,
|
XMM15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
runtime::FunctionInfo* symbol_info;
|
||||||
|
LIRLabel* label;
|
||||||
|
LIRRegister reg;
|
||||||
|
int8_t i8;
|
||||||
|
int16_t i16;
|
||||||
|
int32_t i32;
|
||||||
|
int64_t i64;
|
||||||
|
float f32;
|
||||||
|
double f64;
|
||||||
|
uint64_t offset;
|
||||||
|
} LIROperand;
|
||||||
|
|
||||||
|
|
||||||
class LIRInstr {
|
class LIRInstr {
|
||||||
public:
|
public:
|
||||||
|
@ -75,21 +88,8 @@ public:
|
||||||
const LIROpcodeInfo* opcode;
|
const LIROpcodeInfo* opcode;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
|
|
||||||
typedef union {
|
|
||||||
runtime::FunctionInfo* symbol_info;
|
|
||||||
LIRLabel* label;
|
|
||||||
LIRRegister reg;
|
|
||||||
int8_t i8;
|
|
||||||
int16_t i16;
|
|
||||||
int32_t i32;
|
|
||||||
int64_t i64;
|
|
||||||
float f32;
|
|
||||||
double f64;
|
|
||||||
uint64_t offset;
|
|
||||||
} Op;
|
|
||||||
|
|
||||||
// TODO(benvanik): make this variable width?
|
// TODO(benvanik): make this variable width?
|
||||||
Op arg[4];
|
LIROperand arg[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
|
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
char* name;
|
char* name;
|
||||||
|
bool local;
|
||||||
|
|
||||||
void* tag;
|
void* tag;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,11 +18,21 @@ namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
namespace lir {
|
namespace lir {
|
||||||
|
|
||||||
#define DEFINE_OPCODE(num, name, sig, flags) \
|
#define DEFINE_OPCODE(num, string_name, flags) \
|
||||||
static const LIROpcodeInfo num##_info = { flags, sig, name, num, };
|
static const LIROpcodeInfo num##_info = { flags, string_name, num, };
|
||||||
#include <alloy/backend/x64/lir/lir_opcodes.inl>
|
#include <alloy/backend/x64/lir/lir_opcodes.inl>
|
||||||
#undef DEFINE_OPCODE
|
#undef DEFINE_OPCODE
|
||||||
|
|
||||||
|
const LIROpcodeInfo& GetOpcodeInfo(LIROpcode opcode) {
|
||||||
|
static const LIROpcodeInfo* lookup[__LIR_OPCODE_MAX_VALUE] = {
|
||||||
|
#define DEFINE_OPCODE(num, string_name, flags) \
|
||||||
|
&num##_info,
|
||||||
|
#include <alloy/backend/x64/lir/lir_opcodes.inl>
|
||||||
|
#undef DEFINE_OPCODE
|
||||||
|
};
|
||||||
|
return *lookup[opcode];
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace lir
|
} // namespace lir
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
|
|
|
@ -20,13 +20,20 @@ namespace lir {
|
||||||
|
|
||||||
|
|
||||||
enum LIROpcode {
|
enum LIROpcode {
|
||||||
LIR_OPCODE_MOV_I32,
|
LIR_OPCODE_COMMENT,
|
||||||
LIR_OPCODE_XOR_I32,
|
LIR_OPCODE_NOP,
|
||||||
LIR_OPCODE_DEC_I32,
|
|
||||||
LIR_OPCODE_SUB_I32,
|
LIR_OPCODE_SOURCE_OFFSET,
|
||||||
LIR_OPCODE_IMUL_I32,
|
|
||||||
LIR_OPCODE_IMUL_I32_AUX,
|
LIR_OPCODE_DEBUG_BREAK,
|
||||||
LIR_OPCODE_DIV_I32,
|
LIR_OPCODE_TRAP,
|
||||||
|
|
||||||
|
LIR_OPCODE_MOV,
|
||||||
|
|
||||||
|
LIR_OPCODE_TEST,
|
||||||
|
|
||||||
|
LIR_OPCODE_JUMP_EQ,
|
||||||
|
LIR_OPCODE_JUMP_NE,
|
||||||
|
|
||||||
__LIR_OPCODE_MAX_VALUE, // Keep at end.
|
__LIR_OPCODE_MAX_VALUE, // Keep at end.
|
||||||
};
|
};
|
||||||
|
@ -40,36 +47,20 @@ enum LIROpcodeFlags {
|
||||||
LIR_OPCODE_FLAG_HIDE = (1 << 6),
|
LIR_OPCODE_FLAG_HIDE = (1 << 6),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LIROpcodeSignatureType {
|
|
||||||
// 3 bits max (0-7)
|
|
||||||
LIR_OPCODE_SIG_TYPE_X = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LIROpcodeSignature {
|
|
||||||
LIR_OPCODE_SIG_X = (LIR_OPCODE_SIG_TYPE_X),
|
|
||||||
LIR_OPCODE_SIG_R32 = (LIR_OPCODE_SIG_TYPE_X),
|
|
||||||
LIR_OPCODE_SIG_R32_R32 = (LIR_OPCODE_SIG_TYPE_X),
|
|
||||||
LIR_OPCODE_SIG_R32_R32_C32 = (LIR_OPCODE_SIG_TYPE_X),
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GET_LIR_OPCODE_SIG_TYPE_DEST(sig) (LIROpcodeSignatureType)(sig & 0x7)
|
|
||||||
#define GET_LIR_OPCODE_SIG_TYPE_SRC1(sig) (LIROpcodeSignatureType)((sig >> 3) & 0x7)
|
|
||||||
#define GET_LIR_OPCODE_SIG_TYPE_SRC2(sig) (LIROpcodeSignatureType)((sig >> 6) & 0x7)
|
|
||||||
#define GET_LIR_OPCODE_SIG_TYPE_SRC3(sig) (LIROpcodeSignatureType)((sig >> 9) & 0x7)
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t signature;
|
|
||||||
const char* name;
|
const char* name;
|
||||||
LIROpcode num;
|
LIROpcode num;
|
||||||
} LIROpcodeInfo;
|
} LIROpcodeInfo;
|
||||||
|
|
||||||
|
|
||||||
#define DEFINE_OPCODE(num, name, sig, flags) \
|
#define DEFINE_OPCODE(num, string_name, flags) \
|
||||||
extern const LIROpcodeInfo num##_info;
|
extern const LIROpcodeInfo num##_info;
|
||||||
#include <alloy/backend/x64/lir/lir_opcodes.inl>
|
#include <alloy/backend/x64/lir/lir_opcodes.inl>
|
||||||
#undef DEFINE_OPCODE
|
#undef DEFINE_OPCODE
|
||||||
|
|
||||||
|
extern const LIROpcodeInfo& GetOpcodeInfo(LIROpcode opcode);
|
||||||
|
|
||||||
|
|
||||||
} // namespace lir
|
} // namespace lir
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
|
|
|
@ -8,37 +8,46 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEFINE_OPCODE(
|
DEFINE_OPCODE(
|
||||||
LIR_OPCODE_MOV_I32,
|
LIR_OPCODE_COMMENT,
|
||||||
"mov.i32",
|
"comment",
|
||||||
LIR_OPCODE_SIG_R32_R32,
|
LIR_OPCODE_FLAG_IGNORE)
|
||||||
0);
|
|
||||||
DEFINE_OPCODE(
|
DEFINE_OPCODE(
|
||||||
LIR_OPCODE_XOR_I32,
|
LIR_OPCODE_NOP,
|
||||||
"xor.i32",
|
"nop",
|
||||||
LIR_OPCODE_SIG_R32_R32,
|
LIR_OPCODE_FLAG_IGNORE)
|
||||||
0);
|
|
||||||
DEFINE_OPCODE(
|
DEFINE_OPCODE(
|
||||||
LIR_OPCODE_DEC_I32,
|
LIR_OPCODE_SOURCE_OFFSET,
|
||||||
"dec.i32",
|
"source_offset",
|
||||||
LIR_OPCODE_SIG_R32,
|
LIR_OPCODE_FLAG_IGNORE | LIR_OPCODE_FLAG_HIDE)
|
||||||
0);
|
|
||||||
DEFINE_OPCODE(
|
DEFINE_OPCODE(
|
||||||
LIR_OPCODE_SUB_I32,
|
LIR_OPCODE_DEBUG_BREAK,
|
||||||
"sub.i32",
|
"debug_break",
|
||||||
LIR_OPCODE_SIG_R32_R32,
|
0)
|
||||||
0);
|
|
||||||
DEFINE_OPCODE(
|
DEFINE_OPCODE(
|
||||||
LIR_OPCODE_IMUL_I32,
|
LIR_OPCODE_TRAP,
|
||||||
"imul.i32",
|
"trap",
|
||||||
LIR_OPCODE_SIG_R32_R32,
|
0)
|
||||||
0);
|
|
||||||
DEFINE_OPCODE(
|
DEFINE_OPCODE(
|
||||||
LIR_OPCODE_IMUL_I32_AUX,
|
LIR_OPCODE_MOV,
|
||||||
"imul.i32.aux",
|
"mov",
|
||||||
LIR_OPCODE_SIG_R32_R32_C32,
|
0)
|
||||||
0);
|
|
||||||
DEFINE_OPCODE(
|
DEFINE_OPCODE(
|
||||||
LIR_OPCODE_DIV_I32,
|
LIR_OPCODE_TEST,
|
||||||
"div.i32",
|
"test",
|
||||||
LIR_OPCODE_SIG_R32,
|
0)
|
||||||
0);
|
|
||||||
|
DEFINE_OPCODE(
|
||||||
|
LIR_OPCODE_JUMP_EQ,
|
||||||
|
"jump_eq",
|
||||||
|
0)
|
||||||
|
|
||||||
|
DEFINE_OPCODE(
|
||||||
|
LIR_OPCODE_JUMP_NE,
|
||||||
|
"jump_ne",
|
||||||
|
0)
|
||||||
|
|
|
@ -1,112 +0,0 @@
|
||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
|
||||||
******************************************************************************
|
|
||||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
DEFINE_OPCODE_X(COMMENT);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_X(NOP);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_X_O(SOURCE_OFFSET);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_X(DEBUG_BREAK);
|
|
||||||
DEFINE_OPCODE_X_V(DEBUG_BREAK_TRUE);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_X(TRAP);
|
|
||||||
DEFINE_OPCODE_X_V(TRAP_TRUE);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_X_S(CALL);
|
|
||||||
DEFINE_OPCODE_X_V_S(CALL_TRUE);
|
|
||||||
DEFINE_OPCODE_X_V(CALL_INDIRECT);
|
|
||||||
DEFINE_OPCODE_X_V_V(CALL_INDIRECT_TRUE);
|
|
||||||
DEFINE_OPCODE_X(RETURN);
|
|
||||||
DEFINE_OPCODE_X_V(SET_RETURN_ADDRESS);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_X_L(BRANCH);
|
|
||||||
DEFINE_OPCODE_X_V_L(BRANCH_TRUE);
|
|
||||||
DEFINE_OPCODE_X_V_L(BRANCH_FALSE);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_V_V(ASSIGN);
|
|
||||||
DEFINE_OPCODE_V_V(CAST);
|
|
||||||
DEFINE_OPCODE_V_V(ZERO_EXTEND);
|
|
||||||
DEFINE_OPCODE_V_V(SIGN_EXTEND);
|
|
||||||
DEFINE_OPCODE_V_V(TRUNCATE);
|
|
||||||
DEFINE_OPCODE_V_V(CONVERT);
|
|
||||||
DEFINE_OPCODE_V_V(ROUND);
|
|
||||||
DEFINE_OPCODE_V_V(VECTOR_CONVERT_I2F);
|
|
||||||
DEFINE_OPCODE_V_V(VECTOR_CONVERT_F2I);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_V_V(LOAD_VECTOR_SHL);
|
|
||||||
DEFINE_OPCODE_V_V(LOAD_VECTOR_SHR);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_V_O(LOAD_CONTEXT);
|
|
||||||
DEFINE_OPCODE_V_O_V(STORE_CONTEXT);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_V_V(LOAD);
|
|
||||||
DEFINE_OPCODE_V_V(LOAD_ACQUIRE);
|
|
||||||
DEFINE_OPCODE_X_V_V(STORE);
|
|
||||||
DEFINE_OPCODE_V_V_V(STORE_RELEASE);
|
|
||||||
DEFINE_OPCODE_X_V_O(PREFETCH);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_V_V_V(MAX);
|
|
||||||
DEFINE_OPCODE_V_V_V(MIN);
|
|
||||||
DEFINE_OPCODE_V_V_V_V(SELECT);
|
|
||||||
DEFINE_OPCODE_V_V(IS_TRUE);
|
|
||||||
DEFINE_OPCODE_V_V(IS_FALSE);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_EQ);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_NE);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_SLT);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_SLE);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_SGT);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_SGE);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_ULT);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_ULE);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_UGT);
|
|
||||||
DEFINE_OPCODE_V_V_V(COMPARE_UGE);
|
|
||||||
DEFINE_OPCODE_V_V(DID_CARRY);
|
|
||||||
DEFINE_OPCODE_V_V(DID_OVERFLOW);
|
|
||||||
DEFINE_OPCODE_V_V_V(VECTOR_COMPARE_EQ);
|
|
||||||
DEFINE_OPCODE_V_V_V(VECTOR_COMPARE_SGT);
|
|
||||||
DEFINE_OPCODE_V_V_V(VECTOR_COMPARE_SGE);
|
|
||||||
DEFINE_OPCODE_V_V_V(VECTOR_COMPARE_UGT);
|
|
||||||
DEFINE_OPCODE_V_V_V(VECTOR_COMPARE_UGE);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_V_V_V(ADD);
|
|
||||||
DEFINE_OPCODE_V_V_V_V(ADD_CARRY);
|
|
||||||
DEFINE_OPCODE_V_V_V(SUB);
|
|
||||||
DEFINE_OPCODE_V_V_V(MUL);
|
|
||||||
DEFINE_OPCODE_V_V_V(DIV);
|
|
||||||
DEFINE_OPCODE_V_V_V(REM);
|
|
||||||
DEFINE_OPCODE_V_V_V_V(MULADD);
|
|
||||||
DEFINE_OPCODE_V_V_V_V(MULSUB);
|
|
||||||
DEFINE_OPCODE_V_V(NEG);
|
|
||||||
DEFINE_OPCODE_V_V(ABS);
|
|
||||||
DEFINE_OPCODE_V_V(SQRT);
|
|
||||||
DEFINE_OPCODE_V_V(RSQRT);
|
|
||||||
DEFINE_OPCODE_V_V_V(DOT_PRODUCT_3);
|
|
||||||
DEFINE_OPCODE_V_V_V(DOT_PRODUCT_4);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_V_V_V(AND);
|
|
||||||
DEFINE_OPCODE_V_V_V(OR);
|
|
||||||
DEFINE_OPCODE_V_V_V(XOR);
|
|
||||||
DEFINE_OPCODE_V_V(NOT);
|
|
||||||
DEFINE_OPCODE_V_V_V(SHL);
|
|
||||||
DEFINE_OPCODE_V_V_V(VECTOR_SHL);
|
|
||||||
DEFINE_OPCODE_V_V_V(SHR);
|
|
||||||
DEFINE_OPCODE_V_V_V(SHA);
|
|
||||||
DEFINE_OPCODE_V_V_V(ROTATE_LEFT);
|
|
||||||
DEFINE_OPCODE_V_V(BYTE_SWAP);
|
|
||||||
DEFINE_OPCODE_V_V(CNTLZ);
|
|
||||||
DEFINE_OPCODE_V_V_V_V(INSERT);
|
|
||||||
DEFINE_OPCODE_V_V_V(EXTRACT);
|
|
||||||
DEFINE_OPCODE_V_V(SPLAT);
|
|
||||||
DEFINE_OPCODE_V_V_V_V(PERMUTE);
|
|
||||||
DEFINE_OPCODE_V_V_O(SWIZZLE);
|
|
||||||
|
|
||||||
DEFINE_OPCODE_V_V_V_V(COMPARE_EXCHANGE);
|
|
||||||
DEFINE_OPCODE_V_V_V(ATOMIC_ADD);
|
|
||||||
DEFINE_OPCODE_V_V_V(ATOMIC_SUB);
|
|
|
@ -1,16 +0,0 @@
|
||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
|
||||||
******************************************************************************
|
|
||||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
DEFINE_LIR_OPCODE_R32_R32(MOV_I32);
|
|
||||||
DEFINE_LIR_OPCODE_R32_R32(XOR_I32);
|
|
||||||
DEFINE_LIR_OPCODE_R32(DEC_I32);
|
|
||||||
DEFINE_LIR_OPCODE_R32_R32(SUB_I32);
|
|
||||||
DEFINE_LIR_OPCODE_R32_R32(IMUL_I32);
|
|
||||||
DEFINE_LIR_OPCODE_R32_R32_C32(IMUL_I32_AUX);
|
|
||||||
DEFINE_LIR_OPCODE_R32(DIV_I32);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,11 +23,11 @@ LoweringTable::LoweringTable(X64Backend* backend) :
|
||||||
|
|
||||||
LoweringTable::~LoweringTable() {
|
LoweringTable::~LoweringTable() {
|
||||||
for (size_t n = 0; n < XECOUNT(lookup_); n++) {
|
for (size_t n = 0; n < XECOUNT(lookup_); n++) {
|
||||||
auto fn = lookup_[n];
|
auto entry = lookup_[n];
|
||||||
while (fn) {
|
while (entry) {
|
||||||
auto next = fn->next;
|
auto next = entry->next;
|
||||||
delete fn;
|
delete entry;
|
||||||
fn = next;
|
entry = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,12 @@ int LoweringTable::Initialize() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoweringTable::AddSequence(hir::Opcode starting_opcode, FnWrapper* fn) {
|
void LoweringTable::AddSequence(hir::Opcode starting_opcode, sequence_fn_t fn) {
|
||||||
auto existing_fn = lookup_[starting_opcode];
|
auto existing_entry = lookup_[starting_opcode];
|
||||||
fn->next = existing_fn;
|
auto new_entry = new sequence_fn_entry_t();
|
||||||
lookup_[starting_opcode] = fn;
|
new_entry->fn = fn;
|
||||||
|
new_entry->next = existing_entry;
|
||||||
|
lookup_[starting_opcode] = new_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LoweringTable::Process(
|
int LoweringTable::Process(
|
||||||
|
@ -78,13 +80,13 @@ int LoweringTable::Process(
|
||||||
auto hir_instr = hir_block->instr_head;
|
auto hir_instr = hir_block->instr_head;
|
||||||
while (hir_instr) {
|
while (hir_instr) {
|
||||||
bool processed = false;
|
bool processed = false;
|
||||||
auto fn = lookup_[hir_instr->opcode->num];
|
auto entry = lookup_[hir_instr->opcode->num];
|
||||||
while (fn) {
|
while (entry) {
|
||||||
if ((*fn)(lir_builder, hir_instr)) {
|
if ((*entry->fn)(*lir_builder, hir_instr)) {
|
||||||
processed = true;
|
processed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fn = fn->next;
|
entry = entry->next;
|
||||||
}
|
}
|
||||||
if (!processed) {
|
if (!processed) {
|
||||||
// No sequence found!
|
// No sequence found!
|
||||||
|
|
|
@ -33,28 +33,18 @@ public:
|
||||||
int Process(hir::HIRBuilder* hir_builder, lir::LIRBuilder* lir_builder);
|
int Process(hir::HIRBuilder* hir_builder, lir::LIRBuilder* lir_builder);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class FnWrapper {
|
typedef bool(*sequence_fn_t)(lir::LIRBuilder& lb, hir::Instr*& instr);
|
||||||
public:
|
void AddSequence(hir::Opcode starting_opcode, sequence_fn_t fn);
|
||||||
FnWrapper() : next(0) {}
|
|
||||||
virtual bool operator()(lir::LIRBuilder* builder, hir::Instr*& instr) const = 0;
|
|
||||||
FnWrapper* next;
|
|
||||||
};
|
|
||||||
template<typename T>
|
|
||||||
class TypedFnWrapper : public FnWrapper {
|
|
||||||
public:
|
|
||||||
TypedFnWrapper(T fn) : fn_(fn) {}
|
|
||||||
virtual bool operator()(lir::LIRBuilder* builder, hir::Instr*& instr) const {
|
|
||||||
return fn_(builder, instr);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
T fn_;
|
|
||||||
};
|
|
||||||
|
|
||||||
void AddSequence(hir::Opcode starting_opcode, FnWrapper* fn);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class sequence_fn_entry_t {
|
||||||
|
public:
|
||||||
|
sequence_fn_t fn;
|
||||||
|
sequence_fn_entry_t* next;
|
||||||
|
};
|
||||||
|
|
||||||
X64Backend* backend_;
|
X64Backend* backend_;
|
||||||
FnWrapper* lookup_[hir::__OPCODE_MAX_VALUE];
|
sequence_fn_entry_t* lookup_[hir::__OPCODE_MAX_VALUE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||||
{
|
{
|
||||||
'sources': [
|
'sources': [
|
||||||
'lowering_hir_opcodes.inl',
|
|
||||||
'lowering_lir_opcodes.inl',
|
|
||||||
'lowering_sequences.cc',
|
'lowering_sequences.cc',
|
||||||
'lowering_sequences.h',
|
'lowering_sequences.h',
|
||||||
'lowering_table.cc',
|
'lowering_table.cc',
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <alloy/backend/x64/tracing.h>
|
#include <alloy/backend/x64/tracing.h>
|
||||||
#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_function.h>
|
#include <alloy/backend/x64/x64_function.h>
|
||||||
#include <alloy/backend/x64/lir/lir_builder.h>
|
#include <alloy/backend/x64/lir/lir_builder.h>
|
||||||
#include <alloy/backend/x64/lowering/lowering_table.h>
|
#include <alloy/backend/x64/lowering/lowering_table.h>
|
||||||
|
@ -20,6 +21,10 @@
|
||||||
#include <alloy/hir/label.h>
|
#include <alloy/hir/label.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
|
namespace BE {
|
||||||
|
#include <beaengine/BeaEngine.h>
|
||||||
|
}
|
||||||
|
|
||||||
using namespace alloy;
|
using namespace alloy;
|
||||||
using namespace alloy::backend;
|
using namespace alloy::backend;
|
||||||
using namespace alloy::backend::x64;
|
using namespace alloy::backend::x64;
|
||||||
|
@ -31,8 +36,9 @@ using namespace alloy::runtime;
|
||||||
|
|
||||||
X64Assembler::X64Assembler(X64Backend* backend) :
|
X64Assembler::X64Assembler(X64Backend* backend) :
|
||||||
x64_backend_(backend),
|
x64_backend_(backend),
|
||||||
optimizer_(0),
|
|
||||||
builder_(0),
|
builder_(0),
|
||||||
|
optimizer_(0),
|
||||||
|
emitter_(0),
|
||||||
Assembler(backend) {
|
Assembler(backend) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +46,7 @@ X64Assembler::~X64Assembler() {
|
||||||
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({
|
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
delete emitter_;
|
||||||
delete optimizer_;
|
delete optimizer_;
|
||||||
delete builder_;
|
delete builder_;
|
||||||
}
|
}
|
||||||
|
@ -50,10 +57,12 @@ int X64Assembler::Initialize() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder_ = new LIRBuilder(x64_backend_);
|
||||||
|
|
||||||
optimizer_ = new Optimizer(backend_->runtime());
|
optimizer_ = new Optimizer(backend_->runtime());
|
||||||
optimizer_->AddPass(new passes::RedundantMovPass());
|
optimizer_->AddPass(new passes::RedundantMovPass());
|
||||||
|
|
||||||
builder_ = new LIRBuilder(x64_backend_);
|
emitter_ = new X64Emitter(x64_backend_);
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::AssemblerInit({
|
alloy::tracing::WriteEvent(EventType::AssemblerInit({
|
||||||
}));
|
}));
|
||||||
|
@ -64,6 +73,7 @@ int X64Assembler::Initialize() {
|
||||||
void X64Assembler::Reset() {
|
void X64Assembler::Reset() {
|
||||||
builder_->Reset();
|
builder_->Reset();
|
||||||
optimizer_->Reset();
|
optimizer_->Reset();
|
||||||
|
emitter_->Reset();
|
||||||
string_buffer_.Reset();
|
string_buffer_.Reset();
|
||||||
Assembler::Reset();
|
Assembler::Reset();
|
||||||
}
|
}
|
||||||
|
@ -103,7 +113,7 @@ int X64Assembler::Assemble(
|
||||||
|
|
||||||
// Stash generated machine code.
|
// Stash generated machine code.
|
||||||
if (debug_info) {
|
if (debug_info) {
|
||||||
//emitter_->Dump(&string_buffer_);
|
DumpMachineCode(&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();
|
||||||
}
|
}
|
||||||
|
@ -121,3 +131,20 @@ XECLEANUP:
|
||||||
Reset();
|
Reset();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void X64Assembler::DumpMachineCode(StringBuffer* str) {
|
||||||
|
BE::DISASM disasm;
|
||||||
|
xe_zero_struct(&disasm, sizeof(disasm));
|
||||||
|
disasm.Archi = 64;
|
||||||
|
disasm.Options = BE::Tabulation + BE::MasmSyntax + BE::PrefixedNumeral;
|
||||||
|
disasm.EIP = 0;// (BE::UIntPtr)assembler_.getCode();
|
||||||
|
BE::UIntPtr eip_end = 0;// assembler_.getCode() + assembler_.getCodeSize();
|
||||||
|
while (disasm.EIP < eip_end) {
|
||||||
|
size_t len = BE::Disasm(&disasm);
|
||||||
|
if (len == BE::UNKNOWN_OPCODE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
str->Append("%p %s", disasm.EIP, disasm.CompleteInstr);
|
||||||
|
disasm.EIP += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
class X64Backend;
|
class X64Backend;
|
||||||
|
class X64Emitter;
|
||||||
namespace lir { class LIRBuilder; }
|
namespace lir { class LIRBuilder; }
|
||||||
namespace optimizer { class Optimizer; }
|
namespace optimizer { class Optimizer; }
|
||||||
|
|
||||||
|
@ -37,10 +38,14 @@ public:
|
||||||
runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
||||||
runtime::DebugInfo* debug_info, runtime::Function** out_function);
|
runtime::DebugInfo* debug_info, runtime::Function** out_function);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DumpMachineCode(StringBuffer* str);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
X64Backend* x64_backend_;
|
X64Backend* x64_backend_;
|
||||||
lir::LIRBuilder* builder_;
|
lir::LIRBuilder* builder_;
|
||||||
optimizer::Optimizer* optimizer_;
|
optimizer::Optimizer* optimizer_;
|
||||||
|
X64Emitter* emitter_;
|
||||||
|
|
||||||
StringBuffer string_buffer_;
|
StringBuffer string_buffer_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <alloy/backend/x64/tracing.h>
|
#include <alloy/backend/x64/tracing.h>
|
||||||
#include <alloy/backend/x64/x64_assembler.h>
|
#include <alloy/backend/x64/x64_assembler.h>
|
||||||
#include <alloy/backend/x64/lowering/lowering_table.h>
|
#include <alloy/backend/x64/lowering/lowering_table.h>
|
||||||
|
#include <alloy/backend/x64/lowering/lowering_sequences.h>
|
||||||
|
|
||||||
using namespace alloy;
|
using namespace alloy;
|
||||||
using namespace alloy::backend;
|
using namespace alloy::backend;
|
||||||
|
@ -38,6 +39,7 @@ int X64Backend::Initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
lowering_table_ = new LoweringTable(this);
|
lowering_table_ = new LoweringTable(this);
|
||||||
|
RegisterSequences(lowering_table_);
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::Init({
|
alloy::tracing::WriteEvent(EventType::Init({
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -29,8 +29,6 @@ public:
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
X64Backend* backend_;
|
X64Backend* backend_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -162,7 +162,7 @@ void HIRBuilder::Dump(StringBuffer* str) {
|
||||||
i = i->next;
|
i = i->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (i->opcode->num == OPCODE_COMMENT) {
|
if (i->opcode == &OPCODE_COMMENT_info) {
|
||||||
str->Append(" ; %s\n", (char*)i->src1.offset);
|
str->Append(" ; %s\n", (char*)i->src1.offset);
|
||||||
i = i->next;
|
i = i->next;
|
||||||
continue;
|
continue;
|
||||||
|
@ -222,6 +222,7 @@ Label* HIRBuilder::NewLabel() {
|
||||||
label->block = NULL;
|
label->block = NULL;
|
||||||
label->id = next_label_id_++;
|
label->id = next_label_id_++;
|
||||||
label->name = NULL;
|
label->name = NULL;
|
||||||
|
label->tag = NULL;
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,6 @@ enum Swizzles {
|
||||||
|
|
||||||
enum Opcode {
|
enum Opcode {
|
||||||
OPCODE_COMMENT,
|
OPCODE_COMMENT,
|
||||||
|
|
||||||
OPCODE_NOP,
|
OPCODE_NOP,
|
||||||
|
|
||||||
OPCODE_SOURCE_OFFSET,
|
OPCODE_SOURCE_OFFSET,
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <third_party/jansson/src/jansson.h>
|
#include <jansson.h>
|
||||||
|
|
||||||
#include <xenia/emulator.h>
|
#include <xenia/emulator.h>
|
||||||
#include <xenia/debug/debug_server.h>
|
#include <xenia/debug/debug_server.h>
|
||||||
|
|
|
@ -16,11 +16,15 @@
|
||||||
|
|
||||||
'sources': [
|
'sources': [
|
||||||
'beaengine/beaengineSources/BeaEngine.c',
|
'beaengine/beaengineSources/BeaEngine.c',
|
||||||
|
'beaengine/include/beaengine/basic_types.h',
|
||||||
|
'beaengine/include/beaengine/BeaEngine.h',
|
||||||
|
'beaengine/include/beaengine/export.h',
|
||||||
|
'beaengine/include/beaengine/macros.h',
|
||||||
],
|
],
|
||||||
|
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
'beaengine/include/',
|
|
||||||
'beaengine/beaengineSources/',
|
'beaengine/beaengineSources/',
|
||||||
|
'beaengine/include/',
|
||||||
],
|
],
|
||||||
|
|
||||||
'defines': [
|
'defines': [
|
||||||
|
|
|
@ -185,9 +185,11 @@
|
||||||
'type': 'static_library',
|
'type': 'static_library',
|
||||||
|
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
|
'beaengine',
|
||||||
'gflags',
|
'gflags',
|
||||||
],
|
],
|
||||||
'export_dependent_settings': [
|
'export_dependent_settings': [
|
||||||
|
'beaengine',
|
||||||
'gflags',
|
'gflags',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -246,14 +248,12 @@
|
||||||
'type': 'static_library',
|
'type': 'static_library',
|
||||||
|
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'beaengine',
|
|
||||||
'gflags',
|
'gflags',
|
||||||
'jansson',
|
'jansson',
|
||||||
'wslay',
|
'wslay',
|
||||||
'alloy',
|
'alloy',
|
||||||
],
|
],
|
||||||
'export_dependent_settings': [
|
'export_dependent_settings': [
|
||||||
'beaengine',
|
|
||||||
'gflags',
|
'gflags',
|
||||||
'jansson',
|
'jansson',
|
||||||
'wslay',
|
'wslay',
|
||||||
|
|
Loading…
Reference in New Issue