Wiring up the LIR flow.
This commit is contained in:
parent
dec0e35957
commit
63f11732a5
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <alloy/backend/x64/lir/lir_builder.h>
|
||||||
|
|
||||||
|
using namespace alloy;
|
||||||
|
using namespace alloy::backend::x64;
|
||||||
|
using namespace alloy::backend::x64::lir;
|
||||||
|
|
||||||
|
|
||||||
|
LIRBuilder::LIRBuilder(X64Backend* backend) :
|
||||||
|
backend_(backend) {
|
||||||
|
}
|
||||||
|
|
||||||
|
LIRBuilder::~LIRBuilder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Reset() {
|
||||||
|
}
|
||||||
|
|
||||||
|
int LIRBuilder::Finalize() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIRBuilder::Dump(StringBuffer* str) {
|
||||||
|
}
|
|
@ -17,23 +17,25 @@
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
class X64Backend;
|
||||||
namespace lir {
|
namespace lir {
|
||||||
|
|
||||||
|
|
||||||
class LIRBuilder {
|
class LIRBuilder {
|
||||||
public:
|
public:
|
||||||
LIRBuilder();
|
LIRBuilder(X64Backend* backend);
|
||||||
virtual ~LIRBuilder();
|
~LIRBuilder();
|
||||||
|
|
||||||
virtual void Reset();
|
void Reset();
|
||||||
virtual int Finalize();
|
int Finalize();
|
||||||
|
|
||||||
void Dump(StringBuffer* str);
|
void Dump(StringBuffer* str);
|
||||||
|
|
||||||
Arena* arena() const { return arena_; }
|
Arena* arena() const { return arena_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Arena* arena_;
|
X64Backend* backend_;
|
||||||
|
Arena* arena_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,12 @@ namespace lir {
|
||||||
|
|
||||||
enum LIROpcode {
|
enum LIROpcode {
|
||||||
LIR_OPCODE_MOV_I32,
|
LIR_OPCODE_MOV_I32,
|
||||||
|
LIR_OPCODE_XOR_I32,
|
||||||
|
LIR_OPCODE_DEC_I32,
|
||||||
|
LIR_OPCODE_SUB_I32,
|
||||||
|
LIR_OPCODE_IMUL_I32,
|
||||||
|
LIR_OPCODE_IMUL_I32_AUX,
|
||||||
|
LIR_OPCODE_DIV_I32,
|
||||||
|
|
||||||
__LIR_OPCODE_MAX_VALUE, // Keep at end.
|
__LIR_OPCODE_MAX_VALUE, // Keep at end.
|
||||||
};
|
};
|
||||||
|
@ -41,6 +47,9 @@ enum LIROpcodeSignatureType {
|
||||||
|
|
||||||
enum LIROpcodeSignature {
|
enum LIROpcodeSignature {
|
||||||
LIR_OPCODE_SIG_X = (LIR_OPCODE_SIG_TYPE_X),
|
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_DEST(sig) (LIROpcodeSignatureType)(sig & 0x7)
|
||||||
|
|
|
@ -7,9 +7,38 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DEFINE_OPCODE(
|
||||||
DEFINE_OPCODE(
|
LIR_OPCODE_MOV_I32,
|
||||||
LIR_OPCODE_MOV_I32,
|
"mov.i32",
|
||||||
"mov.i32",
|
LIR_OPCODE_SIG_R32_R32,
|
||||||
LIR_OPCODE_SIG_X,
|
0);
|
||||||
0);
|
DEFINE_OPCODE(
|
||||||
|
LIR_OPCODE_XOR_I32,
|
||||||
|
"xor.i32",
|
||||||
|
LIR_OPCODE_SIG_R32_R32,
|
||||||
|
0);
|
||||||
|
DEFINE_OPCODE(
|
||||||
|
LIR_OPCODE_DEC_I32,
|
||||||
|
"dec.i32",
|
||||||
|
LIR_OPCODE_SIG_R32,
|
||||||
|
0);
|
||||||
|
DEFINE_OPCODE(
|
||||||
|
LIR_OPCODE_SUB_I32,
|
||||||
|
"sub.i32",
|
||||||
|
LIR_OPCODE_SIG_R32_R32,
|
||||||
|
0);
|
||||||
|
DEFINE_OPCODE(
|
||||||
|
LIR_OPCODE_IMUL_I32,
|
||||||
|
"imul.i32",
|
||||||
|
LIR_OPCODE_SIG_R32_R32,
|
||||||
|
0);
|
||||||
|
DEFINE_OPCODE(
|
||||||
|
LIR_OPCODE_IMUL_I32_AUX,
|
||||||
|
"imul.i32.aux",
|
||||||
|
LIR_OPCODE_SIG_R32_R32_C32,
|
||||||
|
0);
|
||||||
|
DEFINE_OPCODE(
|
||||||
|
LIR_OPCODE_DIV_I32,
|
||||||
|
"div.i32",
|
||||||
|
LIR_OPCODE_SIG_R32,
|
||||||
|
0);
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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);
|
|
@ -7,26 +7,10 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <alloy/backend/x64/x64_codegen.h>
|
DEFINE_LIR_OPCODE_R32_R32(MOV_I32);
|
||||||
|
DEFINE_LIR_OPCODE_R32_R32(XOR_I32);
|
||||||
#include <alloy/backend/x64/x64_backend.h>
|
DEFINE_LIR_OPCODE_R32(DEC_I32);
|
||||||
|
DEFINE_LIR_OPCODE_R32_R32(SUB_I32);
|
||||||
using namespace alloy;
|
DEFINE_LIR_OPCODE_R32_R32(IMUL_I32);
|
||||||
using namespace alloy::backend;
|
DEFINE_LIR_OPCODE_R32_R32_C32(IMUL_I32_AUX);
|
||||||
using namespace alloy::backend::x64;
|
DEFINE_LIR_OPCODE_R32(DIV_I32);
|
||||||
using namespace alloy::runtime;
|
|
||||||
|
|
||||||
|
|
||||||
X64Codegen::X64Codegen(X64Backend* backend) :
|
|
||||||
backend_(backend) {
|
|
||||||
}
|
|
||||||
|
|
||||||
X64Codegen::~X64Codegen() {
|
|
||||||
}
|
|
||||||
|
|
||||||
int X64Codegen::Initialize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void X64Codegen::Reset() {
|
|
||||||
}
|
|
|
@ -0,0 +1,487 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <alloy/backend/x64/lowering/lowering_sequences.h>
|
||||||
|
|
||||||
|
#include <alloy/backend/x64/lowering/lowering_table.h>
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
using namespace alloy;
|
||||||
|
using namespace alloy::backend::x64;
|
||||||
|
using namespace alloy::backend::x64::lir;
|
||||||
|
using namespace alloy::backend::x64::lowering;
|
||||||
|
using namespace alloy::hir;
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
|
enum ArgType {
|
||||||
|
NULL_ARG_TYPE,
|
||||||
|
VALUE_ARG_TYPE,
|
||||||
|
CONSTANT_ARG_TYPE,
|
||||||
|
OUT_ARG_TYPE,
|
||||||
|
IN_ARG_TYPE,
|
||||||
|
REG_ARG_TYPE,
|
||||||
|
};
|
||||||
|
template<ArgType ARG_TYPE>
|
||||||
|
class Arg {
|
||||||
|
public:
|
||||||
|
const static ArgType arg_type = ARG_TYPE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NullArg : public Arg<NULL_ARG_TYPE> {};
|
||||||
|
|
||||||
|
template<int TYPE>
|
||||||
|
class ValueRef : public Arg<VALUE_ARG_TYPE> {
|
||||||
|
public:
|
||||||
|
enum { type = TYPE };
|
||||||
|
};
|
||||||
|
template<int TYPE, bool HAS_VALUE = false,
|
||||||
|
int8_t INT8_VALUE = 0,
|
||||||
|
int16_t INT16_VALUE = 0,
|
||||||
|
int32_t INT32_VALUE = 0,
|
||||||
|
int64_t INT64_VALUE = 0,
|
||||||
|
intmax_t FLOAT32_NUM_VALUE = 0,
|
||||||
|
intmax_t FLOAT32_DEN_VALUE = 1,
|
||||||
|
intmax_t FLOAT64_NUM_VALUE = 0,
|
||||||
|
intmax_t FLOAT64_DEN_VALUE = 1>
|
||||||
|
// vec
|
||||||
|
class Constant : public Arg<CONSTANT_ARG_TYPE> {
|
||||||
|
public:
|
||||||
|
enum { type = TYPE };
|
||||||
|
enum : bool { has_value = HAS_VALUE };
|
||||||
|
const static int8_t i8 = INT8_VALUE;
|
||||||
|
const static int16_t i16 = INT16_VALUE;
|
||||||
|
const static int32_t i32 = INT32_VALUE;
|
||||||
|
const static int64_t i64 = INT64_VALUE;
|
||||||
|
const static intmax_t f32_num = FLOAT32_NUM_VALUE;
|
||||||
|
const static intmax_t f32_den = FLOAT32_DEN_VALUE;
|
||||||
|
const static intmax_t f64_num = FLOAT64_NUM_VALUE;
|
||||||
|
const static intmax_t f64_den = FLOAT64_DEN_VALUE;
|
||||||
|
// vec
|
||||||
|
};
|
||||||
|
template<int8_t VALUE>
|
||||||
|
class Int8Constant : public Constant<INT8_TYPE, true, VALUE> {};
|
||||||
|
template<int16_t VALUE>
|
||||||
|
class Int16Constant : public Constant<INT16_TYPE, true, 0, VALUE> {};
|
||||||
|
template<int32_t VALUE>
|
||||||
|
class Int32Constant : public Constant<INT32_TYPE, true, 0, 0, VALUE> {};
|
||||||
|
template<int64_t VALUE>
|
||||||
|
class Int64Constant : public Constant<INT64_TYPE, true, 0, 0, 0, VALUE> {};
|
||||||
|
template<intmax_t NUM, intmax_t DEN>
|
||||||
|
class Float32Constant : public Constant<FLOAT32_TYPE, true, 0, 0, 0, 0, NUM, DEN> {};
|
||||||
|
template<intmax_t NUM, intmax_t DEN>
|
||||||
|
class Float64Constant : public Constant<FLOAT64_TYPE, true, 0, 0, 0, 0, 0, 0, NUM, DEN> {};
|
||||||
|
// vec
|
||||||
|
|
||||||
|
template<int SLOT>
|
||||||
|
class Out : public Arg<OUT_ARG_TYPE> {
|
||||||
|
public:
|
||||||
|
enum { slot = SLOT };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<int SLOT, int ARG>
|
||||||
|
class In : public Arg<IN_ARG_TYPE> {
|
||||||
|
public:
|
||||||
|
enum { slot = SLOT };
|
||||||
|
enum { arg = ARG };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<int REG_NAME>
|
||||||
|
class Reg : public Arg<REG_ARG_TYPE> {
|
||||||
|
public:
|
||||||
|
enum { reg_name = REG_NAME };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Matcher {
|
||||||
|
public:
|
||||||
|
template <int v> struct IntType { static const int value = v; };
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType<NULL_ARG_TYPE>) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType<VALUE_ARG_TYPE>) {
|
||||||
|
return op.value->type == T::type;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType<CONSTANT_ARG_TYPE>) {
|
||||||
|
if (op.value->type != T::type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!T::has_value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
switch (T::type) {
|
||||||
|
case INT8_TYPE:
|
||||||
|
return op.value->constant.i8 == T::i8;
|
||||||
|
case INT16_TYPE:
|
||||||
|
return op.value->constant.i16 == T::i16;
|
||||||
|
case INT32_TYPE:
|
||||||
|
return op.value->constant.i32 == T::i32;
|
||||||
|
case INT64_TYPE:
|
||||||
|
return op.value->constant.i64 == T::i64;
|
||||||
|
case FLOAT32_TYPE:
|
||||||
|
return op.value->constant.f32 == (T::f32_num / T::f32_den);
|
||||||
|
case FLOAT64_TYPE:
|
||||||
|
return op.value->constant.f64 == (T::f64_num / T::f64_den);
|
||||||
|
// vec
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType<OUT_ARG_TYPE>) {
|
||||||
|
Instr* instr = instr_list[T::slot];
|
||||||
|
return op.value == instr->dest;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType<IN_ARG_TYPE>) {
|
||||||
|
Instr* instr = instr_list[T::slot];
|
||||||
|
switch (T::arg) {
|
||||||
|
case 0:
|
||||||
|
return op.value == instr->src1.value;
|
||||||
|
case 1:
|
||||||
|
return op.value == instr->src2.value;
|
||||||
|
case 2:
|
||||||
|
return op.value == instr->src3.value;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static bool CheckDest(Instr* instr_list[], Value* value, IntType<NULL_ARG_TYPE>) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
static bool CheckDest(Instr* instr_list[], Value* value, IntType<VALUE_ARG_TYPE>) {
|
||||||
|
return value->type == T::type;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
static bool CheckDest(Instr* instr_list[], Value* value, IntType<OUT_ARG_TYPE>) {
|
||||||
|
Instr* instr = instr_list[T::slot];
|
||||||
|
return value == instr->dest;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
static bool CheckDest(Instr* instr_list[], Value* value, IntType<IN_ARG_TYPE>) {
|
||||||
|
Instr* instr = instr_list[T::slot];
|
||||||
|
switch (T::arg) {
|
||||||
|
case 0:
|
||||||
|
return value == instr->src1.value;
|
||||||
|
case 1:
|
||||||
|
return value == instr->src2.value;
|
||||||
|
case 2:
|
||||||
|
return value == instr->src3.value;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t I = 0, typename HIRS>
|
||||||
|
static typename std::enable_if<I == std::tuple_size<HIRS>::value, void>::type
|
||||||
|
Match(Instr* instr_list[], int& instr_offset, Instr*&, bool&) {
|
||||||
|
}
|
||||||
|
template <size_t I = 0, typename HIRS>
|
||||||
|
static typename std::enable_if<I < std::tuple_size<HIRS>::value, void>::type
|
||||||
|
Match(Instr* instr_list[], int& instr_offset, Instr*& instr, bool& matched) {
|
||||||
|
instr_list[instr_offset++] = instr;
|
||||||
|
typedef std::tuple_element<I, HIRS>::type T;
|
||||||
|
if (instr->opcode->num != T::opcode) {
|
||||||
|
matched = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Matches opcode, check args.
|
||||||
|
if (!std::is_same<T::dest, NullArg>::value) {
|
||||||
|
if (!CheckDest<T::dest>(instr_list, instr->dest, IntType<T::dest::arg_type>())) {
|
||||||
|
matched = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!std::is_same<T::arg0, NullArg>::value) {
|
||||||
|
if (!CheckArg<T::arg0>(instr_list, instr->src1, IntType<T::arg0::arg_type>())) {
|
||||||
|
matched = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!std::is_same<T::arg1, NullArg>::value) {
|
||||||
|
if (!CheckArg<T::arg1>(instr_list, instr->src2, IntType<T::arg1::arg_type>())) {
|
||||||
|
matched = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!std::is_same<T::arg2, NullArg>::value) {
|
||||||
|
if (!CheckArg<T::arg2>(instr_list, instr->src3, IntType<T::arg2::arg_type>())) {
|
||||||
|
matched = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instr = instr->next;
|
||||||
|
Match<I + 1, HIRS>(instr_list, instr_offset, instr, matched);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename HIRS>
|
||||||
|
static bool Matches(Instr* instr_list[], int& instr_offset, Instr*& instr) {
|
||||||
|
bool matched = true;
|
||||||
|
Instr* orig_instr = instr;
|
||||||
|
Match<0, HIRS>(instr_list, instr_offset, instr, matched);
|
||||||
|
if (!matched) {
|
||||||
|
instr = orig_instr;
|
||||||
|
}
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Emitter {
|
||||||
|
public:
|
||||||
|
template <size_t I = 0, typename LIRS>
|
||||||
|
static typename std::enable_if<I == std::tuple_size<LIRS>::value, void>::type
|
||||||
|
EmitInstr(LIRBuilder* builder, Instr*[]) {
|
||||||
|
}
|
||||||
|
template <size_t I = 0, typename LIRS>
|
||||||
|
static typename std::enable_if<I < std::tuple_size<LIRS>::value, void>::type
|
||||||
|
EmitInstr(LIRBuilder* builder, Instr* instr_list[]) {
|
||||||
|
typedef std::tuple_element<I, LIRS>::type T;
|
||||||
|
//LIRInstr* lir_instr = builder->AppendInstr(T::opcode);
|
||||||
|
if (!std::is_same<T::dest, NullArg>::value) {
|
||||||
|
// lir_instr->dest = ...
|
||||||
|
}
|
||||||
|
if (!std::is_same<T::arg0, NullArg>::value) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
if (!std::is_same<T::arg1, NullArg>::value) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
if (!std::is_same<T::arg2, NullArg>::value) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
EmitInstr<I + 1, LIRS>(builder, instr_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename LIRS>
|
||||||
|
static void Emit(LIRBuilder* builder, Instr* instr_list[]) {
|
||||||
|
EmitInstr<0, LIRS>(builder, instr_list);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename MATCH, typename EMIT>
|
||||||
|
void Translate(LoweringTable* table) {
|
||||||
|
auto exec = [](LIRBuilder* builder, Instr*& instr) {
|
||||||
|
Instr* instr_list[32] = { 0 };
|
||||||
|
int instr_offset = 0;
|
||||||
|
if (Matcher::Matches<MATCH>(instr_list, instr_offset, instr)) {
|
||||||
|
Emitter::Emit<EMIT>(builder, instr_list);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
auto new_fn = new LoweringTable::TypedFnWrapper<decltype(exec)>(exec);
|
||||||
|
table->AddSequence(std::tuple_element<0, MATCH>::type::opcode, new_fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template<Opcode OPCODE, OpcodeSignature SIGNATURE, int FLAGS,
|
||||||
|
typename DEST = NullArg, typename ARG0 = NullArg, typename ARG1 = NullArg, typename ARG2 = NullArg>
|
||||||
|
class HIR_OPCODE {
|
||||||
|
public:
|
||||||
|
static const Opcode opcode = OPCODE;
|
||||||
|
static const OpcodeSignature signature = SIGNATURE;
|
||||||
|
static const int flags = FLAGS;
|
||||||
|
|
||||||
|
typedef DEST dest;
|
||||||
|
typedef ARG0 arg0;
|
||||||
|
typedef ARG1 arg1;
|
||||||
|
typedef ARG2 arg2;
|
||||||
|
};
|
||||||
|
#define DEFINE_OPCODE(num, name, sig, flags) \
|
||||||
|
template<typename DEST = NullArg, typename ARG0 = NullArg, typename ARG1 = NullArg, typename ARG2 = NullArg> \
|
||||||
|
class BASE_HIR_##num : public HIR_OPCODE<num, sig, flags, DEST, ARG0, ARG1, ARG2>{};
|
||||||
|
#include <alloy/hir/opcodes.inl>
|
||||||
|
#undef DEFINE_OPCODE
|
||||||
|
#define DEFINE_OPCODE_V_O(name) \
|
||||||
|
template<typename DEST, typename ARG0> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<DEST, ARG0> {}
|
||||||
|
#define DEFINE_OPCODE_V_O_V(name) \
|
||||||
|
template<typename DEST, typename ARG0, typename ARG1> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<DEST, ARG0, ARG1> {}
|
||||||
|
#define DEFINE_OPCODE_V_V(name) \
|
||||||
|
template<typename DEST, typename ARG0> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<DEST, ARG0> {}
|
||||||
|
#define DEFINE_OPCODE_V_V_O(name) \
|
||||||
|
template<typename DEST, typename ARG0, typename ARG1> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<DEST, ARG0, ARG1> {}
|
||||||
|
#define DEFINE_OPCODE_V_V_V(name) \
|
||||||
|
template<typename DEST, typename ARG0, typename ARG1> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<DEST, ARG0, ARG1> {}
|
||||||
|
#define DEFINE_OPCODE_V_V_V_V(name) \
|
||||||
|
template<typename DEST, typename ARG0, typename ARG1, typename ARG2> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<DEST, ARG0, ARG1, ARG2> {}
|
||||||
|
#define DEFINE_OPCODE_X(name) \
|
||||||
|
template<int NONE = 0> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<> {}
|
||||||
|
#define DEFINE_OPCODE_X_L(name) \
|
||||||
|
template<typename ARG0> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<NullArg, ARG0> {}
|
||||||
|
#define DEFINE_OPCODE_X_O(name) \
|
||||||
|
template<typename ARG0> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<NullArg, ARG0> {}
|
||||||
|
#define DEFINE_OPCODE_X_S(name) \
|
||||||
|
template<typename ARG0> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<NullArg, ARG0> {}
|
||||||
|
#define DEFINE_OPCODE_X_V(name) \
|
||||||
|
template<typename ARG0> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<NullArg, ARG0> {}
|
||||||
|
#define DEFINE_OPCODE_X_V_L(name) \
|
||||||
|
template<typename ARG0, typename ARG1> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<NullArg, ARG0, ARG1> {}
|
||||||
|
#define DEFINE_OPCODE_X_V_O(name) \
|
||||||
|
template<typename ARG0, typename ARG1> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<NullArg, ARG0, ARG1> {}
|
||||||
|
#define DEFINE_OPCODE_X_V_S(name) \
|
||||||
|
template<typename ARG0, typename ARG1> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<NullArg, ARG0, ARG1> {}
|
||||||
|
#define DEFINE_OPCODE_X_V_V(name) \
|
||||||
|
template<typename ARG0, typename ARG1> \
|
||||||
|
class HIR_##name : public BASE_HIR_OPCODE_##name<NullArg, ARG0, ARG1> {}
|
||||||
|
#include <alloy/backend/x64/lowering/lowering_hir_opcodes.inl>
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template<LIROpcode OPCODE, LIROpcodeSignature SIGNATURE, int FLAGS,
|
||||||
|
typename DEST = NullArg, typename ARG0 = NullArg, typename ARG1 = NullArg, typename ARG2 = NullArg>
|
||||||
|
class LIR_OPCODE {
|
||||||
|
public:
|
||||||
|
static const LIROpcode opcode = OPCODE;
|
||||||
|
static const LIROpcodeSignature signature = SIGNATURE;
|
||||||
|
static const int flags = FLAGS;
|
||||||
|
|
||||||
|
typedef DEST dest;
|
||||||
|
typedef ARG0 arg0;
|
||||||
|
typedef ARG1 arg1;
|
||||||
|
typedef ARG2 arg2;
|
||||||
|
};
|
||||||
|
#define DEFINE_OPCODE(num, name, sig, flags) \
|
||||||
|
template<typename DEST = NullArg, typename ARG0 = NullArg, typename ARG1 = NullArg, typename ARG2 = NullArg> \
|
||||||
|
class BASE_##num : public LIR_OPCODE<num, sig, flags, DEST, ARG0, ARG1, ARG2> {};
|
||||||
|
#include <alloy/backend/x64/lir/lir_opcodes.inl>
|
||||||
|
#undef DEFINE_OPCODE
|
||||||
|
#define DEFINE_LIR_OPCODE_X(name) \
|
||||||
|
template<int NONE = 0> \
|
||||||
|
class LIR_##name : public BASE_LIR_OPCODE_##name<> {}
|
||||||
|
#define DEFINE_LIR_OPCODE_R32(name) \
|
||||||
|
template<typename DEST> \
|
||||||
|
class LIR_##name : public BASE_LIR_OPCODE_##name<DEST> {}
|
||||||
|
#define DEFINE_LIR_OPCODE_R32_R32(name) \
|
||||||
|
template<typename DEST, typename ARG0> \
|
||||||
|
class LIR_##name : public BASE_LIR_OPCODE_##name<DEST, ARG0> {}
|
||||||
|
#define DEFINE_LIR_OPCODE_R32_R32_C32(name) \
|
||||||
|
template<typename DEST, typename ARG0, typename ARG1> \
|
||||||
|
class LIR_##name : public BASE_LIR_OPCODE_##name<DEST, ARG0, ARG1> {}
|
||||||
|
#include <alloy/backend/x64/lowering/lowering_lir_opcodes.inl>
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REG8, REG16, REG32, REG64, REGXMM,
|
||||||
|
|
||||||
|
AL, AX, EAX, RAX,
|
||||||
|
BL, BX, EBX, RBX,
|
||||||
|
CL, CX, ECX, RCX,
|
||||||
|
DL, DX, EDX, RDX,
|
||||||
|
R8B, R8W, R8D, R8,
|
||||||
|
R9B, R9W, R9D, R9,
|
||||||
|
R10B, R10W, R10D, R10,
|
||||||
|
R11B, R11W, R11D, R11,
|
||||||
|
R12B, R12W, R12D, R12,
|
||||||
|
R13B, R13W, R13D, R13,
|
||||||
|
R14B, R14W, R14D, R14,
|
||||||
|
R15B, R15W, R15D, R15,
|
||||||
|
|
||||||
|
SIL, SI, ESI, RSI,
|
||||||
|
DIL, DI, EDI, RDI,
|
||||||
|
|
||||||
|
RBP,
|
||||||
|
RSP,
|
||||||
|
|
||||||
|
XMM0,
|
||||||
|
XMM1,
|
||||||
|
XMM2,
|
||||||
|
XMM3,
|
||||||
|
XMM4,
|
||||||
|
XMM5,
|
||||||
|
XMM6,
|
||||||
|
XMM7,
|
||||||
|
XMM8,
|
||||||
|
XMM9,
|
||||||
|
XMM10,
|
||||||
|
XMM11,
|
||||||
|
XMM12,
|
||||||
|
XMM13,
|
||||||
|
XMM14,
|
||||||
|
XMM15,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
|
||||||
|
Translate<tuple<
|
||||||
|
HIR_NOP<>
|
||||||
|
>, tuple<
|
||||||
|
>> (table);
|
||||||
|
|
||||||
|
Translate<tuple<
|
||||||
|
HIR_SUB<ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>>
|
||||||
|
>, tuple<
|
||||||
|
LIR_MOV_I32<Out<0>, In<0, 0>>,
|
||||||
|
LIR_SUB_I32<Out<0>, In<0, 1>>
|
||||||
|
>> (table);
|
||||||
|
Translate<tuple<
|
||||||
|
HIR_SUB<ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>, Int32Constant<1>>
|
||||||
|
>, tuple<
|
||||||
|
LIR_MOV_I32<Out<0>, In<0, 0>>,
|
||||||
|
LIR_DEC_I32<Out<0>>
|
||||||
|
>> (table);
|
||||||
|
|
||||||
|
Translate<tuple<
|
||||||
|
HIR_MUL<ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>, Constant<INT32_TYPE>>
|
||||||
|
>, tuple<
|
||||||
|
LIR_IMUL_I32_AUX<Out<0>, In<0, 0>, In<0, 1>>
|
||||||
|
>> (table);
|
||||||
|
Translate<tuple<
|
||||||
|
HIR_MUL<ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>>
|
||||||
|
>, tuple<
|
||||||
|
LIR_MOV_I32<Out<0>, In<0, 0>>,
|
||||||
|
LIR_IMUL_I32<Out<0>, In<0, 1>>
|
||||||
|
>> (table);
|
||||||
|
|
||||||
|
Translate<tuple<
|
||||||
|
HIR_DIV<ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>>
|
||||||
|
>, tuple<
|
||||||
|
LIR_MOV_I32<Reg<EAX>, In<0, 0>>,
|
||||||
|
LIR_XOR_I32<Reg<EDX>, Reg<EDX>>,
|
||||||
|
LIR_DIV_I32<In<0, 1>>,
|
||||||
|
LIR_MOV_I32<Out<0>, Reg<EAX>>
|
||||||
|
>> (table);
|
||||||
|
|
||||||
|
//Translate<tuple<
|
||||||
|
// HIR_SUB<ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>, ValueRef<INT32_TYPE>>,
|
||||||
|
// HIR_IS_TRUE<ValueRef<INT8_TYPE>, Out<0>>
|
||||||
|
//>, tuple<
|
||||||
|
// LIR_MOV_I32<Out<0>, In<0, 0>>,
|
||||||
|
// LIR_SUB_I32<Out<0>, In<0, 1>>,
|
||||||
|
// LIR_EFLAGS_NOT_ZF<Out<1>>
|
||||||
|
//>> (table);
|
||||||
|
}
|
|
@ -7,38 +7,27 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ALLOY_BACKEND_X64_X64_CODEGEN_H_
|
#ifndef ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_SEQUENCES_H_
|
||||||
#define ALLOY_BACKEND_X64_X64_CODEGEN_H_
|
#define ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_SEQUENCES_H_
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
#include <alloy/hir/instr.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
namespace lowering {
|
||||||
|
|
||||||
class X64Backend;
|
class LoweringTable;
|
||||||
|
|
||||||
|
void RegisterSequences(LoweringTable* table);
|
||||||
class X64Codegen {
|
|
||||||
public:
|
|
||||||
X64Codegen(X64Backend* backend);
|
|
||||||
~X64Codegen();
|
|
||||||
|
|
||||||
int Initialize();
|
|
||||||
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
private:
|
|
||||||
X64Backend* backend_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace lowering
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
#endif // ALLOY_BACKEND_X64_X64_CODEGEN_H_
|
#endif // ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_SEQUENCES_H_
|
|
@ -0,0 +1,56 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <alloy/backend/x64/lowering/lowering_table.h>
|
||||||
|
|
||||||
|
#include <alloy/backend/x64/lowering/lowering_sequences.h>
|
||||||
|
|
||||||
|
using namespace alloy;
|
||||||
|
using namespace alloy::backend::x64;
|
||||||
|
using namespace alloy::backend::x64::lowering;
|
||||||
|
|
||||||
|
|
||||||
|
LoweringTable::LoweringTable(X64Backend* backend) :
|
||||||
|
backend_(backend) {
|
||||||
|
xe_zero_struct(lookup_, sizeof(lookup_));
|
||||||
|
}
|
||||||
|
|
||||||
|
LoweringTable::~LoweringTable() {
|
||||||
|
for (size_t n = 0; n < XECOUNT(lookup_); n++) {
|
||||||
|
auto fn = lookup_[n];
|
||||||
|
while (fn) {
|
||||||
|
auto next = fn->next;
|
||||||
|
delete fn;
|
||||||
|
fn = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int LoweringTable::Initialize() {
|
||||||
|
RegisterSequences(this);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoweringTable::AddSequence(hir::Opcode starting_opcode, FnWrapper* fn) {
|
||||||
|
auto existing_fn = lookup_[starting_opcode];
|
||||||
|
fn->next = existing_fn;
|
||||||
|
lookup_[starting_opcode] = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LoweringTable::Process(lir::LIRBuilder* builder) {
|
||||||
|
/*LIRInstr* instr = 0;
|
||||||
|
auto fn = lookup_[instr->opcode->num];
|
||||||
|
while (fn) {
|
||||||
|
if ((*fn)(builder, instr)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
fn = fn->next;
|
||||||
|
}*/
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_TABLE_H_
|
||||||
|
#define ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_TABLE_H_
|
||||||
|
|
||||||
|
#include <alloy/core.h>
|
||||||
|
#include <alloy/backend/x64/lir/lir_instr.h>
|
||||||
|
#include <alloy/hir/instr.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace alloy {
|
||||||
|
namespace backend {
|
||||||
|
namespace x64 {
|
||||||
|
class X64Backend;
|
||||||
|
namespace lir { class LIRBuilder; }
|
||||||
|
namespace lowering {
|
||||||
|
|
||||||
|
|
||||||
|
class LoweringTable {
|
||||||
|
public:
|
||||||
|
LoweringTable(X64Backend* backend);
|
||||||
|
~LoweringTable();
|
||||||
|
|
||||||
|
int Initialize();
|
||||||
|
|
||||||
|
int Process(lir::LIRBuilder* builder);
|
||||||
|
|
||||||
|
public:
|
||||||
|
class FnWrapper {
|
||||||
|
public:
|
||||||
|
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:
|
||||||
|
X64Backend* backend_;
|
||||||
|
FnWrapper* lookup_[hir::__OPCODE_MAX_VALUE];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace lowering
|
||||||
|
} // namespace x64
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace alloy
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_TABLE_H_
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||||
|
{
|
||||||
|
'sources': [
|
||||||
|
'lowering_hir_opcodes.inl',
|
||||||
|
'lowering_lir_opcodes.inl',
|
||||||
|
'lowering_sequences.cc',
|
||||||
|
'lowering_sequences.h',
|
||||||
|
'lowering_table.cc',
|
||||||
|
'lowering_table.h',
|
||||||
|
],
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <alloy/backend/x64/optimizer/passes/redundant_mov_pass.h>
|
||||||
|
|
||||||
|
using namespace alloy;
|
||||||
|
using namespace alloy::backend::x64::lir;
|
||||||
|
using namespace alloy::backend::x64::optimizer;
|
||||||
|
using namespace alloy::backend::x64::optimizer::passes;
|
||||||
|
|
||||||
|
|
||||||
|
RedundantMovPass::RedundantMovPass() :
|
||||||
|
OptimizerPass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
RedundantMovPass::~RedundantMovPass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
int RedundantMovPass::Run(LIRBuilder* builder) {
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -6,8 +6,6 @@
|
||||||
'x64_assembler.h',
|
'x64_assembler.h',
|
||||||
'x64_backend.cc',
|
'x64_backend.cc',
|
||||||
'x64_backend.h',
|
'x64_backend.h',
|
||||||
'x64_codegen.cc',
|
|
||||||
'x64_codegen.h',
|
|
||||||
'x64_emitter.cc',
|
'x64_emitter.cc',
|
||||||
'x64_emitter.h',
|
'x64_emitter.h',
|
||||||
'x64_function.cc',
|
'x64_function.cc',
|
||||||
|
@ -16,6 +14,7 @@
|
||||||
|
|
||||||
'includes': [
|
'includes': [
|
||||||
'lir/sources.gypi',
|
'lir/sources.gypi',
|
||||||
|
'lowering/sources.gypi',
|
||||||
'optimizer/sources.gypi',
|
'optimizer/sources.gypi',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
#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_function.h>
|
#include <alloy/backend/x64/x64_function.h>
|
||||||
|
#include <alloy/backend/x64/lir/lir_builder.h>
|
||||||
|
#include <alloy/backend/x64/lowering/lowering_table.h>
|
||||||
|
#include <alloy/backend/x64/optimizer/optimizer.h>
|
||||||
|
#include <alloy/backend/x64/optimizer/optimizer_passes.h>
|
||||||
#include <alloy/hir/hir_builder.h>
|
#include <alloy/hir/hir_builder.h>
|
||||||
#include <alloy/hir/label.h>
|
#include <alloy/hir/label.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
@ -19,17 +23,25 @@
|
||||||
using namespace alloy;
|
using namespace alloy;
|
||||||
using namespace alloy::backend;
|
using namespace alloy::backend;
|
||||||
using namespace alloy::backend::x64;
|
using namespace alloy::backend::x64;
|
||||||
|
using namespace alloy::backend::x64::lir;
|
||||||
|
using namespace alloy::backend::x64::optimizer;
|
||||||
using namespace alloy::hir;
|
using namespace alloy::hir;
|
||||||
using namespace alloy::runtime;
|
using namespace alloy::runtime;
|
||||||
|
|
||||||
|
|
||||||
X64Assembler::X64Assembler(X64Backend* backend) :
|
X64Assembler::X64Assembler(X64Backend* backend) :
|
||||||
|
x64_backend_(backend),
|
||||||
|
optimizer_(0),
|
||||||
|
builder_(0),
|
||||||
Assembler(backend) {
|
Assembler(backend) {
|
||||||
}
|
}
|
||||||
|
|
||||||
X64Assembler::~X64Assembler() {
|
X64Assembler::~X64Assembler() {
|
||||||
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({
|
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
delete optimizer_;
|
||||||
|
delete builder_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Assembler::Initialize() {
|
int X64Assembler::Initialize() {
|
||||||
|
@ -38,6 +50,11 @@ int X64Assembler::Initialize() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optimizer_ = new Optimizer(backend_->runtime());
|
||||||
|
optimizer_->AddPass(new passes::RedundantMovPass());
|
||||||
|
|
||||||
|
builder_ = new LIRBuilder(x64_backend_);
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::AssemblerInit({
|
alloy::tracing::WriteEvent(EventType::AssemblerInit({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -45,15 +62,53 @@ int X64Assembler::Initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Assembler::Reset() {
|
void X64Assembler::Reset() {
|
||||||
|
builder_->Reset();
|
||||||
|
optimizer_->Reset();
|
||||||
|
string_buffer_.Reset();
|
||||||
Assembler::Reset();
|
Assembler::Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Assembler::Assemble(
|
int X64Assembler::Assemble(
|
||||||
FunctionInfo* symbol_info, HIRBuilder* builder,
|
FunctionInfo* symbol_info, HIRBuilder* hir_builder,
|
||||||
DebugInfo* debug_info, Function** out_function) {
|
DebugInfo* debug_info, Function** out_function) {
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
// Lower HIR -> LIR.
|
||||||
|
auto lowering_table = x64_backend_->lowering_table();
|
||||||
|
result = lowering_table->Process(builder_);
|
||||||
|
XEEXPECTZERO(result);
|
||||||
|
|
||||||
|
// Stash raw LIR.
|
||||||
|
if (debug_info) {
|
||||||
|
builder_->Dump(&string_buffer_);
|
||||||
|
debug_info->set_raw_lir_disasm(string_buffer_.ToString());
|
||||||
|
string_buffer_.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize LIR.
|
||||||
|
result = optimizer_->Optimize(builder_);
|
||||||
|
XEEXPECTZERO(result);
|
||||||
|
|
||||||
|
// Stash optimized LIR.
|
||||||
|
if (debug_info) {
|
||||||
|
builder_->Dump(&string_buffer_);
|
||||||
|
debug_info->set_lir_disasm(string_buffer_.ToString());
|
||||||
|
string_buffer_.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit machine code.
|
||||||
|
// TODO(benvanik): machine code.
|
||||||
|
|
||||||
X64Function* fn = new X64Function(symbol_info);
|
X64Function* fn = new X64Function(symbol_info);
|
||||||
fn->set_debug_info(debug_info);
|
fn->set_debug_info(debug_info);
|
||||||
|
|
||||||
|
// TODO(benvanik): set mc
|
||||||
|
|
||||||
*out_function = fn;
|
*out_function = fn;
|
||||||
return 0;
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
XECLEANUP:
|
||||||
|
Reset();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
class X64Backend;
|
class X64Backend;
|
||||||
|
namespace lir { class LIRBuilder; }
|
||||||
|
namespace optimizer { class Optimizer; }
|
||||||
|
|
||||||
|
|
||||||
class X64Assembler : public Assembler {
|
class X64Assembler : public Assembler {
|
||||||
|
@ -36,6 +38,11 @@ public:
|
||||||
runtime::DebugInfo* debug_info, runtime::Function** out_function);
|
runtime::DebugInfo* debug_info, runtime::Function** out_function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
X64Backend* x64_backend_;
|
||||||
|
lir::LIRBuilder* builder_;
|
||||||
|
optimizer::Optimizer* optimizer_;
|
||||||
|
|
||||||
|
StringBuffer string_buffer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,20 +11,24 @@
|
||||||
|
|
||||||
#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>
|
||||||
|
|
||||||
using namespace alloy;
|
using namespace alloy;
|
||||||
using namespace alloy::backend;
|
using namespace alloy::backend;
|
||||||
using namespace alloy::backend::x64;
|
using namespace alloy::backend::x64;
|
||||||
|
using namespace alloy::backend::x64::lowering;
|
||||||
using namespace alloy::runtime;
|
using namespace alloy::runtime;
|
||||||
|
|
||||||
|
|
||||||
X64Backend::X64Backend(Runtime* runtime) :
|
X64Backend::X64Backend(Runtime* runtime) :
|
||||||
|
lowering_table_(0),
|
||||||
Backend(runtime) {
|
Backend(runtime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
X64Backend::~X64Backend() {
|
X64Backend::~X64Backend() {
|
||||||
alloy::tracing::WriteEvent(EventType::Deinit({
|
alloy::tracing::WriteEvent(EventType::Deinit({
|
||||||
}));
|
}));
|
||||||
|
delete lowering_table_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Backend::Initialize() {
|
int X64Backend::Initialize() {
|
||||||
|
@ -33,6 +37,8 @@ int X64Backend::Initialize() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lowering_table_ = new LoweringTable(this);
|
||||||
|
|
||||||
alloy::tracing::WriteEvent(EventType::Init({
|
alloy::tracing::WriteEvent(EventType::Init({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ namespace alloy {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
|
namespace lowering { class LoweringTable; }
|
||||||
|
|
||||||
|
|
||||||
#define ALLOY_HAS_X64_BACKEND 1
|
#define ALLOY_HAS_X64_BACKEND 1
|
||||||
|
|
||||||
|
@ -28,9 +30,14 @@ public:
|
||||||
X64Backend(runtime::Runtime* runtime);
|
X64Backend(runtime::Runtime* runtime);
|
||||||
virtual ~X64Backend();
|
virtual ~X64Backend();
|
||||||
|
|
||||||
|
lowering::LoweringTable* lowering_table() const { return lowering_table_; }
|
||||||
|
|
||||||
virtual int Initialize();
|
virtual int Initialize();
|
||||||
|
|
||||||
virtual Assembler* CreateAssembler();
|
virtual Assembler* CreateAssembler();
|
||||||
|
|
||||||
|
private:
|
||||||
|
lowering::LoweringTable* lowering_table_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ private:
|
||||||
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_;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue