From 63f11732a5d0476317d800472f694d7633e03388 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 29 Dec 2013 22:05:41 -0800 Subject: [PATCH] Wiring up the LIR flow. --- src/alloy/backend/x64/lir/lir_builder.cc | 32 ++ src/alloy/backend/x64/lir/lir_builder.h | 12 +- src/alloy/backend/x64/lir/lir_opcodes.h | 9 + src/alloy/backend/x64/lir/lir_opcodes.inl | 41 +- .../x64/lowering/lowering_hir_opcodes.inl | 112 ++++ .../lowering_lir_opcodes.inl} | 30 +- .../x64/lowering/lowering_sequences.cc | 487 ++++++++++++++++++ .../lowering_sequences.h} | 29 +- .../backend/x64/lowering/lowering_table.cc | 56 ++ .../backend/x64/lowering/lowering_table.h | 67 +++ src/alloy/backend/x64/lowering/sources.gypi | 11 + .../optimizer/passes/redundant_mov_pass.cc | 27 + src/alloy/backend/x64/sources.gypi | 3 +- src/alloy/backend/x64/x64_assembler.cc | 59 ++- src/alloy/backend/x64/x64_assembler.h | 7 + src/alloy/backend/x64/x64_backend.cc | 6 + src/alloy/backend/x64/x64_backend.h | 7 + src/alloy/frontend/ppc/ppc_translator.h | 2 +- 18 files changed, 938 insertions(+), 59 deletions(-) create mode 100644 src/alloy/backend/x64/lowering/lowering_hir_opcodes.inl rename src/alloy/backend/x64/{x64_codegen.cc => lowering/lowering_lir_opcodes.inl} (55%) create mode 100644 src/alloy/backend/x64/lowering/lowering_sequences.cc rename src/alloy/backend/x64/{x64_codegen.h => lowering/lowering_sequences.h} (66%) create mode 100644 src/alloy/backend/x64/lowering/lowering_table.cc create mode 100644 src/alloy/backend/x64/lowering/lowering_table.h create mode 100644 src/alloy/backend/x64/lowering/sources.gypi diff --git a/src/alloy/backend/x64/lir/lir_builder.cc b/src/alloy/backend/x64/lir/lir_builder.cc index e69de29bb..f92b64a37 100644 --- a/src/alloy/backend/x64/lir/lir_builder.cc +++ b/src/alloy/backend/x64/lir/lir_builder.cc @@ -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 + +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) { +} diff --git a/src/alloy/backend/x64/lir/lir_builder.h b/src/alloy/backend/x64/lir/lir_builder.h index bbd9b6c87..46ddbfb35 100644 --- a/src/alloy/backend/x64/lir/lir_builder.h +++ b/src/alloy/backend/x64/lir/lir_builder.h @@ -17,23 +17,25 @@ namespace alloy { namespace backend { namespace x64 { +class X64Backend; namespace lir { class LIRBuilder { public: - LIRBuilder(); - virtual ~LIRBuilder(); + LIRBuilder(X64Backend* backend); + ~LIRBuilder(); - virtual void Reset(); - virtual int Finalize(); + void Reset(); + int Finalize(); void Dump(StringBuffer* str); Arena* arena() const { return arena_; } protected: - Arena* arena_; + X64Backend* backend_; + Arena* arena_; }; diff --git a/src/alloy/backend/x64/lir/lir_opcodes.h b/src/alloy/backend/x64/lir/lir_opcodes.h index 8abb53405..564fc8c29 100644 --- a/src/alloy/backend/x64/lir/lir_opcodes.h +++ b/src/alloy/backend/x64/lir/lir_opcodes.h @@ -21,6 +21,12 @@ namespace lir { enum LIROpcode { 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. }; @@ -41,6 +47,9 @@ enum LIROpcodeSignatureType { 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) diff --git a/src/alloy/backend/x64/lir/lir_opcodes.inl b/src/alloy/backend/x64/lir/lir_opcodes.inl index 5fcb6eaef..fb3544c81 100644 --- a/src/alloy/backend/x64/lir/lir_opcodes.inl +++ b/src/alloy/backend/x64/lir/lir_opcodes.inl @@ -7,9 +7,38 @@ ****************************************************************************** */ - - DEFINE_OPCODE( - LIR_OPCODE_MOV_I32, - "mov.i32", - LIR_OPCODE_SIG_X, - 0); +DEFINE_OPCODE( + LIR_OPCODE_MOV_I32, + "mov.i32", + LIR_OPCODE_SIG_R32_R32, + 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); diff --git a/src/alloy/backend/x64/lowering/lowering_hir_opcodes.inl b/src/alloy/backend/x64/lowering/lowering_hir_opcodes.inl new file mode 100644 index 000000000..1aeddce41 --- /dev/null +++ b/src/alloy/backend/x64/lowering/lowering_hir_opcodes.inl @@ -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); diff --git a/src/alloy/backend/x64/x64_codegen.cc b/src/alloy/backend/x64/lowering/lowering_lir_opcodes.inl similarity index 55% rename from src/alloy/backend/x64/x64_codegen.cc rename to src/alloy/backend/x64/lowering/lowering_lir_opcodes.inl index 153292e58..748d9d221 100644 --- a/src/alloy/backend/x64/x64_codegen.cc +++ b/src/alloy/backend/x64/lowering/lowering_lir_opcodes.inl @@ -7,26 +7,10 @@ ****************************************************************************** */ -#include - -#include - -using namespace alloy; -using namespace alloy::backend; -using namespace alloy::backend::x64; -using namespace alloy::runtime; - - -X64Codegen::X64Codegen(X64Backend* backend) : - backend_(backend) { -} - -X64Codegen::~X64Codegen() { -} - -int X64Codegen::Initialize() { - return 0; -} - -void X64Codegen::Reset() { -} +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); diff --git a/src/alloy/backend/x64/lowering/lowering_sequences.cc b/src/alloy/backend/x64/lowering/lowering_sequences.cc new file mode 100644 index 000000000..049c7dfd7 --- /dev/null +++ b/src/alloy/backend/x64/lowering/lowering_sequences.cc @@ -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 + +#include + +#include + +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 +class Arg { +public: + const static ArgType arg_type = ARG_TYPE; +}; + +class NullArg : public Arg {}; + +template +class ValueRef : public Arg { +public: + enum { type = TYPE }; +}; +template + // vec +class Constant : public Arg { +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 +class Int8Constant : public Constant {}; +template +class Int16Constant : public Constant {}; +template +class Int32Constant : public Constant {}; +template +class Int64Constant : public Constant {}; +template +class Float32Constant : public Constant {}; +template +class Float64Constant : public Constant {}; +// vec + +template +class Out : public Arg { +public: + enum { slot = SLOT }; +}; + +template +class In : public Arg { +public: + enum { slot = SLOT }; + enum { arg = ARG }; +}; + +template +class Reg : public Arg { +public: + enum { reg_name = REG_NAME }; +}; + + +class Matcher { +public: + template struct IntType { static const int value = v; }; + + template + static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType) { + return true; + } + template + static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType) { + return op.value->type == T::type; + } + template + static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType) { + 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 + static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType) { + Instr* instr = instr_list[T::slot]; + return op.value == instr->dest; + } + template + static bool CheckArg(Instr* instr_list[], Instr::Op& op, IntType) { + 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 + static bool CheckDest(Instr* instr_list[], Value* value, IntType) { + return true; + } + template + static bool CheckDest(Instr* instr_list[], Value* value, IntType) { + return value->type == T::type; + } + template + static bool CheckDest(Instr* instr_list[], Value* value, IntType) { + Instr* instr = instr_list[T::slot]; + return value == instr->dest; + } + template + static bool CheckDest(Instr* instr_list[], Value* value, IntType) { + 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 + static typename std::enable_if::value, void>::type + Match(Instr* instr_list[], int& instr_offset, Instr*&, bool&) { + } + template + static typename std::enable_if::value, void>::type + Match(Instr* instr_list[], int& instr_offset, Instr*& instr, bool& matched) { + instr_list[instr_offset++] = instr; + typedef std::tuple_element::type T; + if (instr->opcode->num != T::opcode) { + matched = false; + return; + } + // Matches opcode, check args. + if (!std::is_same::value) { + if (!CheckDest(instr_list, instr->dest, IntType())) { + matched = false; + return; + } + } + if (!std::is_same::value) { + if (!CheckArg(instr_list, instr->src1, IntType())) { + matched = false; + return; + } + } + if (!std::is_same::value) { + if (!CheckArg(instr_list, instr->src2, IntType())) { + matched = false; + return; + } + } + if (!std::is_same::value) { + if (!CheckArg(instr_list, instr->src3, IntType())) { + matched = false; + return; + } + } + instr = instr->next; + Match(instr_list, instr_offset, instr, matched); + } + + template + 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 + static typename std::enable_if::value, void>::type + EmitInstr(LIRBuilder* builder, Instr*[]) { + } + template + static typename std::enable_if::value, void>::type + EmitInstr(LIRBuilder* builder, Instr* instr_list[]) { + typedef std::tuple_element::type T; + //LIRInstr* lir_instr = builder->AppendInstr(T::opcode); + if (!std::is_same::value) { + // lir_instr->dest = ... + } + if (!std::is_same::value) { + // + } + if (!std::is_same::value) { + // + } + if (!std::is_same::value) { + // + } + EmitInstr(builder, instr_list); + } + + template + static void Emit(LIRBuilder* builder, Instr* instr_list[]) { + EmitInstr<0, LIRS>(builder, instr_list); + } +}; + + +template +void Translate(LoweringTable* table) { + auto exec = [](LIRBuilder* builder, Instr*& instr) { + Instr* instr_list[32] = { 0 }; + int instr_offset = 0; + if (Matcher::Matches(instr_list, instr_offset, instr)) { + Emitter::Emit(builder, instr_list); + return true; + } + return false; + }; + auto new_fn = new LoweringTable::TypedFnWrapper(exec); + table->AddSequence(std::tuple_element<0, MATCH>::type::opcode, new_fn); +} + + +} // namespace + + +namespace { +template +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 \ +class BASE_HIR_##num : public HIR_OPCODE{}; +#include +#undef DEFINE_OPCODE +#define DEFINE_OPCODE_V_O(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_V_O_V(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_V_V(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_V_V_O(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_V_V_V(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_V_V_V_V(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_X(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name<> {} +#define DEFINE_OPCODE_X_L(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_X_O(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_X_S(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_X_V(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_X_V_L(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_X_V_O(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_X_V_S(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#define DEFINE_OPCODE_X_V_V(name) \ + template \ + class HIR_##name : public BASE_HIR_OPCODE_##name {} +#include +} + +namespace { +template +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 \ + class BASE_##num : public LIR_OPCODE {}; +#include +#undef DEFINE_OPCODE +#define DEFINE_LIR_OPCODE_X(name) \ + template \ + class LIR_##name : public BASE_LIR_OPCODE_##name<> {} +#define DEFINE_LIR_OPCODE_R32(name) \ + template \ + class LIR_##name : public BASE_LIR_OPCODE_##name {} +#define DEFINE_LIR_OPCODE_R32_R32(name) \ + template \ + class LIR_##name : public BASE_LIR_OPCODE_##name {} +#define DEFINE_LIR_OPCODE_R32_R32_C32(name) \ + template \ + class LIR_##name : public BASE_LIR_OPCODE_##name {} +#include +} + +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< + >> (table); + + Translate, ValueRef, ValueRef> + >, tuple< + LIR_MOV_I32, In<0, 0>>, + LIR_SUB_I32, In<0, 1>> + >> (table); + Translate, ValueRef, Int32Constant<1>> + >, tuple< + LIR_MOV_I32, In<0, 0>>, + LIR_DEC_I32> + >> (table); + + Translate, ValueRef, Constant> + >, tuple< + LIR_IMUL_I32_AUX, In<0, 0>, In<0, 1>> + >> (table); + Translate, ValueRef, ValueRef> + >, tuple< + LIR_MOV_I32, In<0, 0>>, + LIR_IMUL_I32, In<0, 1>> + >> (table); + + Translate, ValueRef, ValueRef> + >, tuple< + LIR_MOV_I32, In<0, 0>>, + LIR_XOR_I32, Reg>, + LIR_DIV_I32>, + LIR_MOV_I32, Reg> + >> (table); + + //Translate, ValueRef, ValueRef>, + // HIR_IS_TRUE, Out<0>> + //>, tuple< + // LIR_MOV_I32, In<0, 0>>, + // LIR_SUB_I32, In<0, 1>>, + // LIR_EFLAGS_NOT_ZF> + //>> (table); +} diff --git a/src/alloy/backend/x64/x64_codegen.h b/src/alloy/backend/x64/lowering/lowering_sequences.h similarity index 66% rename from src/alloy/backend/x64/x64_codegen.h rename to src/alloy/backend/x64/lowering/lowering_sequences.h index 0fd0dd8bb..634d52f47 100644 --- a/src/alloy/backend/x64/x64_codegen.h +++ b/src/alloy/backend/x64/lowering/lowering_sequences.h @@ -7,38 +7,27 @@ ****************************************************************************** */ -#ifndef ALLOY_BACKEND_X64_X64_CODEGEN_H_ -#define ALLOY_BACKEND_X64_X64_CODEGEN_H_ +#ifndef ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_SEQUENCES_H_ +#define ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_SEQUENCES_H_ #include +#include namespace alloy { namespace backend { namespace x64 { +namespace lowering { -class X64Backend; - - -class X64Codegen { -public: - X64Codegen(X64Backend* backend); - ~X64Codegen(); - - int Initialize(); - - void Reset(); - - // - -private: - X64Backend* backend_; -}; +class LoweringTable; + +void RegisterSequences(LoweringTable* table); +} // namespace lowering } // namespace x64 } // namespace backend } // namespace alloy -#endif // ALLOY_BACKEND_X64_X64_CODEGEN_H_ +#endif // ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_SEQUENCES_H_ diff --git a/src/alloy/backend/x64/lowering/lowering_table.cc b/src/alloy/backend/x64/lowering/lowering_table.cc new file mode 100644 index 000000000..66d29063a --- /dev/null +++ b/src/alloy/backend/x64/lowering/lowering_table.cc @@ -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 + +#include + +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; +} \ No newline at end of file diff --git a/src/alloy/backend/x64/lowering/lowering_table.h b/src/alloy/backend/x64/lowering/lowering_table.h new file mode 100644 index 000000000..5b417ac88 --- /dev/null +++ b/src/alloy/backend/x64/lowering/lowering_table.h @@ -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 +#include +#include + + +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 + 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_ diff --git a/src/alloy/backend/x64/lowering/sources.gypi b/src/alloy/backend/x64/lowering/sources.gypi new file mode 100644 index 000000000..f404ccba8 --- /dev/null +++ b/src/alloy/backend/x64/lowering/sources.gypi @@ -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', + ], +} diff --git a/src/alloy/backend/x64/optimizer/passes/redundant_mov_pass.cc b/src/alloy/backend/x64/optimizer/passes/redundant_mov_pass.cc index e69de29bb..acbec6089 100644 --- a/src/alloy/backend/x64/optimizer/passes/redundant_mov_pass.cc +++ b/src/alloy/backend/x64/optimizer/passes/redundant_mov_pass.cc @@ -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 + +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; +} diff --git a/src/alloy/backend/x64/sources.gypi b/src/alloy/backend/x64/sources.gypi index 750becab6..d63c6c415 100644 --- a/src/alloy/backend/x64/sources.gypi +++ b/src/alloy/backend/x64/sources.gypi @@ -6,8 +6,6 @@ 'x64_assembler.h', 'x64_backend.cc', 'x64_backend.h', - 'x64_codegen.cc', - 'x64_codegen.h', 'x64_emitter.cc', 'x64_emitter.h', 'x64_function.cc', @@ -16,6 +14,7 @@ 'includes': [ 'lir/sources.gypi', + 'lowering/sources.gypi', 'optimizer/sources.gypi', ], } diff --git a/src/alloy/backend/x64/x64_assembler.cc b/src/alloy/backend/x64/x64_assembler.cc index 09f809a16..118a50e37 100644 --- a/src/alloy/backend/x64/x64_assembler.cc +++ b/src/alloy/backend/x64/x64_assembler.cc @@ -12,6 +12,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -19,17 +23,25 @@ using namespace alloy; using namespace alloy::backend; using namespace alloy::backend::x64; +using namespace alloy::backend::x64::lir; +using namespace alloy::backend::x64::optimizer; using namespace alloy::hir; using namespace alloy::runtime; X64Assembler::X64Assembler(X64Backend* backend) : + x64_backend_(backend), + optimizer_(0), + builder_(0), Assembler(backend) { } X64Assembler::~X64Assembler() { alloy::tracing::WriteEvent(EventType::AssemblerDeinit({ })); + + delete optimizer_; + delete builder_; } int X64Assembler::Initialize() { @@ -38,6 +50,11 @@ int X64Assembler::Initialize() { return result; } + optimizer_ = new Optimizer(backend_->runtime()); + optimizer_->AddPass(new passes::RedundantMovPass()); + + builder_ = new LIRBuilder(x64_backend_); + alloy::tracing::WriteEvent(EventType::AssemblerInit({ })); @@ -45,15 +62,53 @@ int X64Assembler::Initialize() { } void X64Assembler::Reset() { + builder_->Reset(); + optimizer_->Reset(); + string_buffer_.Reset(); Assembler::Reset(); } int X64Assembler::Assemble( - FunctionInfo* symbol_info, HIRBuilder* builder, + FunctionInfo* symbol_info, HIRBuilder* hir_builder, 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); fn->set_debug_info(debug_info); + // TODO(benvanik): set mc + *out_function = fn; - return 0; + + result = 0; + +XECLEANUP: + Reset(); + return result; } diff --git a/src/alloy/backend/x64/x64_assembler.h b/src/alloy/backend/x64/x64_assembler.h index a883eadca..7a19dc438 100644 --- a/src/alloy/backend/x64/x64_assembler.h +++ b/src/alloy/backend/x64/x64_assembler.h @@ -20,6 +20,8 @@ namespace backend { namespace x64 { class X64Backend; +namespace lir { class LIRBuilder; } +namespace optimizer { class Optimizer; } class X64Assembler : public Assembler { @@ -36,6 +38,11 @@ public: runtime::DebugInfo* debug_info, runtime::Function** out_function); private: + X64Backend* x64_backend_; + lir::LIRBuilder* builder_; + optimizer::Optimizer* optimizer_; + + StringBuffer string_buffer_; }; diff --git a/src/alloy/backend/x64/x64_backend.cc b/src/alloy/backend/x64/x64_backend.cc index dcebf165e..0b2b10879 100644 --- a/src/alloy/backend/x64/x64_backend.cc +++ b/src/alloy/backend/x64/x64_backend.cc @@ -11,20 +11,24 @@ #include #include +#include using namespace alloy; using namespace alloy::backend; using namespace alloy::backend::x64; +using namespace alloy::backend::x64::lowering; using namespace alloy::runtime; X64Backend::X64Backend(Runtime* runtime) : + lowering_table_(0), Backend(runtime) { } X64Backend::~X64Backend() { alloy::tracing::WriteEvent(EventType::Deinit({ })); + delete lowering_table_; } int X64Backend::Initialize() { @@ -33,6 +37,8 @@ int X64Backend::Initialize() { return result; } + lowering_table_ = new LoweringTable(this); + alloy::tracing::WriteEvent(EventType::Init({ })); diff --git a/src/alloy/backend/x64/x64_backend.h b/src/alloy/backend/x64/x64_backend.h index e9102d418..f6f7f13b8 100644 --- a/src/alloy/backend/x64/x64_backend.h +++ b/src/alloy/backend/x64/x64_backend.h @@ -19,6 +19,8 @@ namespace alloy { namespace backend { namespace x64 { +namespace lowering { class LoweringTable; } + #define ALLOY_HAS_X64_BACKEND 1 @@ -28,9 +30,14 @@ public: X64Backend(runtime::Runtime* runtime); virtual ~X64Backend(); + lowering::LoweringTable* lowering_table() const { return lowering_table_; } + virtual int Initialize(); virtual Assembler* CreateAssembler(); + +private: + lowering::LoweringTable* lowering_table_; }; diff --git a/src/alloy/frontend/ppc/ppc_translator.h b/src/alloy/frontend/ppc/ppc_translator.h index 107245f5e..83bfce152 100644 --- a/src/alloy/frontend/ppc/ppc_translator.h +++ b/src/alloy/frontend/ppc/ppc_translator.h @@ -43,7 +43,7 @@ private: private: PPCFrontend* frontend_; PPCScanner* scanner_; - PPCHIRBuilder* builder_; + PPCHIRBuilder* builder_; compiler::Compiler* compiler_; backend::Assembler* assembler_;