Initial Alloy implementation.
This is a regression in functionality and performance, but a much better foundation for the future of the project (I think). It can run basic apps under an SSA interpreter but doesn't support some of the features required to do real 360 apps yet.
This commit is contained in:
13
src/alloy/hir/block.cc
Normal file
13
src/alloy/hir/block.cc
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/hir/block.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
40
src/alloy/hir/block.h
Normal file
40
src/alloy/hir/block.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_HIR_BLOCK_H_
|
||||
#define ALLOY_HIR_BLOCK_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace hir {
|
||||
|
||||
class Instr;
|
||||
class Label;
|
||||
|
||||
|
||||
class Block {
|
||||
public:
|
||||
Block* next;
|
||||
Block* prev;
|
||||
|
||||
Label* label_head;
|
||||
Label* label_tail;
|
||||
|
||||
Instr* instr_head;
|
||||
Instr* instr_tail;
|
||||
};
|
||||
|
||||
|
||||
} // namespace hir
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_HIR_BLOCK_H_
|
||||
2110
src/alloy/hir/function_builder.cc
Normal file
2110
src/alloy/hir/function_builder.cc
Normal file
File diff suppressed because it is too large
Load Diff
225
src/alloy/hir/function_builder.h
Normal file
225
src/alloy/hir/function_builder.h
Normal file
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_HIR_FUNCTION_BUILDER_H_
|
||||
#define ALLOY_HIR_FUNCTION_BUILDER_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
#include <alloy/hir/block.h>
|
||||
#include <alloy/hir/instr.h>
|
||||
#include <alloy/hir/opcodes.h>
|
||||
#include <alloy/hir/value.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace hir {
|
||||
|
||||
enum FunctionAttributes {
|
||||
FUNCTION_ATTRIB_INLINE = (1 << 1),
|
||||
};
|
||||
|
||||
|
||||
class FunctionBuilder {
|
||||
public:
|
||||
FunctionBuilder();
|
||||
virtual ~FunctionBuilder();
|
||||
|
||||
virtual void Reset();
|
||||
|
||||
void Dump(StringBuffer* str);
|
||||
|
||||
uint32_t attributes() const { return attributes_; }
|
||||
void set_attributes(uint32_t value) { attributes_ = value; }
|
||||
|
||||
Block* first_block() const { return block_head_; }
|
||||
Block* current_block() const;
|
||||
Instr* last_instr() const;
|
||||
|
||||
Label* NewLabel();
|
||||
void MarkLabel(Label* label);
|
||||
void InsertLabel(Label* label, Instr* prev_instr);
|
||||
|
||||
// static allocations:
|
||||
// Value* AllocStatic(size_t length);
|
||||
|
||||
// stack allocations:
|
||||
// Value* AllocLocal(TypeName type);
|
||||
|
||||
void Comment(const char* format, ...);
|
||||
|
||||
void Nop();
|
||||
|
||||
// trace info/etc
|
||||
void DebugBreak();
|
||||
void DebugBreakTrue(Value* cond);
|
||||
|
||||
void Trap();
|
||||
void TrapTrue(Value* cond);
|
||||
|
||||
void Call(runtime::FunctionInfo* symbol_info, uint32_t call_flags = 0);
|
||||
void CallTrue(Value* cond, runtime::FunctionInfo* symbol_info,
|
||||
uint32_t call_flags = 0);
|
||||
void CallIndirect(Value* value, uint32_t call_flags = 0);
|
||||
void CallIndirectTrue(Value* cond, Value* value, uint32_t call_flags = 0);
|
||||
void Return();
|
||||
|
||||
void Branch(Label* label, uint32_t branch_flags = 0);
|
||||
void BranchIf(Value* cond, Label* true_label, Label* false_label,
|
||||
uint32_t branch_flags = 0);
|
||||
void BranchTrue(Value* cond, Label* label,
|
||||
uint32_t branch_flags = 0);
|
||||
void BranchFalse(Value* cond, Label* label,
|
||||
uint32_t branch_flags = 0);
|
||||
|
||||
// phi type_name, Block* b1, Value* v1, Block* b2, Value* v2, etc
|
||||
|
||||
Value* Assign(Value* value);
|
||||
Value* Cast(Value* value, TypeName target_type);
|
||||
Value* ZeroExtend(Value* value, TypeName target_type);
|
||||
Value* SignExtend(Value* value, TypeName target_type);
|
||||
Value* Truncate(Value* value, TypeName target_type);
|
||||
Value* Convert(Value* value, TypeName target_type,
|
||||
RoundMode round_mode = ROUND_TO_ZERO);
|
||||
Value* Round(Value* value, RoundMode round_mode);
|
||||
|
||||
// TODO(benvanik): make this cleaner -- not happy with it.
|
||||
// It'd be nice if Convert() supported this, however then we'd need a
|
||||
// VEC128_INT32_TYPE or something.
|
||||
Value* VectorConvertI2F(Value* value);
|
||||
Value* VectorConvertF2I(Value* value, RoundMode round_mode = ROUND_TO_ZERO);
|
||||
|
||||
Value* LoadZero(TypeName type);
|
||||
Value* LoadConstant(int8_t value);
|
||||
Value* LoadConstant(uint8_t value);
|
||||
Value* LoadConstant(int16_t value);
|
||||
Value* LoadConstant(uint16_t value);
|
||||
Value* LoadConstant(int32_t value);
|
||||
Value* LoadConstant(uint32_t value);
|
||||
Value* LoadConstant(int64_t value);
|
||||
Value* LoadConstant(uint64_t value);
|
||||
Value* LoadConstant(float value);
|
||||
Value* LoadConstant(double value);
|
||||
Value* LoadConstant(const vec128_t& value);
|
||||
|
||||
Value* LoadContext(size_t offset, TypeName type);
|
||||
void StoreContext(size_t offset, Value* value);
|
||||
|
||||
Value* Load(Value* address, TypeName type, uint32_t load_flags = 0);
|
||||
Value* LoadAcquire(Value* address, TypeName type, uint32_t load_flags = 0);
|
||||
void Store(Value* address, Value* value, uint32_t store_flags = 0);
|
||||
Value* StoreRelease(Value* address, Value* value, uint32_t store_flags = 0);
|
||||
void Prefetch(Value* address, size_t length, uint32_t prefetch_flags = 0);
|
||||
|
||||
Value* Max(Value* value1, Value* value2);
|
||||
Value* Min(Value* value1, Value* value2);
|
||||
Value* Select(Value* cond, Value* value1, Value* value2);
|
||||
Value* IsTrue(Value* value);
|
||||
Value* IsFalse(Value* value);
|
||||
Value* CompareEQ(Value* value1, Value* value2);
|
||||
Value* CompareNE(Value* value1, Value* value2);
|
||||
Value* CompareSLT(Value* value1, Value* value2);
|
||||
Value* CompareSLE(Value* value1, Value* value2);
|
||||
Value* CompareSGT(Value* value1, Value* value2);
|
||||
Value* CompareSGE(Value* value1, Value* value2);
|
||||
Value* CompareULT(Value* value1, Value* value2);
|
||||
Value* CompareULE(Value* value1, Value* value2);
|
||||
Value* CompareUGT(Value* value1, Value* value2);
|
||||
Value* CompareUGE(Value* value1, Value* value2);
|
||||
Value* DidCarry(Value* value);
|
||||
Value* DidOverflow(Value* value);
|
||||
Value* VectorCompareEQ(Value* value1, Value* value2, TypeName part_type);
|
||||
Value* VectorCompareSGT(Value* value1, Value* value2, TypeName part_type);
|
||||
Value* VectorCompareSGE(Value* value1, Value* value2, TypeName part_type);
|
||||
Value* VectorCompareUGT(Value* value1, Value* value2, TypeName part_type);
|
||||
Value* VectorCompareUGE(Value* value1, Value* value2, TypeName part_type);
|
||||
|
||||
Value* Add(Value* value1, Value* value2, uint32_t arithmetic_flags = 0);
|
||||
Value* AddWithCarry(Value* value1, Value* value2, Value* value3,
|
||||
uint32_t arithmetic_flags = 0);
|
||||
Value* Sub(Value* value1, Value* value2,
|
||||
uint32_t arithmetic_flags = 0);
|
||||
Value* Mul(Value* value1, Value* value2);
|
||||
Value* Div(Value* value1, Value* value2);
|
||||
Value* Rem(Value* value1, Value* value2);
|
||||
Value* MulAdd(Value* value1, Value* value2, Value* value3); // (1 * 2) + 3
|
||||
Value* MulSub(Value* value1, Value* value2, Value* value3); // (1 * 2) - 3
|
||||
Value* Neg(Value* value);
|
||||
Value* Abs(Value* value);
|
||||
Value* Sqrt(Value* value);
|
||||
Value* RSqrt(Value* value);
|
||||
Value* DotProduct3(Value* value1, Value* value2);
|
||||
Value* DotProduct4(Value* value1, Value* value2);
|
||||
|
||||
Value* And(Value* value1, Value* value2);
|
||||
Value* Or(Value* value1, Value* value2);
|
||||
Value* Xor(Value* value1, Value* value2);
|
||||
Value* Not(Value* value);
|
||||
Value* Shl(Value* value1, Value* value2);
|
||||
Value* VectorShl(Value* value1, Value* value2, TypeName part_type);
|
||||
Value* Shl(Value* value1, int8_t value2);
|
||||
Value* Shr(Value* value1, Value* value2);
|
||||
Value* Shr(Value* value1, int8_t value2);
|
||||
Value* Sha(Value* value1, Value* value2);
|
||||
Value* Sha(Value* value1, int8_t value2);
|
||||
Value* RotateLeft(Value* value1, Value* value2);
|
||||
Value* ByteSwap(Value* value);
|
||||
Value* CountLeadingZeros(Value* value);
|
||||
Value* Insert(Value* value, uint32_t index, Value* part);
|
||||
Value* Extract(Value* value, uint32_t index, TypeName target_type);
|
||||
// i8->i16/i32/... (i8|i8 / i8|i8|i8|i8 / ...)
|
||||
// i8/i16/i32 -> vec128
|
||||
Value* Splat(Value* value, TypeName target_type);
|
||||
Value* Permute(Value* control, Value* value1, Value* value2,
|
||||
TypeName part_type);
|
||||
Value* Swizzle(Value* value, TypeName part_type, uint32_t swizzle_mask);
|
||||
// SelectBits(cond, value1, value2)
|
||||
// pack/unpack/etc
|
||||
|
||||
Value* CompareExchange(Value* address,
|
||||
Value* compare_value, Value* exchange_value);
|
||||
Value* AtomicAdd(Value* address, Value* value);
|
||||
Value* AtomicSub(Value* address, Value* value);
|
||||
|
||||
protected:
|
||||
void DumpValue(StringBuffer* str, Value* value);
|
||||
void DumpOp(
|
||||
StringBuffer* str, OpcodeSignatureType sig_type, Instr::Op* op);
|
||||
|
||||
Value* AllocValue(TypeName type = INT64_TYPE);
|
||||
Value* CloneValue(Value* source);
|
||||
|
||||
private:
|
||||
Block* AppendBlock();
|
||||
void EndBlock();
|
||||
Instr* AppendInstr(const OpcodeInfo& opcode, uint16_t flags,
|
||||
Value* dest = 0);
|
||||
Value* CompareXX(const OpcodeInfo& opcode, Value* value1, Value* value2);
|
||||
Value* VectorCompareXX(
|
||||
const OpcodeInfo& opcode, Value* value1, Value* value2, TypeName part_type);
|
||||
|
||||
protected:
|
||||
Arena* arena_;
|
||||
|
||||
private:
|
||||
uint32_t attributes_;
|
||||
|
||||
uint32_t next_label_id_;
|
||||
uint32_t next_value_ordinal_;
|
||||
|
||||
Block* block_head_;
|
||||
Block* block_tail_;
|
||||
Block* current_block_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace hir
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_HIR_FUNCTION_BUILDER_H_
|
||||
13
src/alloy/hir/instr.cc
Normal file
13
src/alloy/hir/instr.cc
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/hir/instr.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
55
src/alloy/hir/instr.h
Normal file
55
src/alloy/hir/instr.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_HIR_INSTR_H_
|
||||
#define ALLOY_HIR_INSTR_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
#include <alloy/hir/opcodes.h>
|
||||
#include <alloy/hir/value.h>
|
||||
|
||||
|
||||
namespace alloy { namespace runtime { class FunctionInfo; } }
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace hir {
|
||||
|
||||
class Block;
|
||||
class Label;
|
||||
|
||||
|
||||
class Instr {
|
||||
public:
|
||||
Block* block;
|
||||
Instr* next;
|
||||
Instr* prev;
|
||||
|
||||
const OpcodeInfo* opcode;
|
||||
uint16_t flags;
|
||||
|
||||
typedef union {
|
||||
runtime::FunctionInfo* symbol_info;
|
||||
Label* label;
|
||||
Value* value;
|
||||
uint64_t offset;
|
||||
} Op;
|
||||
|
||||
Value* dest;
|
||||
Op src1;
|
||||
Op src2;
|
||||
Op src3;
|
||||
};
|
||||
|
||||
|
||||
} // namespace hir
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_HIR_INSTR_H_
|
||||
13
src/alloy/hir/label.cc
Normal file
13
src/alloy/hir/label.cc
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/hir/label.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
39
src/alloy/hir/label.h
Normal file
39
src/alloy/hir/label.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_HIR_LABEL_H_
|
||||
#define ALLOY_HIR_LABEL_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace hir {
|
||||
|
||||
class Block;
|
||||
|
||||
|
||||
class Label {
|
||||
public:
|
||||
Block* block;
|
||||
Label* next;
|
||||
Label* prev;
|
||||
|
||||
uint32_t id;
|
||||
char* name;
|
||||
|
||||
void* tag;
|
||||
};
|
||||
|
||||
|
||||
} // namespace hir
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_HIR_LABEL_H_
|
||||
219
src/alloy/hir/opcodes.h
Normal file
219
src/alloy/hir/opcodes.h
Normal file
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_HIR_OPCODES_H_
|
||||
#define ALLOY_HIR_OPCODES_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace hir {
|
||||
|
||||
|
||||
enum CallFlags {
|
||||
CALL_TAIL = (1 << 1),
|
||||
};
|
||||
enum BranchFlags {
|
||||
BRANCH_LIKELY = (1 << 1),
|
||||
BRANCH_UNLIKELY = (1 << 2),
|
||||
};
|
||||
enum RoundMode {
|
||||
// to zero/nearest/etc
|
||||
ROUND_TO_ZERO = 0,
|
||||
ROUND_TO_NEAREST,
|
||||
};
|
||||
enum LoadFlags {
|
||||
LOAD_NO_ALIAS = (1 << 1),
|
||||
LOAD_ALIGNED = (1 << 2),
|
||||
LOAD_UNALIGNED = (1 << 3),
|
||||
LOAD_VOLATILE = (1 << 4),
|
||||
};
|
||||
enum StoreFlags {
|
||||
STORE_NO_ALIAS = (1 << 1),
|
||||
STORE_ALIGNED = (1 << 2),
|
||||
STORE_UNALIGNED = (1 << 3),
|
||||
STORE_VOLATILE = (1 << 4),
|
||||
};
|
||||
enum PrefetchFlags {
|
||||
PREFETCH_LOAD = (1 << 1),
|
||||
PREFETCH_STORE = (1 << 2),
|
||||
};
|
||||
enum ArithmeticFlags {
|
||||
ARITHMETIC_SET_CARRY = (1 << 1),
|
||||
};
|
||||
enum Permutes {
|
||||
PERMUTE_XY_ZW = 0x05040100,
|
||||
};
|
||||
enum Swizzles {
|
||||
SWIZZLE_XYZW_TO_XYZW = 0xE4,
|
||||
SWIZZLE_XYZW_TO_YZWX = 0x39,
|
||||
SWIZZLE_XYZW_TO_ZWXY = 0x4E,
|
||||
SWIZZLE_XYZW_TO_WXYZ = 0x93,
|
||||
};
|
||||
|
||||
|
||||
enum Opcode {
|
||||
OPCODE_COMMENT,
|
||||
|
||||
OPCODE_NOP,
|
||||
|
||||
OPCODE_DEBUG_BREAK,
|
||||
OPCODE_DEBUG_BREAK_TRUE,
|
||||
|
||||
OPCODE_TRAP,
|
||||
OPCODE_TRAP_TRUE,
|
||||
|
||||
OPCODE_CALL,
|
||||
OPCODE_CALL_TRUE,
|
||||
OPCODE_CALL_INDIRECT,
|
||||
OPCODE_CALL_INDIRECT_TRUE,
|
||||
OPCODE_RETURN,
|
||||
|
||||
OPCODE_BRANCH,
|
||||
OPCODE_BRANCH_IF,
|
||||
OPCODE_BRANCH_TRUE,
|
||||
OPCODE_BRANCH_FALSE,
|
||||
|
||||
OPCODE_ASSIGN,
|
||||
OPCODE_CAST,
|
||||
OPCODE_ZERO_EXTEND,
|
||||
OPCODE_SIGN_EXTEND,
|
||||
OPCODE_TRUNCATE,
|
||||
OPCODE_CONVERT,
|
||||
OPCODE_ROUND,
|
||||
OPCODE_VECTOR_CONVERT_I2F,
|
||||
OPCODE_VECTOR_CONVERT_F2I,
|
||||
|
||||
OPCODE_LOAD_CONTEXT,
|
||||
OPCODE_STORE_CONTEXT,
|
||||
|
||||
OPCODE_LOAD,
|
||||
OPCODE_LOAD_ACQUIRE,
|
||||
OPCODE_STORE,
|
||||
OPCODE_STORE_RELEASE,
|
||||
OPCODE_PREFETCH,
|
||||
|
||||
OPCODE_MAX,
|
||||
OPCODE_MIN,
|
||||
OPCODE_SELECT,
|
||||
OPCODE_IS_TRUE,
|
||||
OPCODE_IS_FALSE,
|
||||
OPCODE_COMPARE_EQ,
|
||||
OPCODE_COMPARE_NE,
|
||||
OPCODE_COMPARE_SLT,
|
||||
OPCODE_COMPARE_SLE,
|
||||
OPCODE_COMPARE_SGT,
|
||||
OPCODE_COMPARE_SGE,
|
||||
OPCODE_COMPARE_ULT,
|
||||
OPCODE_COMPARE_ULE,
|
||||
OPCODE_COMPARE_UGT,
|
||||
OPCODE_COMPARE_UGE,
|
||||
OPCODE_DID_CARRY,
|
||||
OPCODE_DID_OVERFLOW,
|
||||
OPCODE_VECTOR_COMPARE_EQ,
|
||||
OPCODE_VECTOR_COMPARE_SGT,
|
||||
OPCODE_VECTOR_COMPARE_SGE,
|
||||
OPCODE_VECTOR_COMPARE_UGT,
|
||||
OPCODE_VECTOR_COMPARE_UGE,
|
||||
|
||||
OPCODE_ADD,
|
||||
OPCODE_ADD_CARRY,
|
||||
OPCODE_SUB,
|
||||
OPCODE_MUL,
|
||||
OPCODE_DIV,
|
||||
OPCODE_REM,
|
||||
OPCODE_MULADD,
|
||||
OPCODE_MULSUB,
|
||||
OPCODE_NEG,
|
||||
OPCODE_ABS,
|
||||
OPCODE_SQRT,
|
||||
OPCODE_RSQRT,
|
||||
OPCODE_DOT_PRODUCT_3,
|
||||
OPCODE_DOT_PRODUCT_4,
|
||||
|
||||
OPCODE_AND,
|
||||
OPCODE_OR,
|
||||
OPCODE_XOR,
|
||||
OPCODE_NOT,
|
||||
OPCODE_SHL,
|
||||
OPCODE_VECTOR_SHL,
|
||||
OPCODE_SHR,
|
||||
OPCODE_SHA,
|
||||
OPCODE_ROTATE_LEFT,
|
||||
OPCODE_BYTE_SWAP,
|
||||
OPCODE_CNTLZ,
|
||||
OPCODE_INSERT,
|
||||
OPCODE_EXTRACT,
|
||||
OPCODE_SPLAT,
|
||||
OPCODE_PERMUTE,
|
||||
OPCODE_SWIZZLE,
|
||||
|
||||
OPCODE_COMPARE_EXCHANGE,
|
||||
OPCODE_ATOMIC_ADD,
|
||||
OPCODE_ATOMIC_SUB,
|
||||
};
|
||||
|
||||
enum OpcodeFlags {
|
||||
OPCODE_FLAG_BRANCH = (1 << 1),
|
||||
OPCODE_FLAG_MEMORY = (1 << 2),
|
||||
OPCODE_FLAG_COMMUNATIVE = (1 << 3),
|
||||
OPCODE_FLAG_VOLATILE = (1 << 4),
|
||||
OPCODE_FLAG_IGNORE = (1 << 5),
|
||||
};
|
||||
|
||||
enum OpcodeSignatureType {
|
||||
// 3 bits max (0-7)
|
||||
OPCODE_SIG_TYPE_X = 0,
|
||||
OPCODE_SIG_TYPE_L = 1,
|
||||
OPCODE_SIG_TYPE_O = 2,
|
||||
OPCODE_SIG_TYPE_S = 3,
|
||||
OPCODE_SIG_TYPE_V = 4,
|
||||
};
|
||||
|
||||
enum OpcodeSignature {
|
||||
OPCODE_SIG_X = (OPCODE_SIG_TYPE_X),
|
||||
OPCODE_SIG_X_L = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_L << 3),
|
||||
OPCODE_SIG_X_O_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_O << 3) | (OPCODE_SIG_TYPE_V << 6),
|
||||
OPCODE_SIG_X_S = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_S << 3),
|
||||
OPCODE_SIG_X_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3),
|
||||
OPCODE_SIG_X_V_L = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_L << 6),
|
||||
OPCODE_SIG_X_V_L_L = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_L << 6) | (OPCODE_SIG_TYPE_L << 9),
|
||||
OPCODE_SIG_X_V_O = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_O << 6),
|
||||
OPCODE_SIG_X_V_S = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_S << 6),
|
||||
OPCODE_SIG_X_V_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6),
|
||||
OPCODE_SIG_X_V_V_V = (OPCODE_SIG_TYPE_X) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6) | (OPCODE_SIG_TYPE_V << 9),
|
||||
OPCODE_SIG_V = (OPCODE_SIG_TYPE_V),
|
||||
OPCODE_SIG_V_O = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_O << 3),
|
||||
OPCODE_SIG_V_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3),
|
||||
OPCODE_SIG_V_V_O = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_O << 6),
|
||||
OPCODE_SIG_V_V_O_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_O << 6) | (OPCODE_SIG_TYPE_V << 9),
|
||||
OPCODE_SIG_V_V_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6),
|
||||
OPCODE_SIG_V_V_V_O = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6) | (OPCODE_SIG_TYPE_O << 9),
|
||||
OPCODE_SIG_V_V_V_V = (OPCODE_SIG_TYPE_V) | (OPCODE_SIG_TYPE_V << 3) | (OPCODE_SIG_TYPE_V << 6) | (OPCODE_SIG_TYPE_V << 9),
|
||||
};
|
||||
|
||||
#define GET_OPCODE_SIG_TYPE_DEST(sig) (OpcodeSignatureType)(sig & 0x7)
|
||||
#define GET_OPCODE_SIG_TYPE_SRC1(sig) (OpcodeSignatureType)((sig >> 3) & 0x7)
|
||||
#define GET_OPCODE_SIG_TYPE_SRC2(sig) (OpcodeSignatureType)((sig >> 6) & 0x7)
|
||||
#define GET_OPCODE_SIG_TYPE_SRC3(sig) (OpcodeSignatureType)((sig >> 9) & 0x7)
|
||||
|
||||
typedef struct {
|
||||
uint32_t flags;
|
||||
uint32_t signature;
|
||||
const char* name;
|
||||
Opcode num;
|
||||
} OpcodeInfo;
|
||||
|
||||
|
||||
} // namespace hir
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_HIR_OPCODES_H_
|
||||
17
src/alloy/hir/sources.gypi
Normal file
17
src/alloy/hir/sources.gypi
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'block.cc',
|
||||
'block.h',
|
||||
'function_builder.cc',
|
||||
'function_builder.h',
|
||||
'instr.cc',
|
||||
'instr.h',
|
||||
'label.cc',
|
||||
'label.h',
|
||||
'opcodes.h',
|
||||
'tracing.h',
|
||||
'value.cc',
|
||||
'value.h',
|
||||
],
|
||||
}
|
||||
35
src/alloy/hir/tracing.h
Normal file
35
src/alloy/hir/tracing.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_HIR_TRACING_H_
|
||||
#define ALLOY_HIR_TRACING_H_
|
||||
|
||||
#include <alloy/tracing/tracing.h>
|
||||
#include <alloy/tracing/event_type.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace hir {
|
||||
|
||||
const uint32_t ALLOY_HIR = alloy::tracing::EventType::ALLOY_HIR;
|
||||
|
||||
|
||||
class EventType {
|
||||
public:
|
||||
enum {
|
||||
ALLOY_HIR_FOO = ALLOY_HIR | (0),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace hir
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_HIR_TRACING_H_
|
||||
195
src/alloy/hir/value.cc
Normal file
195
src/alloy/hir/value.cc
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/hir/value.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
|
||||
|
||||
uint64_t Value::AsUint64() {
|
||||
XEASSERT(IsConstant());
|
||||
switch (type) {
|
||||
case INT8_TYPE:
|
||||
return constant.i8;
|
||||
case INT16_TYPE:
|
||||
return constant.i16;
|
||||
case INT32_TYPE:
|
||||
return constant.i32;
|
||||
case INT64_TYPE:
|
||||
return constant.i64;
|
||||
default:
|
||||
XEASSERTALWAYS();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Value::Cast(TypeName target_type) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::ZeroExtend(TypeName target_type) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::SignExtend(TypeName target_type) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Truncate(TypeName target_type) {
|
||||
switch (type) {
|
||||
case INT16_TYPE:
|
||||
switch (target_type) {
|
||||
case INT8_TYPE:
|
||||
type = target_type;
|
||||
constant.i64 = constant.i64 & 0xFF;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
switch (target_type) {
|
||||
case INT8_TYPE:
|
||||
type = target_type;
|
||||
constant.i64 = constant.i64 & 0xFF;
|
||||
return;
|
||||
case INT16_TYPE:
|
||||
type = target_type;
|
||||
constant.i64 = constant.i64 & 0xFFFF;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case INT64_TYPE:
|
||||
switch (target_type) {
|
||||
case INT8_TYPE:
|
||||
type = target_type;
|
||||
constant.i64 = constant.i64 & 0xFF;
|
||||
return;
|
||||
case INT16_TYPE:
|
||||
type = target_type;
|
||||
constant.i64 = constant.i64 & 0xFFFF;
|
||||
return;
|
||||
case INT32_TYPE:
|
||||
type = target_type;
|
||||
constant.i64 = constant.i64 & 0xFFFFFFFF;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Unsupported types.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Convert(TypeName target_type, RoundMode round_mode) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Round(RoundMode round_mode) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Add(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Sub(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Mul(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Div(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Rem(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::MulAdd(Value* dest, Value* value1, Value* value2, Value* value3) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::MulSub(Value* dest, Value* value1, Value* value2, Value* value3) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Neg() {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Abs() {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Sqrt() {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::And(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Or(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Xor(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Not() {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Shl(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Shr(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::Sha(Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
void Value::ByteSwap() {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
bool Value::Compare(Opcode opcode, Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
return false;
|
||||
}
|
||||
188
src/alloy/hir/value.h
Normal file
188
src/alloy/hir/value.h
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_HIR_VALUE_H_
|
||||
#define ALLOY_HIR_VALUE_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
#include <alloy/hir/opcodes.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace hir {
|
||||
|
||||
|
||||
enum TypeName {
|
||||
INT8_TYPE,
|
||||
INT16_TYPE,
|
||||
INT32_TYPE,
|
||||
INT64_TYPE,
|
||||
FLOAT32_TYPE,
|
||||
FLOAT64_TYPE,
|
||||
VEC128_TYPE,
|
||||
|
||||
MAX_TYPENAME,
|
||||
};
|
||||
|
||||
enum ValueFlags {
|
||||
VALUE_IS_CONSTANT = (1 << 1),
|
||||
};
|
||||
|
||||
|
||||
class Value {
|
||||
public:
|
||||
uint32_t ordinal;
|
||||
TypeName type;
|
||||
|
||||
uint32_t flags;
|
||||
union {
|
||||
int8_t i8;
|
||||
int16_t i16;
|
||||
int32_t i32;
|
||||
int64_t i64;
|
||||
float f32;
|
||||
double f64;
|
||||
vec128_t v128;
|
||||
} constant;
|
||||
|
||||
void* tag;
|
||||
|
||||
void set_zero(TypeName type) {
|
||||
this->type = type;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.v128.low = constant.v128.high = 0;
|
||||
}
|
||||
void set_constant(int8_t value) {
|
||||
type = INT8_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.i8 = value;
|
||||
}
|
||||
void set_constant(uint8_t value) {
|
||||
type = INT8_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.i8 = value;
|
||||
}
|
||||
void set_constant(int16_t value) {
|
||||
type = INT16_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.i16 = value;
|
||||
}
|
||||
void set_constant(uint16_t value) {
|
||||
type = INT16_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.i16 = value;
|
||||
}
|
||||
void set_constant(int32_t value) {
|
||||
type = INT32_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.i32 = value;
|
||||
}
|
||||
void set_constant(uint32_t value) {
|
||||
type = INT32_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.i32 = value;
|
||||
}
|
||||
void set_constant(int64_t value) {
|
||||
type = INT64_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.i64 = value;
|
||||
}
|
||||
void set_constant(uint64_t value) {
|
||||
type = INT64_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.i64 = value;
|
||||
}
|
||||
void set_constant(float value) {
|
||||
type = FLOAT32_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.f32 = value;
|
||||
}
|
||||
void set_constant(double value) {
|
||||
type = FLOAT64_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.f64 = value;
|
||||
}
|
||||
void set_constant(const vec128_t& value) {
|
||||
type = VEC128_TYPE;
|
||||
flags |= VALUE_IS_CONSTANT;
|
||||
constant.v128 = value;
|
||||
}
|
||||
|
||||
inline bool IsConstant() const {
|
||||
return !!(flags & VALUE_IS_CONSTANT);
|
||||
}
|
||||
bool IsConstantTrue() const {
|
||||
if (type == VEC128_TYPE) {
|
||||
return false;
|
||||
}
|
||||
return (flags & VALUE_IS_CONSTANT) && !!constant.i64;
|
||||
}
|
||||
bool IsConstantFalse() const {
|
||||
if (type == VEC128_TYPE) {
|
||||
return false;
|
||||
}
|
||||
return (flags & VALUE_IS_CONSTANT) && !constant.i64;
|
||||
}
|
||||
bool IsConstantZero() const {
|
||||
if (type == VEC128_TYPE) {
|
||||
return false;
|
||||
}
|
||||
return (flags & VALUE_IS_CONSTANT) && !constant.i64;
|
||||
}
|
||||
bool IsConstantEQ(Value* other) const {
|
||||
if (type == VEC128_TYPE) {
|
||||
return false;
|
||||
}
|
||||
return (flags & VALUE_IS_CONSTANT) &&
|
||||
(other->flags & VALUE_IS_CONSTANT) &&
|
||||
constant.i64 == other->constant.i64;
|
||||
}
|
||||
bool IsConstantNE(Value* other) const {
|
||||
if (type == VEC128_TYPE) {
|
||||
return false;
|
||||
}
|
||||
return (flags & VALUE_IS_CONSTANT) &&
|
||||
(other->flags & VALUE_IS_CONSTANT) &&
|
||||
constant.i64 != other->constant.i64;
|
||||
}
|
||||
uint64_t AsUint64();
|
||||
|
||||
void Cast(TypeName target_type);
|
||||
void ZeroExtend(TypeName target_type);
|
||||
void SignExtend(TypeName target_type);
|
||||
void Truncate(TypeName target_type);
|
||||
void Convert(TypeName target_type, RoundMode round_mode);
|
||||
void Round(RoundMode round_mode);
|
||||
void Add(Value* other);
|
||||
void Sub(Value* other);
|
||||
void Mul(Value* other);
|
||||
void Div(Value* other);
|
||||
void Rem(Value* other);
|
||||
static void MulAdd(Value* dest, Value* value1, Value* value2, Value* value3);
|
||||
static void MulSub(Value* dest, Value* value1, Value* value2, Value* value3);
|
||||
void Neg();
|
||||
void Abs();
|
||||
void Sqrt();
|
||||
void And(Value* other);
|
||||
void Or(Value* other);
|
||||
void Xor(Value* other);
|
||||
void Not();
|
||||
void Shl(Value* other);
|
||||
void Shr(Value* other);
|
||||
void Sha(Value* other);
|
||||
void ByteSwap();
|
||||
bool Compare(Opcode opcode, Value* other);
|
||||
};
|
||||
|
||||
|
||||
} // namespace hir
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_HIR_VALUE_H_
|
||||
Reference in New Issue
Block a user