Moving alloy/ into xenia/cpu/ to start simplifying things.
This commit is contained in:
parent
59395318f3
commit
29912f44c0
|
@ -1,6 +1,5 @@
|
|||
All code (headers and sources) lives under this path, excluding third_party code.
|
||||
|
||||
* alloy: the dynamic recompiler that parses PPC and generates code.
|
||||
* poly: a lightweight cross-platform/compiler compatibility library.
|
||||
* xdb: xenia debugger library and UI.
|
||||
* xenia: emulator code.
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
alloy: small dynamic recompiler engine
|
||||
===
|
||||
|
||||
Alloy is a transpiler framework that allows for pluggable frontends for decoding
|
||||
guest machine instructions (such as PPC) and pluggable backends for generating
|
||||
host code (such as x64). It features an SSA IR designed to model machine
|
||||
instructions and vector operations and compilation passes that seek to efficiently
|
||||
optimize previously-optimized code.
|
||||
|
||||
Future versions will cache generated code across runs and enable offline
|
||||
precompilation.
|
||||
|
||||
Frontends
|
||||
---
|
||||
|
||||
Frontends are responsible for translating guest machine instructions into IR.
|
||||
Information about the guest machine and ABI is used to support efficient CPU
|
||||
state accesses and debug information.
|
||||
|
||||
* PPC64 with Altivec extenions
|
||||
|
||||
Backends
|
||||
---
|
||||
|
||||
A backend takes optimized IR and assembles an implementation-specific result.
|
||||
The backend is also responsible for executing the code it generates and supporting
|
||||
debugging features (such as breakpoints).
|
||||
|
||||
* x64: IA-64 with AVX2 code generator
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_ALLOY_PRIVATE_H_
|
||||
#define ALLOY_ALLOY_PRIVATE_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
DECLARE_bool(debug);
|
||||
DECLARE_bool(always_disasm);
|
||||
|
||||
DECLARE_bool(validate_hir);
|
||||
|
||||
DECLARE_uint64(break_on_instruction);
|
||||
DECLARE_uint64(break_on_memory);
|
||||
DECLARE_bool(break_on_debugbreak);
|
||||
|
||||
#endif // ALLOY_ALLOY_PRIVATE_H_
|
|
@ -1,35 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/alloy.h"
|
||||
#include "alloy/alloy-private.h"
|
||||
|
||||
using namespace alloy;
|
||||
|
||||
#if 0 && DEBUG
|
||||
#define DEFAULT_DEBUG_FLAG true
|
||||
#else
|
||||
#define DEFAULT_DEBUG_FLAG false
|
||||
#endif
|
||||
|
||||
DEFINE_bool(debug, DEFAULT_DEBUG_FLAG,
|
||||
"Allow debugging and retain debug information.");
|
||||
DEFINE_bool(
|
||||
always_disasm, false,
|
||||
"Always add debug info to functions, even when no debugger is attached.");
|
||||
|
||||
DEFINE_bool(validate_hir, false,
|
||||
"Perform validation checks on the HIR during compilation.");
|
||||
|
||||
// Breakpoints:
|
||||
DEFINE_uint64(break_on_instruction, 0,
|
||||
"int3 before the given guest address is executed.");
|
||||
DEFINE_uint64(break_on_memory, 0,
|
||||
"int3 on read/write to the given memory address.");
|
||||
DEFINE_bool(break_on_debugbreak, true, "int3 on JITed __debugbreak requests.");
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_ALLOY_H_
|
||||
#define ALLOY_ALLOY_H_
|
||||
|
||||
#include "alloy/runtime/function.h"
|
||||
#include "alloy/runtime/module.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "alloy/runtime/thread_state.h"
|
||||
|
||||
#endif // ALLOY_ALLOY_H_
|
|
@ -1,194 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_CONTEXT_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_CONTEXT_H_
|
||||
|
||||
#include "poly/poly.h"
|
||||
#include "poly/vec128.h"
|
||||
|
||||
namespace alloy { namespace runtime {
|
||||
class Runtime;
|
||||
class ThreadState;
|
||||
} }
|
||||
|
||||
namespace alloy {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
using vec128_t = poly::vec128_t;
|
||||
|
||||
// Map:
|
||||
// 0-31: GPR
|
||||
// 32-63: FPR
|
||||
// 64: LR
|
||||
// 65: CTR
|
||||
// 66: XER
|
||||
// 67: FPSCR
|
||||
// 68: VSCR
|
||||
// 69-76: CR0-7
|
||||
// 100: invalid
|
||||
// 128-256: VR
|
||||
|
||||
#pragma pack(push, 4)
|
||||
typedef struct alignas(64) PPCContext_s {
|
||||
// Must be stored at 0x0 for now.
|
||||
// TODO(benvanik): find a nice way to describe this to the JIT.
|
||||
runtime::ThreadState* thread_state;
|
||||
// TODO(benvanik): this is getting nasty. Must be here.
|
||||
uint8_t* membase;
|
||||
|
||||
// Most frequently used registers first.
|
||||
uint64_t r[32]; // General purpose registers
|
||||
uint64_t lr; // Link register
|
||||
uint64_t ctr; // Count register
|
||||
|
||||
// XER register
|
||||
// Split to make it easier to do individual updates.
|
||||
uint8_t xer_ca;
|
||||
uint8_t xer_ov;
|
||||
uint8_t xer_so;
|
||||
|
||||
// Condition registers
|
||||
// These are split to make it easier to do DCE on unused stores.
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr0_lt; // Negative (LT) - result is negative
|
||||
uint8_t cr0_gt; // Positive (GT) - result is positive (and not zero)
|
||||
uint8_t cr0_eq; // Zero (EQ) - result is zero or a stwcx/stdcx completed successfully
|
||||
uint8_t cr0_so; // Summary Overflow (SO) - copy of XER[SO]
|
||||
};
|
||||
} cr0;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr1_fx; // FP exception summary - copy of FPSCR[FX]
|
||||
uint8_t cr1_fex; // FP enabled exception summary - copy of FPSCR[FEX]
|
||||
uint8_t cr1_vx; // FP invalid operation exception summary - copy of FPSCR[VX]
|
||||
uint8_t cr1_ox; // FP overflow exception - copy of FPSCR[OX]
|
||||
};
|
||||
} cr1;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr2_0; uint8_t cr2_1; uint8_t cr2_2; uint8_t cr2_3;
|
||||
};
|
||||
} cr2;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr3_0; uint8_t cr3_1; uint8_t cr3_2; uint8_t cr3_3;
|
||||
};
|
||||
} cr3;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr4_0; uint8_t cr4_1; uint8_t cr4_2; uint8_t cr4_3;
|
||||
};
|
||||
} cr4;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr5_0; uint8_t cr5_1; uint8_t cr5_2; uint8_t cr5_3;
|
||||
};
|
||||
} cr5;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr6_all_equal;
|
||||
uint8_t cr6_1;
|
||||
uint8_t cr6_none_equal;
|
||||
uint8_t cr6_3;
|
||||
};
|
||||
} cr6;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr7_0; uint8_t cr7_1; uint8_t cr7_2; uint8_t cr7_3;
|
||||
};
|
||||
} cr7;
|
||||
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t rn :2; // FP rounding control: 00 = nearest
|
||||
// 01 = toward zero
|
||||
// 10 = toward +infinity
|
||||
// 11 = toward -infinity
|
||||
uint32_t ni :1; // Floating-point non-IEEE mode
|
||||
uint32_t xe :1; // IEEE floating-point inexact exception enable
|
||||
uint32_t ze :1; // IEEE floating-point zero divide exception enable
|
||||
uint32_t ue :1; // IEEE floating-point underflow exception enable
|
||||
uint32_t oe :1; // IEEE floating-point overflow exception enable
|
||||
uint32_t ve :1; // FP invalid op exception enable
|
||||
uint32_t vxcvi :1; // FP invalid op exception: invalid integer convert -- sticky
|
||||
uint32_t vxsqrt :1; // FP invalid op exception: invalid sqrt -- sticky
|
||||
uint32_t vxsoft :1; // FP invalid op exception: software request -- sticky
|
||||
uint32_t reserved :1;
|
||||
uint32_t fprf_un :1; // FP result unordered or NaN (FU or ?)
|
||||
uint32_t fprf_eq :1; // FP result equal or zero (FE or =)
|
||||
uint32_t fprf_gt :1; // FP result greater than or positive (FG or >)
|
||||
uint32_t fprf_lt :1; // FP result less than or negative (FL or <)
|
||||
uint32_t fprf_c :1; // FP result class
|
||||
uint32_t fi :1; // FP fraction inexact
|
||||
uint32_t fr :1; // FP fraction rounded
|
||||
uint32_t vxvc :1; // FP invalid op exception: invalid compare -- sticky
|
||||
uint32_t vximz :1; // FP invalid op exception: infinity * 0 -- sticky
|
||||
uint32_t vxzdz :1; // FP invalid op exception: 0 / 0 -- sticky
|
||||
uint32_t vxidi :1; // FP invalid op exception: infinity / infinity -- sticky
|
||||
uint32_t vxisi :1; // FP invalid op exception: infinity - infinity -- sticky
|
||||
uint32_t vxsnan :1; // FP invalid op exception: SNaN -- sticky
|
||||
uint32_t xx :1; // FP inexact exception -- sticky
|
||||
uint32_t zx :1; // FP zero divide exception -- sticky
|
||||
uint32_t ux :1; // FP underflow exception -- sticky
|
||||
uint32_t ox :1; // FP overflow exception -- sticky
|
||||
uint32_t vx :1; // FP invalid operation exception summary
|
||||
uint32_t fex :1; // FP enabled exception summary
|
||||
uint32_t fx :1; // FP exception summary -- sticky
|
||||
} bits;
|
||||
} fpscr; // Floating-point status and control register
|
||||
|
||||
uint8_t vscr_sat;
|
||||
|
||||
double f[32]; // Floating-point registers
|
||||
vec128_t v[128]; // VMX128 vector registers
|
||||
|
||||
// uint32_t get_fprf() {
|
||||
// return fpscr.value & 0x000F8000;
|
||||
// }
|
||||
// void set_fprf(const uint32_t v) {
|
||||
// fpscr.value = (fpscr.value & ~0x000F8000) | v;
|
||||
// }
|
||||
|
||||
// Thread ID assigned to this context.
|
||||
uint32_t thread_id;
|
||||
|
||||
// Reserve address for load acquire/store release. Shared.
|
||||
uint64_t* reserve_address;
|
||||
uint64_t* reserve_value;
|
||||
|
||||
// Used to shuttle data into externs. Contents volatile.
|
||||
uint64_t scratch;
|
||||
|
||||
// Runtime-specific data pointer. Used on callbacks to get access to the
|
||||
// current runtime and its data.
|
||||
runtime::Runtime* runtime;
|
||||
|
||||
void SetRegFromString(const char* name, const char* value);
|
||||
bool CompareRegWithString(const char* name, const char* value,
|
||||
char* out_value, size_t out_value_size);
|
||||
} PPCContext;
|
||||
#pragma pack(pop)
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_CONTEXT_H_
|
|
@ -1,76 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/memory.h"
|
||||
|
||||
#include "poly/poly.h"
|
||||
|
||||
namespace alloy {
|
||||
|
||||
Memory::Memory()
|
||||
: membase_(nullptr),
|
||||
reserve_address_(0),
|
||||
reserve_value_(0),
|
||||
trace_base_(0) {
|
||||
system_page_size_ = poly::page_size();
|
||||
}
|
||||
|
||||
Memory::~Memory() = default;
|
||||
|
||||
int Memory::Initialize() { return 0; }
|
||||
|
||||
void Memory::Zero(uint64_t address, size_t size) {
|
||||
uint8_t* p = membase_ + address;
|
||||
memset(p, 0, size);
|
||||
}
|
||||
|
||||
void Memory::Fill(uint64_t address, size_t size, uint8_t value) {
|
||||
uint8_t* p = membase_ + address;
|
||||
memset(p, value, size);
|
||||
}
|
||||
|
||||
void Memory::Copy(uint64_t dest, uint64_t src, size_t size) {
|
||||
uint8_t* pdest = membase_ + dest;
|
||||
const uint8_t* psrc = membase_ + src;
|
||||
memcpy(pdest, psrc, size);
|
||||
}
|
||||
|
||||
uint64_t Memory::SearchAligned(uint64_t start, uint64_t end,
|
||||
const uint32_t* values, size_t value_count) {
|
||||
assert_true(start <= end);
|
||||
const uint32_t* p = reinterpret_cast<const uint32_t*>(membase_ + start);
|
||||
const uint32_t* pe = reinterpret_cast<const uint32_t*>(membase_ + end);
|
||||
while (p != pe) {
|
||||
if (*p == values[0]) {
|
||||
const uint32_t* pc = p + 1;
|
||||
size_t matched = 1;
|
||||
for (size_t n = 1; n < value_count; n++, pc++) {
|
||||
if (*pc != values[n]) {
|
||||
break;
|
||||
}
|
||||
matched++;
|
||||
}
|
||||
if (matched == value_count) {
|
||||
return uint64_t(reinterpret_cast<const uint8_t*>(p) - membase_);
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SimpleMemory::SimpleMemory(size_t capacity) : memory_(capacity) {
|
||||
membase_ = reinterpret_cast<uint8_t*>(memory_.data());
|
||||
reserve_address_ = capacity - 8;
|
||||
reserve_value_ = capacity - 16;
|
||||
}
|
||||
|
||||
SimpleMemory::~SimpleMemory() = default;
|
||||
|
||||
} // namespace alloy
|
|
@ -1,62 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_MEMORY_H_
|
||||
#define ALLOY_MEMORY_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace alloy {
|
||||
|
||||
class Memory {
|
||||
public:
|
||||
Memory();
|
||||
virtual ~Memory();
|
||||
|
||||
inline uint8_t* membase() const { return membase_; }
|
||||
inline uint8_t* Translate(uint64_t guest_address) const {
|
||||
return membase_ + guest_address;
|
||||
};
|
||||
inline uint64_t* reserve_address() { return &reserve_address_; }
|
||||
inline uint64_t* reserve_value() { return &reserve_value_; }
|
||||
|
||||
uint64_t trace_base() const { return trace_base_; }
|
||||
void set_trace_base(uint64_t value) { trace_base_ = value; }
|
||||
|
||||
virtual int Initialize();
|
||||
|
||||
// TODO(benvanik): make poly memory utils for these.
|
||||
void Zero(uint64_t address, size_t size);
|
||||
void Fill(uint64_t address, size_t size, uint8_t value);
|
||||
void Copy(uint64_t dest, uint64_t src, size_t size);
|
||||
|
||||
uint64_t SearchAligned(uint64_t start, uint64_t end, const uint32_t* values,
|
||||
size_t value_count);
|
||||
|
||||
protected:
|
||||
size_t system_page_size_;
|
||||
uint8_t* membase_;
|
||||
uint64_t reserve_address_;
|
||||
uint64_t reserve_value_;
|
||||
uint64_t trace_base_;
|
||||
};
|
||||
|
||||
class SimpleMemory : public Memory {
|
||||
public:
|
||||
SimpleMemory(size_t capacity);
|
||||
~SimpleMemory() override;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> memory_;
|
||||
};
|
||||
|
||||
} // namespace alloy
|
||||
|
||||
#endif // ALLOY_MEMORY_H_
|
|
@ -1,37 +0,0 @@
|
|||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'alloy-private.h',
|
||||
'alloy.cc',
|
||||
'alloy.h',
|
||||
'memory.cc',
|
||||
'memory.h',
|
||||
],
|
||||
|
||||
'conditions': [
|
||||
['OS == "mac" or OS == "linux"', {
|
||||
'sources': [
|
||||
],
|
||||
}],
|
||||
['OS == "linux"', {
|
||||
'sources': [
|
||||
],
|
||||
}],
|
||||
['OS == "mac"', {
|
||||
'sources': [
|
||||
],
|
||||
}],
|
||||
['OS == "win"', {
|
||||
'sources': [
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
||||
'includes': [
|
||||
'backend/sources.gypi',
|
||||
'compiler/sources.gypi',
|
||||
'frontend/sources.gypi',
|
||||
'hir/sources.gypi',
|
||||
'runtime/sources.gypi',
|
||||
],
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/test/util.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
using namespace poly;
|
||||
|
||||
TEST_CASE("INSERT_INT8", "[instr]") {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
TestFunction test([i](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstant(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->r[4] = i;
|
||||
ctx->r[5] = 100 + i;
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
auto expected =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
expected.i8[i ^ 0x3] = 100 + i;
|
||||
REQUIRE(result == expected);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("INSERT_INT16", "[instr]") {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
TestFunction test([i](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstant(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT16_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, 6, 7);
|
||||
ctx->r[4] = i;
|
||||
ctx->r[5] = 100 + i;
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
auto expected = vec128s(0, 1, 2, 3, 4, 5, 6, 7);
|
||||
expected.i16[i ^ 0x1] = 100 + i;
|
||||
REQUIRE(result == expected);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("INSERT_INT32", "[instr]") {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
TestFunction test([i](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstant(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT32_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 2, 3);
|
||||
ctx->r[4] = i;
|
||||
ctx->r[5] = 100 + i;
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
auto expected = vec128i(0, 1, 2, 3);
|
||||
expected.i32[i] = 100 + i;
|
||||
REQUIRE(result == expected);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,279 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/test/util.h"
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
using namespace poly;
|
||||
|
||||
TEST_CASE("SHR_I8", "[instr]") {
|
||||
TestFunction test([](hir::HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xF0;
|
||||
ctx->r[5] = 4;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x0F);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x7F);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x80;
|
||||
ctx->r[5] = 8;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7F;
|
||||
ctx->r[5] = 7;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHR_I16", "[instr]") {
|
||||
TestFunction test([](hir::HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF00;
|
||||
ctx->r[5] = 8;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x00FF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFE;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x7FFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x8000;
|
||||
ctx->r[5] = 16;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFF;
|
||||
ctx->r[5] = 15;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHR_I32", "[instr]") {
|
||||
TestFunction test([](hir::HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFF0000;
|
||||
ctx->r[5] = 16;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x0000FFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFE;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x7FFFFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x80000000;
|
||||
ctx->r[5] = 32;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x80000000);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFF;
|
||||
ctx->r[5] = 31;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHR_I64", "[instr]") {
|
||||
TestFunction test([](hir::HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.Shr(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFF00000000ull;
|
||||
ctx->r[5] = 32;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x00000000FFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFFFFFFFFFFull;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFFFFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFFFFFFFFFEull;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x7FFFFFFFFFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x8000000000000000ull;
|
||||
ctx->r[5] = 64;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x8000000000000000ull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFFFFFFFFFFull;
|
||||
ctx->r[5] = 63;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHR_V128", "[instr]") {
|
||||
TestFunction test([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Shr(LoadVR(b, 4), b.Truncate(LoadGPR(b, 1), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[1] = 0;
|
||||
ctx->v[4] = vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[1] = 1;
|
||||
ctx->v[4] = vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[1] = 2;
|
||||
ctx->v[4] = vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0x3FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[1] = 8;
|
||||
ctx->v[4] = vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
});
|
||||
}
|
|
@ -7,9 +7,10 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/backend/assembler.h"
|
||||
#include "xenia/cpu/backend/assembler.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
|
||||
Assembler::Assembler(Backend* backend) : backend_(backend) {}
|
||||
|
@ -21,4 +22,5 @@ int Assembler::Initialize() { return 0; }
|
|||
void Assembler::Reset() {}
|
||||
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_ASSEMBLER_H_
|
||||
#define ALLOY_BACKEND_ASSEMBLER_H_
|
||||
#ifndef XENIA_BACKEND_ASSEMBLER_H_
|
||||
#define XENIA_BACKEND_ASSEMBLER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace hir {
|
||||
class HIRBuilder;
|
||||
} // namespace hir
|
||||
|
@ -22,9 +23,11 @@ class Function;
|
|||
class FunctionInfo;
|
||||
class Runtime;
|
||||
} // namespace runtime
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
|
||||
class Backend;
|
||||
|
@ -49,6 +52,7 @@ class Assembler {
|
|||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_ASSEMBLER_H_
|
||||
#endif // XENIA_BACKEND_ASSEMBLER_H_
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/backend/backend.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
|
||||
using alloy::runtime::Runtime;
|
||||
using xe::cpu::runtime::Runtime;
|
||||
|
||||
Backend::Backend(Runtime* runtime) : runtime_(runtime) {
|
||||
memset(&machine_info_, 0, sizeof(machine_info_));
|
||||
|
@ -27,4 +28,5 @@ void* Backend::AllocThreadData() { return nullptr; }
|
|||
void Backend::FreeThreadData(void* thread_data) {}
|
||||
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,20 +7,23 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_BACKEND_H_
|
||||
#define ALLOY_BACKEND_BACKEND_H_
|
||||
#ifndef XENIA_BACKEND_BACKEND_H_
|
||||
#define XENIA_BACKEND_BACKEND_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "alloy/backend/machine_info.h"
|
||||
#include "xenia/cpu/backend/machine_info.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace runtime {
|
||||
class Runtime;
|
||||
} // namespace runtime
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
|
||||
class Assembler;
|
||||
|
@ -46,6 +49,7 @@ class Backend {
|
|||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_BACKEND_H_
|
||||
#endif // XENIA_BACKEND_BACKEND_H_
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_MACHINE_INFO_H_
|
||||
#define ALLOY_BACKEND_MACHINE_INFO_H_
|
||||
#ifndef XENIA_BACKEND_MACHINE_INFO_H_
|
||||
#define XENIA_BACKEND_MACHINE_INFO_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
|
||||
struct MachineInfo {
|
||||
|
@ -30,6 +31,7 @@ struct MachineInfo {
|
|||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_MACHINE_INFO_H_
|
||||
#endif // XENIA_BACKEND_MACHINE_INFO_H_
|
|
@ -7,14 +7,14 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/backend/x64/x64_assembler.h"
|
||||
#include "xenia/cpu/backend/x64/x64_assembler.h"
|
||||
|
||||
#include "alloy/backend/x64/x64_backend.h"
|
||||
#include "alloy/backend/x64/x64_emitter.h"
|
||||
#include "alloy/backend/x64/x64_function.h"
|
||||
#include "alloy/hir/hir_builder.h"
|
||||
#include "alloy/hir/label.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
#include "xenia/cpu/backend/x64/x64_function.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/hir/label.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "poly/reset_scope.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
|
@ -22,17 +22,18 @@ namespace BE {
|
|||
#include <beaengine/BeaEngine.h>
|
||||
} // namespace BE
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::runtime;
|
||||
using namespace xe::cpu::runtime;
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::runtime::DebugInfo;
|
||||
using alloy::runtime::Function;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::runtime::DebugInfo;
|
||||
using xe::cpu::runtime::Function;
|
||||
using xe::cpu::runtime::FunctionInfo;
|
||||
|
||||
X64Assembler::X64Assembler(X64Backend* backend)
|
||||
: Assembler(backend), x64_backend_(backend) {}
|
||||
|
@ -64,7 +65,7 @@ int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
|||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<DebugInfo> debug_info,
|
||||
uint32_t trace_flags, Function** out_function) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Reset when we leave.
|
||||
poly::make_reset_scope(this);
|
||||
|
@ -130,4 +131,5 @@ void X64Assembler::DumpMachineCode(DebugInfo* debug_info, void* machine_code,
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,15 +7,16 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_X64_ASSEMBLER_H_
|
||||
#define ALLOY_BACKEND_X64_X64_ASSEMBLER_H_
|
||||
#ifndef XENIA_BACKEND_X64_X64_ASSEMBLER_H_
|
||||
#define XENIA_BACKEND_X64_X64_ASSEMBLER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "alloy/backend/assembler.h"
|
||||
#include "xenia/cpu/backend/assembler.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -51,6 +52,7 @@ class X64Assembler : public Assembler {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_ASSEMBLER_H_
|
||||
#endif // XENIA_BACKEND_X64_X64_ASSEMBLER_H_
|
|
@ -7,18 +7,19 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
|
||||
#include "alloy/backend/x64/x64_assembler.h"
|
||||
#include "alloy/backend/x64/x64_code_cache.h"
|
||||
#include "alloy/backend/x64/x64_sequences.h"
|
||||
#include "alloy/backend/x64/x64_thunk_emitter.h"
|
||||
#include "xenia/cpu/backend/x64/x64_assembler.h"
|
||||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
||||
#include "xenia/cpu/backend/x64/x64_thunk_emitter.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
using alloy::runtime::Runtime;
|
||||
using xe::cpu::runtime::Runtime;
|
||||
|
||||
X64Backend::X64Backend(Runtime* runtime) : Backend(runtime), code_cache_(0) {}
|
||||
|
||||
|
@ -62,4 +63,5 @@ std::unique_ptr<Assembler> X64Backend::CreateAssembler() {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,18 +7,19 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_X64_BACKEND_H_
|
||||
#define ALLOY_BACKEND_X64_X64_BACKEND_H_
|
||||
#ifndef XENIA_BACKEND_X64_X64_BACKEND_H_
|
||||
#define XENIA_BACKEND_X64_X64_BACKEND_H_
|
||||
|
||||
#include "alloy/backend/backend.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
class X64CodeCache;
|
||||
|
||||
#define ALLOY_HAS_X64_BACKEND 1
|
||||
#define XENIA_HAS_X64_BACKEND 1
|
||||
|
||||
typedef void* (*HostToGuestThunk)(void* target, void* arg0, void* arg1);
|
||||
typedef void* (*GuestToHostThunk)(void* target, void* arg0, void* arg1);
|
||||
|
@ -44,6 +45,7 @@ class X64Backend : public Backend {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_BACKEND_H_
|
||||
#endif // XENIA_BACKEND_X64_X64_BACKEND_H_
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_X64_CODE_CACHE_H_
|
||||
#define ALLOY_BACKEND_X64_X64_CODE_CACHE_H_
|
||||
#ifndef XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
||||
#define XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -41,6 +42,7 @@ class X64CodeCache {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_CODE_CACHE_H_
|
||||
#endif // XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
|
@ -7,15 +7,15 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <alloy/backend/x64/x64_code_cache.h>
|
||||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <poly/assert.h>
|
||||
#include <poly/math.h>
|
||||
#include <xenia/profiling.h>
|
||||
#include "poly/assert.h"
|
||||
#include "poly/math.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -49,8 +49,6 @@ int X64CodeCache::Initialize() { return 0; }
|
|||
|
||||
void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||
size_t stack_size) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Always move the code to land on 16b alignment. We do this by rounding up
|
||||
// to 16b so that all offsets are aligned.
|
||||
code_size = poly::round_up(code_size, 16);
|
||||
|
@ -96,4 +94,5 @@ X64CodeChunk::~X64CodeChunk() {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,12 +7,12 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/backend/x64/x64_code_cache.h"
|
||||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||
|
||||
#include "poly/poly.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -59,8 +59,6 @@ int X64CodeCache::Initialize() { return 0; }
|
|||
|
||||
void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||
size_t stack_size) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
size_t alloc_size = code_size;
|
||||
|
||||
// Add unwind info into the allocation size. Keep things 16b aligned.
|
||||
|
@ -279,4 +277,5 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size,
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,42 +7,43 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/backend/x64/x64_emitter.h"
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
|
||||
#include "alloy/alloy-private.h"
|
||||
#include "alloy/backend/x64/x64_backend.h"
|
||||
#include "alloy/backend/x64/x64_code_cache.h"
|
||||
#include "alloy/backend/x64/x64_function.h"
|
||||
#include "alloy/backend/x64/x64_sequences.h"
|
||||
#include "alloy/backend/x64/x64_thunk_emitter.h"
|
||||
#include "alloy/hir/hir_builder.h"
|
||||
#include "alloy/runtime/debug_info.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "alloy/runtime/symbol_info.h"
|
||||
#include "alloy/runtime/thread_state.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||
#include "xenia/cpu/backend/x64/x64_function.h"
|
||||
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
||||
#include "xenia/cpu/backend/x64/x64_thunk_emitter.h"
|
||||
#include "xenia/cpu/cpu-private.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/runtime/debug_info.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/cpu/runtime/symbol_info.h"
|
||||
#include "xenia/cpu/runtime/thread_state.h"
|
||||
#include "poly/vec128.h"
|
||||
#include "xdb/protocol.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::runtime;
|
||||
|
||||
using poly::vec128b;
|
||||
using poly::vec128f;
|
||||
using poly::vec128i;
|
||||
|
||||
using namespace Xbyak;
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::Instr;
|
||||
using alloy::runtime::Function;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
using alloy::runtime::SourceMapEntry;
|
||||
using alloy::runtime::ThreadState;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::Instr;
|
||||
using xe::cpu::runtime::Function;
|
||||
using xe::cpu::runtime::FunctionInfo;
|
||||
using xe::cpu::runtime::SourceMapEntry;
|
||||
using xe::cpu::runtime::ThreadState;
|
||||
|
||||
static const size_t MAX_CODE_SIZE = 1 * 1024 * 1024;
|
||||
|
||||
|
@ -77,7 +78,7 @@ int X64Emitter::Initialize() { return 0; }
|
|||
int X64Emitter::Emit(HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
runtime::DebugInfo* debug_info, uint32_t trace_flags,
|
||||
void*& out_code_address, size_t& out_code_size) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Reset.
|
||||
if (debug_info_flags & DEBUG_INFO_SOURCE_MAP) {
|
||||
|
@ -937,4 +938,5 @@ Address X64Emitter::StashXmm(int index, const Xmm& r) {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,14 +7,15 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_X64_EMITTER_H_
|
||||
#define ALLOY_BACKEND_X64_X64_EMITTER_H_
|
||||
#ifndef XENIA_BACKEND_X64_X64_EMITTER_H_
|
||||
#define XENIA_BACKEND_X64_X64_EMITTER_H_
|
||||
|
||||
#include "alloy/hir/value.h"
|
||||
#include "xenia/cpu/hir/value.h"
|
||||
#include "poly/arena.h"
|
||||
#include "third_party/xbyak/xbyak/xbyak.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace hir {
|
||||
class HIRBuilder;
|
||||
class Instr;
|
||||
|
@ -25,9 +26,11 @@ class FunctionInfo;
|
|||
class Runtime;
|
||||
class SymbolInfo;
|
||||
} // namespace runtime
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -208,6 +211,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_EMITTER_H_
|
||||
#endif // XENIA_BACKEND_X64_X64_EMITTER_H_
|
|
@ -7,20 +7,21 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/backend/x64/x64_function.h"
|
||||
#include "xenia/cpu/backend/x64/x64_function.h"
|
||||
|
||||
#include "alloy/backend/x64/x64_backend.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "alloy/runtime/thread_state.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/cpu/runtime/thread_state.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
using alloy::runtime::Breakpoint;
|
||||
using alloy::runtime::Function;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
using alloy::runtime::ThreadState;
|
||||
using xe::cpu::runtime::Breakpoint;
|
||||
using xe::cpu::runtime::Function;
|
||||
using xe::cpu::runtime::FunctionInfo;
|
||||
using xe::cpu::runtime::ThreadState;
|
||||
|
||||
X64Function::X64Function(FunctionInfo* symbol_info)
|
||||
: Function(symbol_info), machine_code_(nullptr), code_size_(0) {}
|
||||
|
@ -47,4 +48,5 @@ int X64Function::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,13 +7,14 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_X64_FUNCTION_H_
|
||||
#define ALLOY_BACKEND_X64_X64_FUNCTION_H_
|
||||
#ifndef XENIA_BACKEND_X64_X64_FUNCTION_H_
|
||||
#define XENIA_BACKEND_X64_X64_FUNCTION_H_
|
||||
|
||||
#include "alloy/runtime/function.h"
|
||||
#include "alloy/runtime/symbol_info.h"
|
||||
#include "xenia/cpu/runtime/function.h"
|
||||
#include "xenia/cpu/runtime/symbol_info.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -40,6 +41,7 @@ class X64Function : public runtime::Function {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_FUNCTION_H_
|
||||
#endif // XENIA_BACKEND_X64_X64_FUNCTION_H_
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
// A note about vectors:
|
||||
// Alloy represents vectors as xyzw pairs, with indices 0123.
|
||||
// Xenia represents vectors as xyzw pairs, with indices 0123.
|
||||
// XMM registers are xyzw pairs with indices 3210, making them more like wzyx.
|
||||
// This makes things somewhat confusing. It'd be nice to just shuffle the
|
||||
// registers around on load/store, however certain operations require that
|
||||
|
@ -22,22 +22,23 @@
|
|||
// load into xmm register:
|
||||
// [0F 0E 0D 0C] [0B 0A 09 08] [07 06 05 04] [03 02 01 00] (w, z, y, x)
|
||||
|
||||
#include "alloy/backend/x64/x64_sequences.h"
|
||||
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
||||
|
||||
#include "alloy/backend/x64/x64_emitter.h"
|
||||
#include "alloy/backend/x64/x64_tracers.h"
|
||||
#include "alloy/hir/hir_builder.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
#include "xenia/cpu/backend/x64/x64_tracers.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
using namespace Xbyak;
|
||||
|
||||
// TODO(benvanik): direct usings.
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::runtime;
|
||||
|
||||
using poly::vec128b;
|
||||
|
||||
|
@ -45,7 +46,7 @@ typedef bool (*SequenceSelectFn)(X64Emitter&, const Instr*, const Instr**);
|
|||
std::unordered_multimap<uint32_t, SequenceSelectFn> sequence_table;
|
||||
|
||||
// Utilities/types used only in this file:
|
||||
#include "alloy/backend/x64/x64_sequence.inl"
|
||||
#include "xenia/cpu/backend/x64/x64_sequence.inl"
|
||||
|
||||
// Selects the right byte/word/etc from a vector. We need to flip logical
|
||||
// indices (0,1,2,3,4,5,6,7,...) = (3,2,1,0,7,6,5,4,...)
|
||||
|
@ -5882,4 +5883,5 @@ bool SelectSequence(X64Emitter& e, const Instr* i, const Instr** new_tail) {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,16 +7,19 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_X64_SEQUENCES_H_
|
||||
#define ALLOY_BACKEND_X64_X64_SEQUENCES_H_
|
||||
#ifndef XENIA_BACKEND_X64_X64_SEQUENCES_H_
|
||||
#define XENIA_BACKEND_X64_X64_SEQUENCES_H_
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace hir {
|
||||
class Instr;
|
||||
} // namespace hir
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -28,6 +31,7 @@ bool SelectSequence(X64Emitter& e, const hir::Instr* i,
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_SEQUENCES_H_
|
||||
#endif // XENIA_BACKEND_X64_X64_SEQUENCES_H_
|
|
@ -7,11 +7,12 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/backend/x64/x64_thunk_emitter.h"
|
||||
#include "xenia/cpu/backend/x64/x64_thunk_emitter.h"
|
||||
|
||||
#include "third_party/xbyak/xbyak/xbyak.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -142,4 +143,5 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,13 +7,14 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_X64_THUNK_EMITTER_H_
|
||||
#define ALLOY_BACKEND_X64_X64_THUNK_EMITTER_H_
|
||||
#ifndef XENIA_BACKEND_X64_X64_THUNK_EMITTER_H_
|
||||
#define XENIA_BACKEND_X64_X64_THUNK_EMITTER_H_
|
||||
|
||||
#include "alloy/backend/x64/x64_backend.h"
|
||||
#include "alloy/backend/x64/x64_emitter.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -136,6 +137,7 @@ class X64ThunkEmitter : public X64Emitter {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_THUNK_EMITTER_H_
|
||||
#endif // XENIA_BACKEND_X64_X64_THUNK_EMITTER_H_
|
|
@ -7,17 +7,18 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/backend/x64/x64_tracers.h"
|
||||
#include "xenia/cpu/backend/x64/x64_tracers.h"
|
||||
|
||||
#include "alloy/backend/x64/x64_emitter.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "alloy/runtime/thread_state.h"
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/cpu/runtime/thread_state.h"
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::backend::x64;
|
||||
using namespace alloy::runtime;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu::backend::x64;
|
||||
using namespace xe::cpu::runtime;
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
@ -197,4 +198,5 @@ void TraceMemoryStoreV128(void* raw_context, uint32_t address, __m128 value) {
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,13 +7,14 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_X64_TRACERS_H_
|
||||
#define ALLOY_BACKEND_X64_X64_TRACERS_H_
|
||||
#ifndef XENIA_BACKEND_X64_X64_TRACERS_H_
|
||||
#define XENIA_BACKEND_X64_X64_TRACERS_H_
|
||||
|
||||
#include <xmmintrin.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
class X64Emitter;
|
||||
|
@ -65,6 +66,7 @@ void TraceMemoryStoreV128(void* raw_context, uint32_t address, __m128 value);
|
|||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_TRACERS_H_
|
||||
#endif // XENIA_BACKEND_X64_X64_TRACERS_H_
|
|
@ -7,16 +7,17 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::runtime::Runtime;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::runtime::Runtime;
|
||||
|
||||
Compiler::Compiler(Runtime* runtime) : runtime_(runtime) {}
|
||||
|
||||
|
@ -30,8 +31,6 @@ void Compiler::AddPass(std::unique_ptr<CompilerPass> pass) {
|
|||
void Compiler::Reset() {}
|
||||
|
||||
int Compiler::Compile(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// TODO(benvanik): sophisticated stuff. Run passes in parallel, run until they
|
||||
// stop changing things, etc.
|
||||
for (size_t i = 0; i < passes_.size(); ++i) {
|
||||
|
@ -46,4 +45,5 @@ int Compiler::Compile(HIRBuilder* builder) {
|
|||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,22 +7,25 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_COMPILER_H_
|
||||
#define ALLOY_COMPILER_COMPILER_H_
|
||||
#ifndef XENIA_COMPILER_COMPILER_H_
|
||||
#define XENIA_COMPILER_COMPILER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "alloy/hir/hir_builder.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "poly/arena.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace runtime {
|
||||
class Runtime;
|
||||
} // namespace runtime
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
|
||||
class CompilerPass;
|
||||
|
@ -49,6 +52,7 @@ class Compiler {
|
|||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_COMPILER_H_
|
||||
#endif // XENIA_COMPILER_COMPILER_H_
|
|
@ -7,11 +7,12 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
|
||||
CompilerPass::CompilerPass() : runtime_(0), compiler_(0) {}
|
||||
|
@ -29,4 +30,5 @@ poly::Arena* CompilerPass::scratch_arena() const {
|
|||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,19 +7,22 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_COMPILER_PASS_H_
|
||||
#define ALLOY_COMPILER_COMPILER_PASS_H_
|
||||
#ifndef XENIA_COMPILER_COMPILER_PASS_H_
|
||||
#define XENIA_COMPILER_COMPILER_PASS_H_
|
||||
|
||||
#include "alloy/hir/hir_builder.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "poly/arena.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace runtime {
|
||||
class Runtime;
|
||||
} // namespace runtime
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
|
||||
class Compiler;
|
||||
|
@ -42,6 +45,7 @@ class CompilerPass {
|
|||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_COMPILER_PASS_H_
|
||||
#endif // XENIA_COMPILER_COMPILER_PASS_H_
|
|
@ -7,21 +7,21 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_COMPILER_PASSES_H_
|
||||
#define ALLOY_COMPILER_COMPILER_PASSES_H_
|
||||
#ifndef XENIA_COMPILER_COMPILER_PASSES_H_
|
||||
#define XENIA_COMPILER_COMPILER_PASSES_H_
|
||||
|
||||
#include "alloy/compiler/passes/constant_propagation_pass.h"
|
||||
#include "alloy/compiler/passes/context_promotion_pass.h"
|
||||
#include "alloy/compiler/passes/control_flow_analysis_pass.h"
|
||||
#include "alloy/compiler/passes/control_flow_simplification_pass.h"
|
||||
#include "alloy/compiler/passes/data_flow_analysis_pass.h"
|
||||
#include "alloy/compiler/passes/dead_code_elimination_pass.h"
|
||||
//#include "alloy/compiler/passes/dead_store_elimination_pass.h"
|
||||
#include "alloy/compiler/passes/finalization_pass.h"
|
||||
#include "alloy/compiler/passes/register_allocation_pass.h"
|
||||
#include "alloy/compiler/passes/simplification_pass.h"
|
||||
#include "alloy/compiler/passes/validation_pass.h"
|
||||
#include "alloy/compiler/passes/value_reduction_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/constant_propagation_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/context_promotion_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/control_flow_analysis_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/control_flow_simplification_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/data_flow_analysis_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/dead_code_elimination_pass.h"
|
||||
//#include "xenia/cpu/compiler/passes/dead_store_elimination_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/finalization_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/register_allocation_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/simplification_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/validation_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/value_reduction_pass.h"
|
||||
|
||||
// TODO:
|
||||
// - mark_use/mark_set
|
||||
|
@ -176,4 +176,4 @@
|
|||
// reg0 = load_local +123 <-- load inserted
|
||||
// reg0 = mul reg0, reg1
|
||||
|
||||
#endif // ALLOY_COMPILER_COMPILER_PASSES_H_
|
||||
#endif // XENIA_COMPILER_COMPILER_PASSES_H_
|
|
@ -7,30 +7,29 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/constant_propagation_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/constant_propagation_pass.h"
|
||||
|
||||
#include "alloy/runtime/function.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/runtime/function.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::TypeName;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::TypeName;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
ConstantPropagationPass::ConstantPropagationPass() : CompilerPass() {}
|
||||
|
||||
ConstantPropagationPass::~ConstantPropagationPass() {}
|
||||
|
||||
int ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Once ContextPromotion has run there will likely be a whole slew of
|
||||
// constants that can be pushed through the function.
|
||||
// Example:
|
||||
|
@ -302,7 +301,8 @@ int ConstantPropagationPass::Run(HIRBuilder* builder) {
|
|||
break;
|
||||
// TODO(benvanik): ADD_CARRY (w/ ARITHMETIC_SET_CARRY)
|
||||
case OPCODE_ADD_CARRY:
|
||||
if (i->src1.value->IsConstantZero() && i->src2.value->IsConstantZero()) {
|
||||
if (i->src1.value->IsConstantZero() &&
|
||||
i->src2.value->IsConstantZero()) {
|
||||
Value* ca = i->src3.value;
|
||||
// If carry is set find the DID_CARRY and fix it.
|
||||
if (!!(i->flags & ARITHMETIC_SET_CARRY)) {
|
||||
|
@ -485,4 +485,5 @@ void ConstantPropagationPass::PropagateCarry(Value* v, bool did_carry) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
@ -29,6 +30,7 @@ class ConstantPropagationPass : public CompilerPass {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
|
@ -7,29 +7,30 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/context_promotion_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/context_promotion_pass.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
DEFINE_bool(store_all_context_values, false,
|
||||
"Don't strip dead context stores to aid in debugging.");
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::frontend::ContextInfo;
|
||||
using alloy::hir::Block;
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::Instr;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::frontend::ContextInfo;
|
||||
using xe::cpu::hir::Block;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::Instr;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
ContextPromotionPass::ContextPromotionPass() : CompilerPass() {}
|
||||
|
||||
|
@ -49,8 +50,6 @@ int ContextPromotionPass::Initialize(Compiler* compiler) {
|
|||
}
|
||||
|
||||
int ContextPromotionPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Like mem2reg, but because context memory is unaliasable it's easier to
|
||||
// check and convert LoadContext/StoreContext into value operations.
|
||||
// Example of load->value promotion:
|
||||
|
@ -147,4 +146,5 @@ void ContextPromotionPass::RemoveDeadStoresBlock(Block* block) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,10 +7,10 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
#if XE_COMPILER_MSVC
|
||||
#pragma warning(push)
|
||||
|
@ -23,7 +23,8 @@
|
|||
#include <llvm/ADT/BitVector.h>
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
@ -47,6 +48,7 @@ class ContextPromotionPass : public CompilerPass {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
|
@ -7,30 +7,29 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/control_flow_analysis_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/control_flow_analysis_pass.h"
|
||||
|
||||
#include "alloy/backend/backend.h"
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::Edge;
|
||||
using alloy::hir::HIRBuilder;
|
||||
using xe::cpu::hir::Edge;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
|
||||
ControlFlowAnalysisPass::ControlFlowAnalysisPass() : CompilerPass() {}
|
||||
|
||||
ControlFlowAnalysisPass::~ControlFlowAnalysisPass() {}
|
||||
|
||||
int ControlFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Reset edges for all blocks. Needed to be re-runnable.
|
||||
// Note that this wastes a bunch of arena memory, so we shouldn't
|
||||
// re-run too often.
|
||||
|
@ -77,4 +76,5 @@ int ControlFlowAnalysisPass::Run(HIRBuilder* builder) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
@ -28,6 +29,7 @@ class ControlFlowAnalysisPass : public CompilerPass {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
|
@ -7,22 +7,23 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/control_flow_simplification_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/control_flow_simplification_pass.h"
|
||||
|
||||
#include "alloy/backend/backend.h"
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::Edge;
|
||||
using alloy::hir::HIRBuilder;
|
||||
using xe::cpu::hir::Edge;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
|
||||
ControlFlowSimplificationPass::ControlFlowSimplificationPass()
|
||||
: CompilerPass() {}
|
||||
|
@ -30,8 +31,6 @@ ControlFlowSimplificationPass::ControlFlowSimplificationPass()
|
|||
ControlFlowSimplificationPass::~ControlFlowSimplificationPass() {}
|
||||
|
||||
int ControlFlowSimplificationPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Walk backwards and merge blocks if possible.
|
||||
bool merged_any = false;
|
||||
auto block = builder->last_block();
|
||||
|
@ -58,4 +57,5 @@ int ControlFlowSimplificationPass::Run(HIRBuilder* builder) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
@ -28,6 +29,7 @@ class ControlFlowSimplificationPass : public CompilerPass {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
|
@ -7,11 +7,11 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/data_flow_analysis_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/data_flow_analysis_pass.h"
|
||||
|
||||
#include "alloy/backend/backend.h"
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
#if XE_COMPILER_MSVC
|
||||
|
@ -24,24 +24,23 @@
|
|||
#include <llvm/ADT/BitVector.h>
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::OpcodeSignatureType;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::OpcodeSignatureType;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
DataFlowAnalysisPass::DataFlowAnalysisPass() : CompilerPass() {}
|
||||
|
||||
DataFlowAnalysisPass::~DataFlowAnalysisPass() {}
|
||||
|
||||
int DataFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Linearize blocks so that we can detect cycles and propagate dependencies.
|
||||
uint32_t block_count = LinearizeBlocks(builder);
|
||||
|
||||
|
@ -94,10 +93,10 @@ void DataFlowAnalysisPass::AnalyzeFlow(HIRBuilder* builder,
|
|||
auto instr = block->instr_head;
|
||||
while (instr) {
|
||||
uint32_t signature = instr->opcode->signature;
|
||||
#define SET_INCOMING_VALUE(v) \
|
||||
if (v->def && v->def->block != block) { \
|
||||
incoming_values.set(v->ordinal); \
|
||||
} \
|
||||
#define SET_INCOMING_VALUE(v) \
|
||||
if (v->def && v->def->block != block) { \
|
||||
incoming_values.set(v->ordinal); \
|
||||
} \
|
||||
assert_true(v->ordinal < max_value_estimate); \
|
||||
value_map[v->ordinal] = v;
|
||||
if (GET_OPCODE_SIG_TYPE_SRC1(signature) == OPCODE_SIG_TYPE_V) {
|
||||
|
@ -208,4 +207,5 @@ void DataFlowAnalysisPass::AnalyzeFlow(HIRBuilder* builder,
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,33 +7,31 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
||||
class DataFlowAnalysisPass : public CompilerPass {
|
||||
public:
|
||||
public:
|
||||
DataFlowAnalysisPass();
|
||||
~DataFlowAnalysisPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
private:
|
||||
uint32_t LinearizeBlocks(hir::HIRBuilder* builder);
|
||||
void AnalyzeFlow(hir::HIRBuilder* builder, uint32_t block_count);
|
||||
};
|
||||
|
||||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
|
@ -7,28 +7,27 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/dead_code_elimination_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/dead_code_elimination_pass.h"
|
||||
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::Instr;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::Instr;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
DeadCodeEliminationPass::DeadCodeEliminationPass() : CompilerPass() {}
|
||||
|
||||
DeadCodeEliminationPass::~DeadCodeEliminationPass() {}
|
||||
|
||||
int DeadCodeEliminationPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// ContextPromotion/DSE will likely leave around a lot of dead statements.
|
||||
// Code generated for comparison/testing produces many unused statements and
|
||||
// with proper use analysis it should be possible to remove most of them:
|
||||
|
@ -215,4 +214,5 @@ bool DeadCodeEliminationPass::CheckLocalUse(Instr* i) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,34 +7,32 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
||||
class DeadCodeEliminationPass : public CompilerPass {
|
||||
public:
|
||||
public:
|
||||
DeadCodeEliminationPass();
|
||||
~DeadCodeEliminationPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
private:
|
||||
void MakeNopRecursive(hir::Instr* i);
|
||||
void ReplaceAssignment(hir::Instr* i);
|
||||
bool CheckLocalUse(hir::Instr* i);
|
||||
};
|
||||
|
||||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
|
@ -7,29 +7,28 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/finalization_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/finalization_pass.h"
|
||||
|
||||
#include "alloy/backend/backend.h"
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
|
||||
FinalizationPass::FinalizationPass() : CompilerPass() {}
|
||||
|
||||
FinalizationPass::~FinalizationPass() {}
|
||||
|
||||
int FinalizationPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Process the HIR and prepare it for lowering.
|
||||
// After this is done the HIR should be ready for emitting.
|
||||
|
||||
|
@ -71,4 +70,5 @@ int FinalizationPass::Run(HIRBuilder* builder) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_FINALIZATION_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_FINALIZATION_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_FINALIZATION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_FINALIZATION_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
@ -28,6 +29,7 @@ class FinalizationPass : public CompilerPass {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_FINALIZATION_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_FINALIZATION_PASS_H_
|
|
@ -7,26 +7,27 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/register_allocation_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/register_allocation_pass.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::backend::MachineInfo;
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::Instr;
|
||||
using alloy::hir::OpcodeSignatureType;
|
||||
using alloy::hir::RegAssignment;
|
||||
using alloy::hir::TypeName;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::backend::MachineInfo;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::Instr;
|
||||
using xe::cpu::hir::OpcodeSignatureType;
|
||||
using xe::cpu::hir::RegAssignment;
|
||||
using xe::cpu::hir::TypeName;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
#define ASSERT_NO_CYCLES 0
|
||||
|
||||
|
@ -66,8 +67,6 @@ RegisterAllocationPass::~RegisterAllocationPass() {
|
|||
}
|
||||
|
||||
int RegisterAllocationPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Simple per-block allocator that operates on SSA form.
|
||||
// Registers do not move across blocks, though this could be
|
||||
// optimized with some intra-block analysis (dominators/etc).
|
||||
|
@ -561,4 +560,5 @@ void RegisterAllocationPass::SortUsageList(Value* value) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,17 +7,18 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
|
||||
#include "alloy/backend/machine_info.h"
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/backend/machine_info.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
@ -80,6 +81,7 @@ class RegisterAllocationPass : public CompilerPass {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
|
@ -7,28 +7,27 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/simplification_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/simplification_pass.h"
|
||||
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::Instr;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::Instr;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
SimplificationPass::SimplificationPass() : CompilerPass() {}
|
||||
|
||||
SimplificationPass::~SimplificationPass() {}
|
||||
|
||||
int SimplificationPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
EliminateConversions(builder);
|
||||
SimplifyAssignments(builder);
|
||||
return 0;
|
||||
|
@ -170,4 +169,5 @@ Value* SimplificationPass::CheckValue(Value* value) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
@ -34,6 +35,7 @@ class SimplificationPass : public CompilerPass {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
|
@ -7,33 +7,32 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/validation_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/validation_pass.h"
|
||||
|
||||
#include "alloy/backend/backend.h"
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::Block;
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::Instr;
|
||||
using alloy::hir::OpcodeSignatureType;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::Block;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::Instr;
|
||||
using xe::cpu::hir::OpcodeSignatureType;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
ValidationPass::ValidationPass() : CompilerPass() {}
|
||||
|
||||
ValidationPass::~ValidationPass() {}
|
||||
|
||||
int ValidationPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
#if 0
|
||||
StringBuffer str;
|
||||
builder->Dump(&str);
|
||||
|
@ -115,4 +114,5 @@ int ValidationPass::ValidateValue(Block* block, Instr* instr, Value* value) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_VALIDATION_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_VALIDATION_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_VALIDATION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_VALIDATION_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
@ -30,6 +31,7 @@ class ValidationPass : public CompilerPass {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_VALIDATION_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_VALIDATION_PASS_H_
|
|
@ -7,11 +7,11 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/compiler/passes/value_reduction_pass.h"
|
||||
#include "xenia/cpu/compiler/passes/value_reduction_pass.h"
|
||||
|
||||
#include "alloy/backend/backend.h"
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
#if XE_COMPILER_MSVC
|
||||
|
@ -24,16 +24,17 @@
|
|||
#include <llvm/ADT/BitVector.h>
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::OpcodeInfo;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::HIRBuilder;
|
||||
using xe::cpu::hir::OpcodeInfo;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
ValueReductionPass::ValueReductionPass() : CompilerPass() {}
|
||||
|
||||
|
@ -57,8 +58,6 @@ void ValueReductionPass::ComputeLastUse(Value* value) {
|
|||
}
|
||||
|
||||
int ValueReductionPass::Run(HIRBuilder* builder) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Walk each block and reuse variable ordinals as much as possible.
|
||||
|
||||
llvm::BitVector ordinals(builder->max_value_ordinal());
|
||||
|
@ -144,4 +143,5 @@ int ValueReductionPass::Run(HIRBuilder* builder) {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
||||
#define ALLOY_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
||||
#ifndef XENIA_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
||||
#define XENIA_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
||||
|
||||
#include "alloy/compiler/compiler_pass.h"
|
||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace compiler {
|
||||
namespace passes {
|
||||
|
||||
|
@ -29,6 +30,7 @@ class ValueReductionPass : public CompilerPass {
|
|||
|
||||
} // namespace passes
|
||||
} // namespace compiler
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
||||
#endif // XENIA_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
|
@ -22,4 +22,13 @@ DECLARE_string(load_module_map);
|
|||
DECLARE_string(dump_path);
|
||||
DECLARE_bool(dump_module_map);
|
||||
|
||||
DECLARE_bool(debug);
|
||||
DECLARE_bool(always_disasm);
|
||||
|
||||
DECLARE_bool(validate_hir);
|
||||
|
||||
DECLARE_uint64(break_on_instruction);
|
||||
DECLARE_uint64(break_on_memory);
|
||||
DECLARE_bool(break_on_debugbreak);
|
||||
|
||||
#endif // XENIA_CPU_PRIVATE_H_
|
||||
|
|
|
@ -28,3 +28,25 @@ DEFINE_string(dump_path, "build/",
|
|||
DEFINE_bool(dump_module_bitcode, true,
|
||||
"Writes the module bitcode both before and after optimizations.");
|
||||
DEFINE_bool(dump_module_map, true, "Dumps the module symbol database.");
|
||||
|
||||
#if 0 && DEBUG
|
||||
#define DEFAULT_DEBUG_FLAG true
|
||||
#else
|
||||
#define DEFAULT_DEBUG_FLAG false
|
||||
#endif
|
||||
|
||||
DEFINE_bool(debug, DEFAULT_DEBUG_FLAG,
|
||||
"Allow debugging and retain debug information.");
|
||||
DEFINE_bool(
|
||||
always_disasm, false,
|
||||
"Always add debug info to functions, even when no debugger is attached.");
|
||||
|
||||
DEFINE_bool(validate_hir, false,
|
||||
"Perform validation checks on the HIR during compilation.");
|
||||
|
||||
// Breakpoints:
|
||||
DEFINE_uint64(break_on_instruction, 0,
|
||||
"int3 before the given guest address is executed.");
|
||||
DEFINE_uint64(break_on_memory, 0,
|
||||
"int3 on read/write to the given memory address.");
|
||||
DEFINE_bool(break_on_debugbreak, true, "int3 on JITed __debugbreak requests.");
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
#define XENIA_CPU_CPU_H_
|
||||
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/cpu/runtime/function.h"
|
||||
#include "xenia/cpu/runtime/module.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/cpu/runtime/thread_state.h"
|
||||
#include "xenia/cpu/xenon_runtime.h"
|
||||
#include "xenia/cpu/xenon_thread_state.h"
|
||||
#include "xenia/cpu/xex_module.h"
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/context_info.h"
|
||||
#include "xenia/cpu/frontend/context_info.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
|
||||
ContextInfo::ContextInfo(size_t size, uintptr_t thread_state_offset,
|
||||
|
@ -21,4 +22,5 @@ ContextInfo::ContextInfo(size_t size, uintptr_t thread_state_offset,
|
|||
ContextInfo::~ContextInfo() {}
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,13 +7,14 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_CONTEXT_INFO_H_
|
||||
#define ALLOY_FRONTEND_CONTEXT_INFO_H_
|
||||
#ifndef XENIA_FRONTEND_CONTEXT_INFO_H_
|
||||
#define XENIA_FRONTEND_CONTEXT_INFO_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
|
||||
class ContextInfo {
|
||||
|
@ -34,6 +35,7 @@ class ContextInfo {
|
|||
};
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_CONTEXT_INFO_H_
|
||||
#endif // XENIA_FRONTEND_CONTEXT_INFO_H_
|
|
@ -7,11 +7,12 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/frontend.h"
|
||||
#include "xenia/cpu/frontend/frontend.h"
|
||||
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
|
||||
Frontend::Frontend(runtime::Runtime* runtime) : runtime_(runtime) {}
|
||||
|
@ -23,4 +24,5 @@ Memory* Frontend::memory() const { return runtime_->memory(); }
|
|||
int Frontend::Initialize() { return 0; }
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,23 +7,26 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_FRONTEND_H_
|
||||
#define ALLOY_FRONTEND_FRONTEND_H_
|
||||
#ifndef XENIA_FRONTEND_FRONTEND_H_
|
||||
#define XENIA_FRONTEND_FRONTEND_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "alloy/frontend/context_info.h"
|
||||
#include "alloy/memory.h"
|
||||
#include "alloy/runtime/function.h"
|
||||
#include "alloy/runtime/symbol_info.h"
|
||||
#include "xenia/cpu/frontend/context_info.h"
|
||||
#include "xenia/memory.h"
|
||||
#include "xenia/cpu/runtime/function.h"
|
||||
#include "xenia/cpu/runtime/symbol_info.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace runtime {
|
||||
class Runtime;
|
||||
} // namespace runtime
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
|
||||
class Frontend {
|
||||
|
@ -48,6 +51,7 @@ class Frontend {
|
|||
};
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_FRONTEND_H_
|
||||
#endif // XENIA_FRONTEND_FRONTEND_H_
|
|
@ -7,11 +7,12 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_context.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -19,9 +20,7 @@ uint64_t ParseInt64(const char* value) {
|
|||
return std::strtoull(value, nullptr, 0);
|
||||
}
|
||||
|
||||
double ParseFloat64(const char* value) {
|
||||
return std::strtod(value, nullptr);
|
||||
}
|
||||
double ParseFloat64(const char* value) { return std::strtod(value, nullptr); }
|
||||
|
||||
vec128_t ParseVec128(const char* value) {
|
||||
vec128_t v;
|
||||
|
@ -85,4 +84,5 @@ bool PPCContext::CompareRegWithString(const char* name, const char* value,
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -0,0 +1,227 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 XENIA_FRONTEND_PPC_PPC_CONTEXT_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_CONTEXT_H_
|
||||
|
||||
#include "poly/poly.h"
|
||||
#include "poly/vec128.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace runtime {
|
||||
class Runtime;
|
||||
class ThreadState;
|
||||
} // namespace runtime
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
using vec128_t = poly::vec128_t;
|
||||
|
||||
// Map:
|
||||
// 0-31: GPR
|
||||
// 32-63: FPR
|
||||
// 64: LR
|
||||
// 65: CTR
|
||||
// 66: XER
|
||||
// 67: FPSCR
|
||||
// 68: VSCR
|
||||
// 69-76: CR0-7
|
||||
// 100: invalid
|
||||
// 128-256: VR
|
||||
|
||||
#pragma pack(push, 4)
|
||||
typedef struct alignas(64) PPCContext_s {
|
||||
// Must be stored at 0x0 for now.
|
||||
// TODO(benvanik): find a nice way to describe this to the JIT.
|
||||
runtime::ThreadState* thread_state;
|
||||
// TODO(benvanik): this is getting nasty. Must be here.
|
||||
uint8_t* membase;
|
||||
|
||||
// Most frequently used registers first.
|
||||
uint64_t r[32]; // General purpose registers
|
||||
uint64_t lr; // Link register
|
||||
uint64_t ctr; // Count register
|
||||
|
||||
// XER register
|
||||
// Split to make it easier to do individual updates.
|
||||
uint8_t xer_ca;
|
||||
uint8_t xer_ov;
|
||||
uint8_t xer_so;
|
||||
|
||||
// Condition registers
|
||||
// These are split to make it easier to do DCE on unused stores.
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr0_lt; // Negative (LT) - result is negative
|
||||
uint8_t cr0_gt; // Positive (GT) - result is positive (and not zero)
|
||||
uint8_t cr0_eq; // Zero (EQ) - result is zero or a stwcx/stdcx completed
|
||||
// successfully
|
||||
uint8_t cr0_so; // Summary Overflow (SO) - copy of XER[SO]
|
||||
};
|
||||
} cr0;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr1_fx; // FP exception summary - copy of FPSCR[FX]
|
||||
uint8_t cr1_fex; // FP enabled exception summary - copy of FPSCR[FEX]
|
||||
uint8_t
|
||||
cr1_vx; // FP invalid operation exception summary - copy of FPSCR[VX]
|
||||
uint8_t cr1_ox; // FP overflow exception - copy of FPSCR[OX]
|
||||
};
|
||||
} cr1;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr2_0;
|
||||
uint8_t cr2_1;
|
||||
uint8_t cr2_2;
|
||||
uint8_t cr2_3;
|
||||
};
|
||||
} cr2;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr3_0;
|
||||
uint8_t cr3_1;
|
||||
uint8_t cr3_2;
|
||||
uint8_t cr3_3;
|
||||
};
|
||||
} cr3;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr4_0;
|
||||
uint8_t cr4_1;
|
||||
uint8_t cr4_2;
|
||||
uint8_t cr4_3;
|
||||
};
|
||||
} cr4;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr5_0;
|
||||
uint8_t cr5_1;
|
||||
uint8_t cr5_2;
|
||||
uint8_t cr5_3;
|
||||
};
|
||||
} cr5;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr6_all_equal;
|
||||
uint8_t cr6_1;
|
||||
uint8_t cr6_none_equal;
|
||||
uint8_t cr6_3;
|
||||
};
|
||||
} cr6;
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t cr7_0;
|
||||
uint8_t cr7_1;
|
||||
uint8_t cr7_2;
|
||||
uint8_t cr7_3;
|
||||
};
|
||||
} cr7;
|
||||
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t rn : 2; // FP rounding control: 00 = nearest
|
||||
// 01 = toward zero
|
||||
// 10 = toward +infinity
|
||||
// 11 = toward -infinity
|
||||
uint32_t ni : 1; // Floating-point non-IEEE mode
|
||||
uint32_t xe : 1; // IEEE floating-point inexact exception enable
|
||||
uint32_t ze : 1; // IEEE floating-point zero divide exception enable
|
||||
uint32_t ue : 1; // IEEE floating-point underflow exception enable
|
||||
uint32_t oe : 1; // IEEE floating-point overflow exception enable
|
||||
uint32_t ve : 1; // FP invalid op exception enable
|
||||
uint32_t vxcvi : 1; // FP invalid op exception: invalid integer convert
|
||||
// -- sticky
|
||||
uint32_t vxsqrt : 1; // FP invalid op exception: invalid sqrt -- sticky
|
||||
uint32_t vxsoft : 1; // FP invalid op exception: software request
|
||||
// -- sticky
|
||||
uint32_t reserved : 1;
|
||||
uint32_t fprf_un : 1; // FP result unordered or NaN (FU or ?)
|
||||
uint32_t fprf_eq : 1; // FP result equal or zero (FE or =)
|
||||
uint32_t fprf_gt : 1; // FP result greater than or positive (FG or >)
|
||||
uint32_t fprf_lt : 1; // FP result less than or negative (FL or <)
|
||||
uint32_t fprf_c : 1; // FP result class
|
||||
uint32_t fi : 1; // FP fraction inexact
|
||||
uint32_t fr : 1; // FP fraction rounded
|
||||
uint32_t vxvc : 1; // FP invalid op exception: invalid compare --
|
||||
// sticky
|
||||
uint32_t vximz : 1; // FP invalid op exception: infinity * 0 -- sticky
|
||||
uint32_t vxzdz : 1; // FP invalid op exception: 0 / 0 -- sticky
|
||||
uint32_t vxidi : 1; // FP invalid op exception: infinity / infinity
|
||||
// -- sticky
|
||||
uint32_t vxisi : 1; // FP invalid op exception: infinity - infinity
|
||||
// -- sticky
|
||||
uint32_t vxsnan : 1; // FP invalid op exception: SNaN -- sticky
|
||||
uint32_t
|
||||
xx : 1; // FP inexact exception -- sticky
|
||||
uint32_t
|
||||
zx : 1; // FP zero divide exception -- sticky
|
||||
uint32_t
|
||||
ux : 1; // FP underflow exception -- sticky
|
||||
uint32_t
|
||||
ox : 1; // FP overflow exception -- sticky
|
||||
uint32_t vx : 1; // FP invalid operation exception summary
|
||||
uint32_t fex : 1; // FP enabled exception summary
|
||||
uint32_t
|
||||
fx : 1; // FP exception summary -- sticky
|
||||
} bits;
|
||||
} fpscr; // Floating-point status and control register
|
||||
|
||||
uint8_t vscr_sat;
|
||||
|
||||
double f[32]; // Floating-point registers
|
||||
vec128_t v[128]; // VMX128 vector registers
|
||||
|
||||
// uint32_t get_fprf() {
|
||||
// return fpscr.value & 0x000F8000;
|
||||
// }
|
||||
// void set_fprf(const uint32_t v) {
|
||||
// fpscr.value = (fpscr.value & ~0x000F8000) | v;
|
||||
// }
|
||||
|
||||
// Thread ID assigned to this context.
|
||||
uint32_t thread_id;
|
||||
|
||||
// Reserve address for load acquire/store release. Shared.
|
||||
uint64_t* reserve_address;
|
||||
uint64_t* reserve_value;
|
||||
|
||||
// Used to shuttle data into externs. Contents volatile.
|
||||
uint64_t scratch;
|
||||
|
||||
// Runtime-specific data pointer. Used on callbacks to get access to the
|
||||
// current runtime and its data.
|
||||
runtime::Runtime* runtime;
|
||||
|
||||
void SetRegFromString(const char* name, const char* value);
|
||||
bool CompareRegWithString(const char* name, const char* value,
|
||||
char* out_value, size_t out_value_size);
|
||||
} PPCContext;
|
||||
#pragma pack(pop)
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_CONTEXT_H_
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_disasm.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_disasm.h"
|
||||
|
||||
#include "poly/poly.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -62,41 +63,41 @@ void Disasm_X_FRT_RA0_RB(InstrData& i, poly::StringBuffer* str) {
|
|||
}
|
||||
void Disasm_D_RT_RA_I(InstrData& i, poly::StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
void Disasm_D_RT_RA0_I(InstrData& i, poly::StringBuffer* str) {
|
||||
if (i.D.RA) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
} else {
|
||||
str->Append("%-8s r%d, 0, %d", i.type->name, i.D.RT,
|
||||
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
}
|
||||
void Disasm_D_FRT_RA_I(InstrData& i, poly::StringBuffer* str) {
|
||||
str->Append("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
void Disasm_D_FRT_RA0_I(InstrData& i, poly::StringBuffer* str) {
|
||||
if (i.D.RA) {
|
||||
str->Append("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
} else {
|
||||
str->Append("%-8s f%d, 0, %d", i.type->name, i.D.RT,
|
||||
(int32_t)(int16_t)XEEXTS16(i.D.DS));
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
}
|
||||
void Disasm_DS_RT_RA_I(InstrData& i, poly::StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||
(int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
}
|
||||
void Disasm_DS_RT_RA0_I(InstrData& i, poly::StringBuffer* str) {
|
||||
if (i.DS.RA) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||
(int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
} else {
|
||||
str->Append("%-8s r%d, 0, %d", i.type->name, i.DS.RT,
|
||||
(int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
}
|
||||
}
|
||||
void Disasm_D_RA(InstrData& i, poly::StringBuffer* str) {
|
||||
|
@ -500,4 +501,5 @@ int DisasmPPC(InstrData& i, poly::StringBuffer* str) {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,13 +7,14 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_DISASM_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_DISASM_H_
|
||||
#ifndef XENIA_FRONTEND_PPC_PPC_DISASM_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_DISASM_H_
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_instr.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_instr.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -21,6 +22,7 @@ int DisasmPPC(InstrData& i, poly::StringBuffer* str);
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_DISASM_H_
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_DISASM_H_
|
|
@ -7,13 +7,14 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_EMIT_PRIVATE_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_EMIT_PRIVATE_H_
|
||||
#ifndef XENIA_FRONTEND_PPC_PPC_EMIT_PRIVATE_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_EMIT_PRIVATE_H_
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_emit.h"
|
||||
#include "alloy/frontend/ppc/ppc_instr.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_emit.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_instr.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -28,6 +29,7 @@ namespace ppc {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_EMIT_PRIVATE_H_
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_EMIT_PRIVATE_H_
|
|
@ -7,12 +7,13 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_EMIT_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_EMIT_H_
|
||||
#ifndef XENIA_FRONTEND_PPC_PPC_EMIT_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_EMIT_H_
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_instr.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_instr.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -24,6 +25,7 @@ void RegisterEmitCategoryMemory();
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_EMIT_H_
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_EMIT_H_
|
|
@ -7,23 +7,24 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_emit-private.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_emit-private.h"
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_context.h"
|
||||
#include "alloy/frontend/ppc/ppc_hir_builder.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_hir_builder.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
using poly::vec128b;
|
||||
using poly::vec128f;
|
||||
using poly::vec128i;
|
||||
using poly::vec128s;
|
||||
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
Value* CalculateEA_0(PPCHIRBuilder& f, uint32_t ra, uint32_t rb);
|
||||
|
||||
|
@ -1462,8 +1463,8 @@ XEEMITTER(vsldoi128, VX128_5(4, 16), VX128_5)(PPCHIRBuilder& f, InstrData& i) {
|
|||
int InstrEmit_vslo_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||
// (VD) <- (VA) << (VB.b[F] & 0x78) (by octet)
|
||||
// TODO(benvanik): flag for shift-by-octet as optimization.
|
||||
Value* sh =
|
||||
f.And(f.Extract(f.LoadVR(vb), 15, INT8_TYPE), f.LoadConstant(int8_t(0x78)));
|
||||
Value* sh = f.And(f.Extract(f.LoadVR(vb), 15, INT8_TYPE),
|
||||
f.LoadConstant(int8_t(0x78)));
|
||||
Value* v = f.Permute(f.LoadVectorShl(sh), f.LoadVR(va),
|
||||
f.LoadZero(VEC128_TYPE), INT8_TYPE);
|
||||
f.StoreVR(vd, v);
|
||||
|
@ -1761,7 +1762,8 @@ XEEMITTER(vpkpx, 0x1000030E, VX)(PPCHIRBuilder& f, InstrData& i) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int InstrEmit_vpkshss_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||
int InstrEmit_vpkshss_(PPCHIRBuilder& f, uint32_t vd, uint32_t va,
|
||||
uint32_t vb) {
|
||||
// Vector Pack Signed Halfword Signed Saturate
|
||||
// Convert VA and VB from signed words to signed saturated bytes then
|
||||
// concat:
|
||||
|
@ -1781,7 +1783,8 @@ XEEMITTER(vpkshss128, VX128(5, 512), VX128)(PPCHIRBuilder& f, InstrData& i) {
|
|||
return InstrEmit_vpkshss_(f, VX128_VD128, VX128_VA128, VX128_VB128);
|
||||
}
|
||||
|
||||
int InstrEmit_vpkswss_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||
int InstrEmit_vpkswss_(PPCHIRBuilder& f, uint32_t vd, uint32_t va,
|
||||
uint32_t vb) {
|
||||
// Vector Pack Signed Word Signed Saturate
|
||||
// Convert VA and VB from signed int words to signed saturated shorts then
|
||||
// concat:
|
||||
|
@ -1801,7 +1804,8 @@ XEEMITTER(vpkswss128, VX128(5, 640), VX128)(PPCHIRBuilder& f, InstrData& i) {
|
|||
return InstrEmit_vpkswss_(f, VX128_VD128, VX128_VA128, VX128_VB128);
|
||||
}
|
||||
|
||||
int InstrEmit_vpkswus_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||
int InstrEmit_vpkswus_(PPCHIRBuilder& f, uint32_t vd, uint32_t va,
|
||||
uint32_t vb) {
|
||||
// Vector Pack Signed Word Unsigned Saturate
|
||||
// Convert VA and VB from signed int words to unsigned saturated shorts then
|
||||
// concat:
|
||||
|
@ -1821,7 +1825,8 @@ XEEMITTER(vpkswus128, VX128(5, 704), VX128)(PPCHIRBuilder& f, InstrData& i) {
|
|||
return InstrEmit_vpkswus_(f, VX128_VD128, VX128_VA128, VX128_VB128);
|
||||
}
|
||||
|
||||
int InstrEmit_vpkuhum_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||
int InstrEmit_vpkuhum_(PPCHIRBuilder& f, uint32_t vd, uint32_t va,
|
||||
uint32_t vb) {
|
||||
// Vector Pack Unsigned Halfword Unsigned Modulo
|
||||
// Convert VA and VB from unsigned shorts to unsigned bytes then concat:
|
||||
// for each i in VA + VB:
|
||||
|
@ -1840,7 +1845,8 @@ XEEMITTER(vpkuhum128, VX128(5, 768), VX128)(PPCHIRBuilder& f, InstrData& i) {
|
|||
return InstrEmit_vpkuhum_(f, VX128_VD128, VX128_VA128, VX128_VB128);
|
||||
}
|
||||
|
||||
int InstrEmit_vpkuhus_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||
int InstrEmit_vpkuhus_(PPCHIRBuilder& f, uint32_t vd, uint32_t va,
|
||||
uint32_t vb) {
|
||||
// Vector Pack Unsigned Halfword Unsigned Saturate
|
||||
// Convert VA and VB from unsigned shorts to unsigned saturated bytes then
|
||||
// concat:
|
||||
|
@ -1860,7 +1866,8 @@ XEEMITTER(vpkuhus128, VX128(5, 832), VX128)(PPCHIRBuilder& f, InstrData& i) {
|
|||
return InstrEmit_vpkuhus_(f, VX128_VD128, VX128_VA128, VX128_VB128);
|
||||
}
|
||||
|
||||
int InstrEmit_vpkshus_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||
int InstrEmit_vpkshus_(PPCHIRBuilder& f, uint32_t vd, uint32_t va,
|
||||
uint32_t vb) {
|
||||
// Vector Pack Signed Halfword Unsigned Saturate
|
||||
// Convert VA and VB from signed shorts to unsigned saturated bytes then
|
||||
// concat:
|
||||
|
@ -1880,7 +1887,8 @@ XEEMITTER(vpkshus128, VX128(5, 576), VX128)(PPCHIRBuilder& f, InstrData& i) {
|
|||
return InstrEmit_vpkshus_(f, VX128_VD128, VX128_VA128, VX128_VB128);
|
||||
}
|
||||
|
||||
int InstrEmit_vpkuwum_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||
int InstrEmit_vpkuwum_(PPCHIRBuilder& f, uint32_t vd, uint32_t va,
|
||||
uint32_t vb) {
|
||||
// Vector Pack Unsigned Word Unsigned Modulo
|
||||
// Concat low shorts from VA + VB:
|
||||
// for each i in VA + VB:
|
||||
|
@ -1899,7 +1907,8 @@ XEEMITTER(vpkuwum128, VX128(5, 896), VX128)(PPCHIRBuilder& f, InstrData& i) {
|
|||
return InstrEmit_vpkuwum_(f, VX128_VD128, VX128_VA128, VX128_VB128);
|
||||
}
|
||||
|
||||
int InstrEmit_vpkuwus_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||
int InstrEmit_vpkuwus_(PPCHIRBuilder& f, uint32_t vd, uint32_t va,
|
||||
uint32_t vb) {
|
||||
// Vector Pack Unsigned Word Unsigned Saturate
|
||||
// Convert VA and VB from unsigned int words to unsigned saturated shorts then
|
||||
// concat:
|
||||
|
@ -1989,7 +1998,8 @@ XEEMITTER(vupkhsb128, VX128(6, 896), VX128)(PPCHIRBuilder& f, InstrData& i) {
|
|||
int InstrEmit_vupklsb_(PPCHIRBuilder& f, uint32_t vd, uint32_t vb) {
|
||||
// Vector Unpack Low Signed Byte
|
||||
// bytes 8-15 expanded to halfwords 0-7 and sign extended
|
||||
Value* v = f.Unpack(f.LoadVR(vb), PACK_TYPE_TO_LO | PACK_TYPE_8_IN_16 |
|
||||
Value* v =
|
||||
f.Unpack(f.LoadVR(vb), PACK_TYPE_TO_LO | PACK_TYPE_8_IN_16 |
|
||||
PACK_TYPE_IN_SIGNED | PACK_TYPE_OUT_SIGNED);
|
||||
f.StoreVR(vd, v);
|
||||
return 0;
|
||||
|
@ -2400,4 +2410,5 @@ void RegisterEmitCategoryAltivec() {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,19 +7,20 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_emit-private.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_emit-private.h"
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_context.h"
|
||||
#include "alloy/frontend/ppc/ppc_hir_builder.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_hir_builder.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
// Integer arithmetic (A-3)
|
||||
|
||||
|
@ -1271,4 +1272,5 @@ void RegisterEmitCategoryALU() {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,20 +7,21 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_emit-private.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_emit-private.h"
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_context.h"
|
||||
#include "alloy/frontend/ppc/ppc_hir_builder.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_hir_builder.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::Label;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::Label;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
int InstrEmit_branch(PPCHIRBuilder& f, const char* src, uint64_t cia,
|
||||
Value* nia, bool lk, Value* cond = NULL,
|
||||
|
@ -749,4 +750,5 @@ void RegisterEmitCategoryControl() {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,20 +7,21 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_emit-private.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_emit-private.h"
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_context.h"
|
||||
#include "alloy/frontend/ppc/ppc_hir_builder.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_hir_builder.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::RoundMode;
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::RoundMode;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
// Good source of information:
|
||||
// http://mamedev.org/source/src/emu/cpu/powerpc/ppc_ops.c
|
||||
|
@ -257,7 +258,7 @@ XEEMITTER(fmsubsx, 0xEC000038, A)(PPCHIRBuilder& f, InstrData& i) {
|
|||
XEEMITTER(fnmaddx, 0xFC00003E, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||
// frD <- -([frA x frC] + frB)
|
||||
Value* v = f.Neg(
|
||||
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
|
||||
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
|
||||
f.StoreFPR(i.A.FRT, v);
|
||||
// f.UpdateFPRF(v);
|
||||
if (i.A.Rc) {
|
||||
|
@ -271,7 +272,7 @@ XEEMITTER(fnmaddx, 0xFC00003E, A)(PPCHIRBuilder& f, InstrData& i) {
|
|||
XEEMITTER(fnmaddsx, 0xEC00003E, A)(PPCHIRBuilder& f, InstrData& i) {
|
||||
// frD <- -([frA x frC] + frB)
|
||||
Value* v = f.Neg(
|
||||
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
|
||||
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
|
||||
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
|
||||
f.StoreFPR(i.A.FRT, v);
|
||||
// f.UpdateFPRF(v);
|
||||
|
@ -554,4 +555,5 @@ void RegisterEmitCategoryFPU() {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,19 +7,20 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_emit-private.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_emit-private.h"
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_context.h"
|
||||
#include "alloy/frontend/ppc/ppc_hir_builder.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_hir_builder.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::Value;
|
||||
using xe::cpu::hir::Value;
|
||||
|
||||
#define TRUNCATE_ADDRESSES 0
|
||||
|
||||
|
@ -1083,4 +1084,5 @@ void RegisterEmitCategoryMemory() {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,21 +7,22 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_frontend.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_frontend.h"
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_context.h"
|
||||
#include "alloy/frontend/ppc/ppc_disasm.h"
|
||||
#include "alloy/frontend/ppc/ppc_emit.h"
|
||||
#include "alloy/frontend/ppc/ppc_translator.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_disasm.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_emit.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_translator.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
using alloy::runtime::Function;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
using alloy::runtime::Runtime;
|
||||
using xe::cpu::runtime::Function;
|
||||
using xe::cpu::runtime::FunctionInfo;
|
||||
using xe::cpu::runtime::Runtime;
|
||||
|
||||
void InitializeIfNeeded();
|
||||
void CleanupOnShutdown();
|
||||
|
@ -103,16 +104,16 @@ int PPCFrontend::DeclareFunction(FunctionInfo* symbol_info) {
|
|||
}
|
||||
|
||||
int PPCFrontend::DefineFunction(FunctionInfo* symbol_info,
|
||||
uint32_t debug_info_flags,
|
||||
uint32_t trace_flags,
|
||||
uint32_t debug_info_flags, uint32_t trace_flags,
|
||||
Function** out_function) {
|
||||
PPCTranslator* translator = translator_pool_.Allocate(this);
|
||||
int result =
|
||||
translator->Translate(symbol_info, debug_info_flags, trace_flags, out_function);
|
||||
int result = translator->Translate(symbol_info, debug_info_flags, trace_flags,
|
||||
out_function);
|
||||
translator_pool_.Release(translator);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,15 +7,16 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_FRONTEND_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_FRONTEND_H_
|
||||
#ifndef XENIA_FRONTEND_PPC_PPC_FRONTEND_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_FRONTEND_H_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "alloy/frontend/frontend.h"
|
||||
#include "xenia/cpu/frontend/frontend.h"
|
||||
#include "poly/type_pool.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -49,6 +50,7 @@ class PPCFrontend : public Frontend {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_FRONTEND_H_
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_FRONTEND_H_
|
|
@ -7,29 +7,30 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_hir_builder.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_hir_builder.h"
|
||||
|
||||
#include "alloy/alloy-private.h"
|
||||
#include "alloy/frontend/ppc/ppc_context.h"
|
||||
#include "alloy/frontend/ppc/ppc_disasm.h"
|
||||
#include "alloy/frontend/ppc/ppc_frontend.h"
|
||||
#include "alloy/frontend/ppc/ppc_instr.h"
|
||||
#include "alloy/hir/label.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/cpu-private.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_disasm.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_frontend.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_instr.h"
|
||||
#include "xenia/cpu/hir/label.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace xe::cpu::hir;
|
||||
|
||||
using alloy::hir::Label;
|
||||
using alloy::hir::TypeName;
|
||||
using alloy::hir::Value;
|
||||
using alloy::runtime::Runtime;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
using xe::cpu::hir::Label;
|
||||
using xe::cpu::hir::TypeName;
|
||||
using xe::cpu::hir::Value;
|
||||
using xe::cpu::runtime::Runtime;
|
||||
using xe::cpu::runtime::FunctionInfo;
|
||||
|
||||
PPCHIRBuilder::PPCHIRBuilder(PPCFrontend* frontend)
|
||||
: HIRBuilder(), frontend_(frontend), comment_buffer_(4096) {}
|
||||
|
@ -45,7 +46,7 @@ void PPCHIRBuilder::Reset() {
|
|||
}
|
||||
|
||||
int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
Memory* memory = frontend_->memory();
|
||||
const uint8_t* p = memory->membase();
|
||||
|
@ -464,9 +465,8 @@ Value* PPCHIRBuilder::LoadAcquire(Value* address, TypeName type,
|
|||
Truncate(address, INT32_TYPE));
|
||||
Value* value = Load(address, type, load_flags);
|
||||
// Save the value so that we can compare it later in StoreRelease.
|
||||
AtomicExchange(
|
||||
LoadContext(offsetof(PPCContext, reserve_value), INT64_TYPE),
|
||||
value);
|
||||
AtomicExchange(LoadContext(offsetof(PPCContext, reserve_value), INT64_TYPE),
|
||||
value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -494,4 +494,5 @@ Value* PPCHIRBuilder::StoreRelease(Value* address, Value* value,
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,24 +7,25 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_HIR_BUILDER_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_HIR_BUILDER_H_
|
||||
#ifndef XENIA_FRONTEND_PPC_PPC_HIR_BUILDER_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_HIR_BUILDER_H_
|
||||
|
||||
#include "alloy/hir/hir_builder.h"
|
||||
#include "alloy/runtime/function.h"
|
||||
#include "alloy/runtime/symbol_info.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/runtime/function.h"
|
||||
#include "xenia/cpu/runtime/symbol_info.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
class PPCFrontend;
|
||||
|
||||
class PPCHIRBuilder : public hir::HIRBuilder {
|
||||
using Instr = alloy::hir::Instr;
|
||||
using Label = alloy::hir::Label;
|
||||
using Value = alloy::hir::Value;
|
||||
using Instr = xe::cpu::hir::Instr;
|
||||
using Label = xe::cpu::hir::Label;
|
||||
using Value = xe::cpu::hir::Value;
|
||||
|
||||
public:
|
||||
PPCHIRBuilder(PPCFrontend* frontend);
|
||||
|
@ -113,6 +114,7 @@ class PPCHIRBuilder : public hir::HIRBuilder {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_HIR_BUILDER_H_
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_HIR_BUILDER_H_
|
|
@ -7,16 +7,17 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_instr.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_instr.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_instr_tables.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_instr_tables.h"
|
||||
#include "poly/poly.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -75,14 +76,14 @@ void InstrOperand::Dump(std::string& out_str) {
|
|||
switch (imm.width) {
|
||||
case 1:
|
||||
if (imm.is_signed) {
|
||||
snprintf(buffer, max_count, "%d", (int32_t)(int8_t)imm.value);
|
||||
snprintf(buffer, max_count, "%d", (int32_t)(int8_t) imm.value);
|
||||
} else {
|
||||
snprintf(buffer, max_count, "0x%.2X", (uint8_t)imm.value);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (imm.is_signed) {
|
||||
snprintf(buffer, max_count, "%d", (int32_t)(int16_t)imm.value);
|
||||
snprintf(buffer, max_count, "%d", (int32_t)(int16_t) imm.value);
|
||||
} else {
|
||||
snprintf(buffer, max_count, "0x%.4X", (uint16_t)imm.value);
|
||||
}
|
||||
|
@ -403,4 +404,5 @@ int RegisterInstrEmit(uint32_t code, InstrEmitFn emit) {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,8 +7,8 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_INSTR_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_INSTR_H_
|
||||
#ifndef XENIA_FRONTEND_PPC_PPC_INSTR_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_INSTR_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
@ -16,7 +16,8 @@
|
|||
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -59,7 +60,7 @@ typedef enum {
|
|||
kXEPPCInstrFormatXDSS = 26,
|
||||
} xe_ppc_instr_format_e;
|
||||
|
||||
typedef enum : uint32_t {
|
||||
enum xe_ppc_instr_mask_e : uint32_t {
|
||||
kXEPPCInstrMaskVXR = 0xFC0003FF,
|
||||
kXEPPCInstrMaskVXA = 0xFC00003F,
|
||||
kXEPPCInstrMaskVX128 = 0xFC0003D0,
|
||||
|
@ -70,7 +71,7 @@ typedef enum : uint32_t {
|
|||
kXEPPCInstrMaskVX128_5 = 0xFC000010,
|
||||
kXEPPCInstrMaskVX128_P = 0xFC000630,
|
||||
kXEPPCInstrMaskVX128_R = 0xFC000390,
|
||||
} xe_ppc_instr_mask_e;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
kXEPPCInstrTypeGeneral = (1 << 0),
|
||||
|
@ -570,6 +571,7 @@ int RegisterInstrEmit(uint32_t code, InstrEmitFn emit);
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_INSTR_H_
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_INSTR_H_
|
|
@ -7,16 +7,17 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_INSTR_TABLES_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_INSTR_TABLES_H_
|
||||
#ifndef XENIA_FRONTEND_PPC_PPC_INSTR_TABLES_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_INSTR_TABLES_H_
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_instr.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_instr.h"
|
||||
#include "poly/poly.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -1095,6 +1096,7 @@ static InstrType instr_table_scan[] = {
|
|||
} // namespace tables
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_INSTR_TABLES_H_
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_INSTR_TABLES_H_
|
|
@ -7,14 +7,14 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_scanner.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_scanner.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_frontend.h"
|
||||
#include "alloy/frontend/ppc/ppc_instr.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_frontend.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_instr.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "poly/logging.h"
|
||||
#include "poly/memory.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
@ -25,11 +25,12 @@
|
|||
#define LOGPPC(fmt, ...) POLY_EMPTY_MACRO
|
||||
#endif
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
using alloy::runtime::FunctionInfo;
|
||||
using xe::cpu::runtime::FunctionInfo;
|
||||
|
||||
PPCScanner::PPCScanner(PPCFrontend* frontend) : frontend_(frontend) {}
|
||||
|
||||
|
@ -44,8 +45,6 @@ bool PPCScanner::IsRestGprLr(uint64_t address) {
|
|||
}
|
||||
|
||||
int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// This is a simple basic block analyizer. It walks the start address to the
|
||||
// end address looking for branches. Each span of instructions between
|
||||
// branches is considered a basic block. When the last blr (that has no
|
||||
|
@ -284,8 +283,6 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
|||
}
|
||||
|
||||
std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
Memory* memory = frontend_->memory();
|
||||
const uint8_t* p = memory->membase();
|
||||
|
||||
|
@ -364,4 +361,5 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,14 +7,15 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_SCANNER_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_SCANNER_H_
|
||||
#ifndef XENIA_FRONTEND_PPC_PPC_SCANNER_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_SCANNER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "alloy/runtime/symbol_info.h"
|
||||
#include "xenia/cpu/runtime/symbol_info.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -43,6 +44,7 @@ class PPCScanner {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_SCANNER_H_
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_SCANNER_H_
|
|
@ -7,31 +7,32 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "alloy/frontend/ppc/ppc_translator.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_translator.h"
|
||||
|
||||
#include "alloy/alloy-private.h"
|
||||
#include "alloy/compiler/compiler_passes.h"
|
||||
#include "alloy/frontend/ppc/ppc_disasm.h"
|
||||
#include "alloy/frontend/ppc/ppc_frontend.h"
|
||||
#include "alloy/frontend/ppc/ppc_hir_builder.h"
|
||||
#include "alloy/frontend/ppc/ppc_instr.h"
|
||||
#include "alloy/frontend/ppc/ppc_scanner.h"
|
||||
#include "alloy/runtime/runtime.h"
|
||||
#include "xenia/cpu/compiler/compiler_passes.h"
|
||||
#include "xenia/cpu/cpu-private.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_disasm.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_frontend.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_hir_builder.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_instr.h"
|
||||
#include "xenia/cpu/frontend/ppc/ppc_scanner.h"
|
||||
#include "xenia/cpu/runtime/runtime.h"
|
||||
#include "poly/reset_scope.h"
|
||||
#include "xenia/profiling.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::runtime;
|
||||
using namespace xe::cpu::runtime;
|
||||
|
||||
using alloy::backend::Backend;
|
||||
using alloy::compiler::Compiler;
|
||||
using alloy::runtime::Function;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
namespace passes = alloy::compiler::passes;
|
||||
using xe::cpu::backend::Backend;
|
||||
using xe::cpu::compiler::Compiler;
|
||||
using xe::cpu::runtime::Function;
|
||||
using xe::cpu::runtime::FunctionInfo;
|
||||
namespace passes = xe::cpu::compiler::passes;
|
||||
|
||||
PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) {
|
||||
Backend* backend = frontend->runtime()->backend();
|
||||
|
@ -88,7 +89,7 @@ PPCTranslator::~PPCTranslator() = default;
|
|||
int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
||||
uint32_t debug_info_flags, uint32_t trace_flags,
|
||||
Function** out_function) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Reset() all caching when we leave.
|
||||
poly::make_reset_scope(builder_);
|
||||
|
@ -125,7 +126,7 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
|||
}
|
||||
|
||||
if (false) {
|
||||
alloy::frontend::ppc::DumpAllInstrCounts();
|
||||
xe::cpu::frontend::ppc::DumpAllInstrCounts();
|
||||
}
|
||||
|
||||
// Emit function.
|
||||
|
@ -211,4 +212,5 @@ void PPCTranslator::DumpSource(runtime::FunctionInfo* symbol_info,
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -7,17 +7,18 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_FRONTEND_PPC_PPC_TRANSLATOR_H_
|
||||
#define ALLOY_FRONTEND_PPC_PPC_TRANSLATOR_H_
|
||||
#ifndef XENIA_FRONTEND_PPC_PPC_TRANSLATOR_H_
|
||||
#define XENIA_FRONTEND_PPC_PPC_TRANSLATOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "alloy/backend/assembler.h"
|
||||
#include "alloy/compiler/compiler.h"
|
||||
#include "alloy/runtime/symbol_info.h"
|
||||
#include "xenia/cpu/backend/assembler.h"
|
||||
#include "xenia/cpu/compiler/compiler.h"
|
||||
#include "xenia/cpu/runtime/symbol_info.h"
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
namespace alloy {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace frontend {
|
||||
namespace ppc {
|
||||
|
||||
|
@ -49,6 +50,7 @@ class PPCTranslator {
|
|||
|
||||
} // namespace ppc
|
||||
} // namespace frontend
|
||||
} // namespace alloy
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // ALLOY_FRONTEND_PPC_PPC_TRANSLATOR_H_
|
||||
#endif // XENIA_FRONTEND_PPC_PPC_TRANSLATOR_H_
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
/vagrant/src/alloy/frontend/ppc/test/bin//instr_add.o: file format elf64-powerpc
|
||||
/vagrant/src/xenia/cpu/frontend/ppc/test/bin//instr_add.o: file format elf64-powerpc
|
||||
|
||||
|
||||
Disassembly of section .text:
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue