Alloy now builds on clang.
Hopefully not just bouncing back to MSVC failures…
This commit is contained in:
parent
4cbd267a52
commit
19b6e90b63
|
@ -183,33 +183,37 @@ protected:
|
|||
|
||||
template <int TAG = -1>
|
||||
struct I8 : ValueOp<I8<TAG>, KEY_TYPE_V_I8, Reg8, int8_t, TAG> {
|
||||
typedef ValueOp<I8<TAG>, KEY_TYPE_V_I8, Reg8, int8_t, TAG> BASE;
|
||||
const int8_t constant() const {
|
||||
assert_true(is_constant);
|
||||
return value->constant.i8;
|
||||
assert_true(BASE::is_constant);
|
||||
return BASE::value->constant.i8;
|
||||
}
|
||||
};
|
||||
template <int TAG = -1>
|
||||
struct I16 : ValueOp<I16<TAG>, KEY_TYPE_V_I16, Reg16, int16_t, TAG> {
|
||||
typedef ValueOp<I16<TAG>, KEY_TYPE_V_I16, Reg16, int16_t, TAG> BASE;
|
||||
const int16_t constant() const {
|
||||
assert_true(is_constant);
|
||||
return value->constant.i16;
|
||||
assert_true(BASE::is_constant);
|
||||
return BASE::value->constant.i16;
|
||||
}
|
||||
};
|
||||
template <int TAG = -1>
|
||||
struct I32 : ValueOp<I32<TAG>, KEY_TYPE_V_I32, Reg32, int32_t, TAG> {
|
||||
typedef ValueOp<I32<TAG>, KEY_TYPE_V_I32, Reg32, int32_t, TAG> BASE;
|
||||
const int32_t constant() const {
|
||||
assert_true(is_constant);
|
||||
return value->constant.i32;
|
||||
assert_true(BASE::is_constant);
|
||||
return BASE::value->constant.i32;
|
||||
}
|
||||
};
|
||||
template <int TAG = -1>
|
||||
struct I64 : ValueOp<I64<TAG>, KEY_TYPE_V_I64, Reg64, int64_t, TAG> {
|
||||
typedef ValueOp<I64<TAG>, KEY_TYPE_V_I64, Reg64, int64_t, TAG> BASE;
|
||||
const int64_t constant() const {
|
||||
assert_true(is_constant);
|
||||
return value->constant.i64;
|
||||
assert_true(BASE::is_constant);
|
||||
return BASE::value->constant.i64;
|
||||
}
|
||||
bool ConstantFitsIn32Reg() const override {
|
||||
int64_t v = value->constant.i64;
|
||||
int64_t v = BASE::value->constant.i64;
|
||||
if ((v & ~0x7FFFFFFF) == 0) {
|
||||
// Fits under 31 bits, so just load using normal mov.
|
||||
return true;
|
||||
|
@ -222,23 +226,26 @@ struct I64 : ValueOp<I64<TAG>, KEY_TYPE_V_I64, Reg64, int64_t, TAG> {
|
|||
};
|
||||
template <int TAG = -1>
|
||||
struct F32 : ValueOp<F32<TAG>, KEY_TYPE_V_F32, Xmm, float, TAG> {
|
||||
typedef ValueOp<F32<TAG>, KEY_TYPE_V_F32, Xmm, float, TAG> BASE;
|
||||
const float constant() const {
|
||||
assert_true(is_constant);
|
||||
return value->constant.f32;
|
||||
assert_true(BASE::is_constant);
|
||||
return BASE::value->constant.f32;
|
||||
}
|
||||
};
|
||||
template <int TAG = -1>
|
||||
struct F64 : ValueOp<F64<TAG>, KEY_TYPE_V_F64, Xmm, double, TAG> {
|
||||
typedef ValueOp<F64<TAG>, KEY_TYPE_V_F64, Xmm, double, TAG> BASE;
|
||||
const double constant() const {
|
||||
assert_true(is_constant);
|
||||
return value->constant.f64;
|
||||
assert_true(BASE::is_constant);
|
||||
return BASE::value->constant.f64;
|
||||
}
|
||||
};
|
||||
template <int TAG = -1>
|
||||
struct V128 : ValueOp<V128<TAG>, KEY_TYPE_V_V128, Xmm, vec128_t, TAG> {
|
||||
typedef ValueOp<V128<TAG>, KEY_TYPE_V_V128, Xmm, vec128_t, TAG> BASE;
|
||||
const vec128_t& constant() const {
|
||||
assert_true(is_constant);
|
||||
return value->constant.v128;
|
||||
assert_true(BASE::is_constant);
|
||||
return BASE::value->constant.v128;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -308,6 +315,7 @@ template <hir::Opcode OPCODE, typename... Ts>
|
|||
struct I;
|
||||
template <hir::Opcode OPCODE, typename DEST>
|
||||
struct I<OPCODE, DEST> : DestField<DEST> {
|
||||
typedef DestField<DEST> BASE;
|
||||
static const hir::Opcode opcode = OPCODE;
|
||||
static const uint32_t key = InstrKey::Construct<OPCODE, DEST::key_type>::value;
|
||||
static const KeyType dest_type = DEST::key_type;
|
||||
|
@ -316,7 +324,7 @@ protected:
|
|||
template <typename... Ti> friend struct SequenceFields;
|
||||
bool Load(const Instr* i, TagTable& tag_table) {
|
||||
if (InstrKey(i).value == key &&
|
||||
LoadDest(i, tag_table)) {
|
||||
BASE::LoadDest(i, tag_table)) {
|
||||
instr = i;
|
||||
return true;
|
||||
}
|
||||
|
@ -325,6 +333,7 @@ protected:
|
|||
};
|
||||
template <hir::Opcode OPCODE, typename DEST, typename SRC1>
|
||||
struct I<OPCODE, DEST, SRC1> : DestField<DEST> {
|
||||
typedef DestField<DEST> BASE;
|
||||
static const hir::Opcode opcode = OPCODE;
|
||||
static const uint32_t key = InstrKey::Construct<OPCODE, DEST::key_type, SRC1::key_type>::value;
|
||||
static const KeyType dest_type = DEST::key_type;
|
||||
|
@ -335,7 +344,7 @@ protected:
|
|||
template <typename... Ti> friend struct SequenceFields;
|
||||
bool Load(const Instr* i, TagTable& tag_table) {
|
||||
if (InstrKey(i).value == key &&
|
||||
LoadDest(i, tag_table) &&
|
||||
BASE::LoadDest(i, tag_table) &&
|
||||
tag_table.CheckTag<SRC1>(i->src1)) {
|
||||
instr = i;
|
||||
src1.Load(i->src1);
|
||||
|
@ -346,6 +355,7 @@ protected:
|
|||
};
|
||||
template <hir::Opcode OPCODE, typename DEST, typename SRC1, typename SRC2>
|
||||
struct I<OPCODE, DEST, SRC1, SRC2> : DestField<DEST> {
|
||||
typedef DestField<DEST> BASE;
|
||||
static const hir::Opcode opcode = OPCODE;
|
||||
static const uint32_t key = InstrKey::Construct<OPCODE, DEST::key_type, SRC1::key_type, SRC2::key_type>::value;
|
||||
static const KeyType dest_type = DEST::key_type;
|
||||
|
@ -358,7 +368,7 @@ protected:
|
|||
template <typename... Ti> friend struct SequenceFields;
|
||||
bool Load(const Instr* i, TagTable& tag_table) {
|
||||
if (InstrKey(i).value == key &&
|
||||
LoadDest(i, tag_table) &&
|
||||
BASE::LoadDest(i, tag_table) &&
|
||||
tag_table.CheckTag<SRC1>(i->src1) &&
|
||||
tag_table.CheckTag<SRC2>(i->src2)) {
|
||||
instr = i;
|
||||
|
@ -371,6 +381,7 @@ protected:
|
|||
};
|
||||
template <hir::Opcode OPCODE, typename DEST, typename SRC1, typename SRC2, typename SRC3>
|
||||
struct I<OPCODE, DEST, SRC1, SRC2, SRC3> : DestField<DEST> {
|
||||
typedef DestField<DEST> BASE;
|
||||
static const hir::Opcode opcode = OPCODE;
|
||||
static const uint32_t key = InstrKey::Construct<OPCODE, DEST::key_type, SRC1::key_type, SRC2::key_type, SRC3::key_type>::value;
|
||||
static const KeyType dest_type = DEST::key_type;
|
||||
|
@ -385,7 +396,7 @@ protected:
|
|||
template <typename... Ti> friend struct SequenceFields;
|
||||
bool Load(const Instr* i, TagTable& tag_table) {
|
||||
if (InstrKey(i).value == key &&
|
||||
LoadDest(i, tag_table) &&
|
||||
BASE::LoadDest(i, tag_table) &&
|
||||
tag_table.CheckTag<SRC1>(i->src1) &&
|
||||
tag_table.CheckTag<SRC2>(i->src2) &&
|
||||
tag_table.CheckTag<SRC3>(i->src3)) {
|
||||
|
@ -404,7 +415,6 @@ struct SequenceFields;
|
|||
template <typename I1>
|
||||
struct SequenceFields<I1> {
|
||||
I1 i1;
|
||||
typedef typename I1 I1Type;
|
||||
protected:
|
||||
template <typename SEQ, typename... Ti> friend struct Sequence;
|
||||
bool Check(const Instr* i, TagTable& tag_table, const Instr** new_tail) {
|
||||
|
@ -516,9 +526,10 @@ const Reg64 GetTempReg<Reg64>(X64Emitter& e) {
|
|||
|
||||
template <typename SEQ, typename T>
|
||||
struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
||||
typedef Sequence<SingleSequence<SEQ, T>, T> BASE;
|
||||
typedef T EmitArgType;
|
||||
static const uint32_t head_key = T::key;
|
||||
static void Emit(X64Emitter& e, const EmitArgs& _) {
|
||||
static void Emit(X64Emitter& e, const typename BASE::EmitArgs& _) {
|
||||
SEQ::Emit(e, _.i1);
|
||||
}
|
||||
|
||||
|
@ -547,7 +558,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.src1.ConstantFitsIn32Reg()) {
|
||||
reg_const_fn(e, i.dest, static_cast<int32_t>(i.src1.constant()));
|
||||
} else {
|
||||
auto temp = GetTempReg<decltype(i.src1)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src1)::reg_type>(e);
|
||||
e.mov(temp, i.src1.constant());
|
||||
reg_reg_fn(e, i.dest, temp);
|
||||
}
|
||||
|
@ -560,7 +571,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.src2.ConstantFitsIn32Reg()) {
|
||||
reg_const_fn(e, i.dest, static_cast<int32_t>(i.src2.constant()));
|
||||
} else {
|
||||
auto temp = GetTempReg<decltype(i.src2)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src2)::reg_type>(e);
|
||||
e.mov(temp, i.src2.constant());
|
||||
reg_reg_fn(e, i.dest, temp);
|
||||
}
|
||||
|
@ -586,7 +597,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.src1.is_constant) {
|
||||
assert_true(!i.src2.is_constant);
|
||||
if (i.dest == i.src2) {
|
||||
auto temp = GetTempReg<decltype(i.src2)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src2)::reg_type>(e);
|
||||
e.mov(temp, i.src2);
|
||||
e.mov(i.dest, i.src1.constant());
|
||||
reg_reg_fn(e, i.dest, temp);
|
||||
|
@ -599,7 +610,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.src2.ConstantFitsIn32Reg()) {
|
||||
reg_const_fn(e, i.dest, static_cast<int32_t>(i.src2.constant()));
|
||||
} else {
|
||||
auto temp = GetTempReg<decltype(i.src2)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src2)::reg_type>(e);
|
||||
e.mov(temp, i.src2.constant());
|
||||
reg_reg_fn(e, i.dest, temp);
|
||||
}
|
||||
|
@ -608,7 +619,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.src2.ConstantFitsIn32Reg()) {
|
||||
reg_const_fn(e, i.dest, static_cast<int32_t>(i.src2.constant()));
|
||||
} else {
|
||||
auto temp = GetTempReg<decltype(i.src2)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src2)::reg_type>(e);
|
||||
e.mov(temp, i.src2.constant());
|
||||
reg_reg_fn(e, i.dest, temp);
|
||||
}
|
||||
|
@ -617,7 +628,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.dest == i.src1) {
|
||||
reg_reg_fn(e, i.dest, i.src2);
|
||||
} else if (i.dest == i.src2) {
|
||||
auto temp = GetTempReg<decltype(i.src2)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src2)::reg_type>(e);
|
||||
e.mov(temp, i.src2);
|
||||
e.mov(i.dest, i.src1);
|
||||
reg_reg_fn(e, i.dest, temp);
|
||||
|
@ -667,7 +678,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.src1.ConstantFitsIn32Reg()) {
|
||||
reg_const_fn(e, i.src2, static_cast<int32_t>(i.src1.constant()));
|
||||
} else {
|
||||
auto temp = GetTempReg<decltype(i.src1)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src1)::reg_type>(e);
|
||||
e.mov(temp, i.src1.constant());
|
||||
reg_reg_fn(e, i.src2, temp);
|
||||
}
|
||||
|
@ -675,7 +686,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.src2.ConstantFitsIn32Reg()) {
|
||||
reg_const_fn(e, i.src1, static_cast<int32_t>(i.src2.constant()));
|
||||
} else {
|
||||
auto temp = GetTempReg<decltype(i.src2)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src2)::reg_type>(e);
|
||||
e.mov(temp, i.src2.constant());
|
||||
reg_reg_fn(e, i.src1, temp);
|
||||
}
|
||||
|
@ -692,7 +703,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.src1.ConstantFitsIn32Reg()) {
|
||||
reg_const_fn(e, i.dest, i.src2, static_cast<int32_t>(i.src1.constant()), true);
|
||||
} else {
|
||||
auto temp = GetTempReg<decltype(i.src1)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src1)::reg_type>(e);
|
||||
e.mov(temp, i.src1.constant());
|
||||
reg_reg_fn(e, i.dest, i.src2, temp, true);
|
||||
}
|
||||
|
@ -700,7 +711,7 @@ struct SingleSequence : public Sequence<SingleSequence<SEQ, T>, T> {
|
|||
if (i.src2.ConstantFitsIn32Reg()) {
|
||||
reg_const_fn(e, i.dest, i.src1, static_cast<int32_t>(i.src2.constant()), false);
|
||||
} else {
|
||||
auto temp = GetTempReg<decltype(i.src2)::reg_type>(e);
|
||||
auto temp = GetTempReg<typename decltype(i.src2)::reg_type>(e);
|
||||
e.mov(temp, i.src2.constant());
|
||||
reg_reg_fn(e, i.dest, i.src1, temp, false);
|
||||
}
|
||||
|
@ -721,8 +732,6 @@ static const tag_t TAG5 = 5;
|
|||
static const tag_t TAG6 = 6;
|
||||
static const tag_t TAG7 = 7;
|
||||
|
||||
typedef bool (*SequenceSelectFn)(X64Emitter&, const Instr*, const Instr**);
|
||||
|
||||
template <typename T>
|
||||
void Register() {
|
||||
sequence_table.insert({ T::head_key, T::Select });
|
||||
|
|
|
@ -39,11 +39,12 @@ using namespace Xbyak;
|
|||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
|
||||
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>
|
||||
|
||||
std::unordered_multimap<uint32_t, SequenceSelectFn> sequence_table;
|
||||
|
||||
// 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,...)
|
||||
#define VEC128_B(n) ((n) ^ 0x3)
|
||||
|
@ -63,7 +64,7 @@ EMITTER(COMMENT, MATCH(I<OPCODE_COMMENT, VoidOp, OffsetOp>)) {
|
|||
// TODO(benvanik): don't just leak this memory.
|
||||
auto str_copy = strdup(str);
|
||||
e.mov(e.rdx, reinterpret_cast<uint64_t>(str_copy));
|
||||
e.CallNative(TraceString);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceString));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1104,12 +1105,7 @@ EMITTER(LOAD_CLOCK, MATCH(I<OPCODE_LOAD_CLOCK, I64<>>)) {
|
|||
e.mov(i.dest, e.rax);
|
||||
}
|
||||
static uint64_t LoadClock(void* raw_context) {
|
||||
LARGE_INTEGER counter;
|
||||
uint64_t time = 0;
|
||||
if (QueryPerformanceCounter(&counter)) {
|
||||
time = counter.QuadPart;
|
||||
}
|
||||
return time;
|
||||
return poly::threading::ticks();
|
||||
}
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(
|
||||
|
@ -1245,7 +1241,7 @@ EMITTER(LOAD_CONTEXT_I8, MATCH(I<OPCODE_LOAD_CONTEXT, I8<>, OffsetOp>)) {
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8, e.byte[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextLoadI8);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextLoadI8));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1256,7 +1252,7 @@ EMITTER(LOAD_CONTEXT_I16, MATCH(I<OPCODE_LOAD_CONTEXT, I16<>, OffsetOp>)) {
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8, e.word[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextLoadI16);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextLoadI16));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1267,7 +1263,7 @@ EMITTER(LOAD_CONTEXT_I32, MATCH(I<OPCODE_LOAD_CONTEXT, I32<>, OffsetOp>)) {
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8, e.dword[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextLoadI32);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextLoadI32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1278,7 +1274,7 @@ EMITTER(LOAD_CONTEXT_I64, MATCH(I<OPCODE_LOAD_CONTEXT, I64<>, OffsetOp>)) {
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8, e.qword[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextLoadI64);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextLoadI64));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1289,7 +1285,7 @@ EMITTER(LOAD_CONTEXT_F32, MATCH(I<OPCODE_LOAD_CONTEXT, F32<>, OffsetOp>)) {
|
|||
if (IsTracingData()) {
|
||||
e.lea(e.r8, e.dword[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextLoadF32);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextLoadF32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1300,7 +1296,7 @@ EMITTER(LOAD_CONTEXT_F64, MATCH(I<OPCODE_LOAD_CONTEXT, F64<>, OffsetOp>)) {
|
|||
if (IsTracingData()) {
|
||||
e.lea(e.r8, e.qword[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextLoadF64);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextLoadF64));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1311,7 +1307,7 @@ EMITTER(LOAD_CONTEXT_V128, MATCH(I<OPCODE_LOAD_CONTEXT, V128<>, OffsetOp>)) {
|
|||
if (IsTracingData()) {
|
||||
e.lea(e.r8, e.ptr[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextLoadV128);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextLoadV128));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1341,7 +1337,7 @@ EMITTER(STORE_CONTEXT_I8, MATCH(I<OPCODE_STORE_CONTEXT, VoidOp, OffsetOp, I8<>>)
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8, e.byte[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextStoreI8);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextStoreI8));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1356,7 +1352,7 @@ EMITTER(STORE_CONTEXT_I16, MATCH(I<OPCODE_STORE_CONTEXT, VoidOp, OffsetOp, I16<>
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8, e.word[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextStoreI16);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextStoreI16));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1371,7 +1367,7 @@ EMITTER(STORE_CONTEXT_I32, MATCH(I<OPCODE_STORE_CONTEXT, VoidOp, OffsetOp, I32<>
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8, e.dword[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextStoreI32);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextStoreI32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1386,7 +1382,7 @@ EMITTER(STORE_CONTEXT_I64, MATCH(I<OPCODE_STORE_CONTEXT, VoidOp, OffsetOp, I64<>
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8, e.qword[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextStoreI64);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextStoreI64));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1401,7 +1397,7 @@ EMITTER(STORE_CONTEXT_F32, MATCH(I<OPCODE_STORE_CONTEXT, VoidOp, OffsetOp, F32<>
|
|||
if (IsTracingData()) {
|
||||
e.lea(e.r8, e.dword[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextStoreF32);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextStoreF32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1416,7 +1412,7 @@ EMITTER(STORE_CONTEXT_F64, MATCH(I<OPCODE_STORE_CONTEXT, VoidOp, OffsetOp, F64<>
|
|||
if (IsTracingData()) {
|
||||
e.lea(e.r8, e.qword[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextStoreF64);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextStoreF64));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1432,7 +1428,7 @@ EMITTER(STORE_CONTEXT_V128, MATCH(I<OPCODE_STORE_CONTEXT, VoidOp, OffsetOp, V128
|
|||
if (IsTracingData()) {
|
||||
e.lea(e.r8, e.ptr[addr]);
|
||||
e.mov(e.rdx, i.src1.value);
|
||||
e.CallNative(TraceContextStoreV128);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceContextStoreV128));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1473,7 +1469,7 @@ EMITTER(LOAD_I8, MATCH(I<OPCODE_LOAD, I8<>, I64<>>)) {
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8b, i.dest);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryLoadI8);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryLoadI8));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1484,7 +1480,7 @@ EMITTER(LOAD_I16, MATCH(I<OPCODE_LOAD, I16<>, I64<>>)) {
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8w, i.dest);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryLoadI16);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryLoadI16));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1495,7 +1491,7 @@ EMITTER(LOAD_I32, MATCH(I<OPCODE_LOAD, I32<>, I64<>>)) {
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8d, i.dest);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryLoadI32);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryLoadI32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1506,7 +1502,7 @@ EMITTER(LOAD_I64, MATCH(I<OPCODE_LOAD, I64<>, I64<>>)) {
|
|||
if (IsTracingData()) {
|
||||
e.mov(e.r8, i.dest);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryLoadI64);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryLoadI64));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1517,7 +1513,7 @@ EMITTER(LOAD_F32, MATCH(I<OPCODE_LOAD, F32<>, I64<>>)) {
|
|||
if (IsTracingData()) {
|
||||
e.lea(e.r8, e.dword[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryLoadF32);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryLoadF32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1528,7 +1524,7 @@ EMITTER(LOAD_F64, MATCH(I<OPCODE_LOAD, F64<>, I64<>>)) {
|
|||
if (IsTracingData()) {
|
||||
e.lea(e.r8, e.qword[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryLoadF64);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryLoadF64));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1540,7 +1536,7 @@ EMITTER(LOAD_V128, MATCH(I<OPCODE_LOAD, V128<>, I64<>>)) {
|
|||
if (IsTracingData()) {
|
||||
e.lea(e.r8, e.ptr[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryLoadV128);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryLoadV128));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1578,7 +1574,7 @@ EMITTER(STORE_I8, MATCH(I<OPCODE_STORE, VoidOp, I64<>, I8<>>)) {
|
|||
auto addr = ComputeMemoryAddress(e, i.src1);
|
||||
e.mov(e.r8b, e.byte[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryStoreI8);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryStoreI8));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1595,7 +1591,7 @@ EMITTER(STORE_I16, MATCH(I<OPCODE_STORE, VoidOp, I64<>, I16<>>)) {
|
|||
auto addr = ComputeMemoryAddress(e, i.src1);
|
||||
e.mov(e.r8w, e.word[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryStoreI16);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryStoreI16));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1612,7 +1608,7 @@ EMITTER(STORE_I32, MATCH(I<OPCODE_STORE, VoidOp, I64<>, I32<>>)) {
|
|||
auto addr = ComputeMemoryAddress(e, i.src1);
|
||||
e.mov(e.r8d, e.dword[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryStoreI32);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryStoreI32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1629,7 +1625,7 @@ EMITTER(STORE_I64, MATCH(I<OPCODE_STORE, VoidOp, I64<>, I64<>>)) {
|
|||
auto addr = ComputeMemoryAddress(e, i.src1);
|
||||
e.mov(e.r8, e.qword[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryStoreI64);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryStoreI64));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1646,7 +1642,7 @@ EMITTER(STORE_F32, MATCH(I<OPCODE_STORE, VoidOp, I64<>, F32<>>)) {
|
|||
auto addr = ComputeMemoryAddress(e, i.src1);
|
||||
e.lea(e.r8, e.ptr[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryStoreF32);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryStoreF32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1663,7 +1659,7 @@ EMITTER(STORE_F64, MATCH(I<OPCODE_STORE, VoidOp, I64<>, F64<>>)) {
|
|||
auto addr = ComputeMemoryAddress(e, i.src1);
|
||||
e.lea(e.r8, e.ptr[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryStoreF64);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryStoreF64));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1681,7 +1677,7 @@ EMITTER(STORE_V128, MATCH(I<OPCODE_STORE, VoidOp, I64<>, V128<>>)) {
|
|||
auto addr = ComputeMemoryAddress(e, i.src1);
|
||||
e.lea(e.r8, e.ptr[addr]);
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(TraceMemoryStoreV128);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemoryStoreV128));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -2099,7 +2095,7 @@ EMITTER_OPCODE_TABLE(
|
|||
// OPCODE_COMPARE_*
|
||||
// ============================================================================
|
||||
#define EMITTER_ASSOCIATIVE_COMPARE_INT(op, instr, inverse_instr, type, reg_type) \
|
||||
EMITTER(COMPARE_##op##_##type, MATCH(I<OPCODE_COMPARE_##op##, I8<>, type<>, type<>>)) { \
|
||||
EMITTER(COMPARE_##op##_##type, MATCH(I<OPCODE_COMPARE_##op, I8<>, type<>, type<>>)) { \
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) { \
|
||||
EmitAssociativeCompareOp( \
|
||||
e, i, \
|
||||
|
@ -2119,7 +2115,7 @@ EMITTER_OPCODE_TABLE(
|
|||
EMITTER_ASSOCIATIVE_COMPARE_INT(op, instr, inverse_instr, I32, Reg32); \
|
||||
EMITTER_ASSOCIATIVE_COMPARE_INT(op, instr, inverse_instr, I64, Reg64); \
|
||||
EMITTER_OPCODE_TABLE( \
|
||||
OPCODE_COMPARE_##op##, \
|
||||
OPCODE_COMPARE_##op, \
|
||||
COMPARE_##op##_I8, \
|
||||
COMPARE_##op##_I16, \
|
||||
COMPARE_##op##_I32, \
|
||||
|
@ -2135,13 +2131,13 @@ EMITTER_ASSOCIATIVE_COMPARE_XX(UGE, setae, setb);
|
|||
|
||||
// http://x86.renejeschke.de/html/file_module_x86_id_288.html
|
||||
#define EMITTER_ASSOCIATIVE_COMPARE_FLT_XX(op, instr) \
|
||||
EMITTER(COMPARE_##op##_F32, MATCH(I<OPCODE_COMPARE_##op##, I8<>, F32<>, F32<>>)) { \
|
||||
EMITTER(COMPARE_##op##_F32, MATCH(I<OPCODE_COMPARE_##op, I8<>, F32<>, F32<>>)) { \
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) { \
|
||||
e.vcomiss(i.src1, i.src2); \
|
||||
e.instr(i.dest); \
|
||||
} \
|
||||
}; \
|
||||
EMITTER(COMPARE_##op##_F64, MATCH(I<OPCODE_COMPARE_##op##, I8<>, F64<>, F64<>>)) { \
|
||||
EMITTER(COMPARE_##op##_F64, MATCH(I<OPCODE_COMPARE_##op, I8<>, F64<>, F64<>>)) { \
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) { \
|
||||
if (i.src1.is_constant) { \
|
||||
e.LoadConstantXmm(e.xmm0, i.src1.constant()); \
|
||||
|
@ -3479,39 +3475,44 @@ EMITTER_OPCODE_TABLE(
|
|||
// http://jrfonseca.blogspot.com/2008/09/fast-sse2-pow-tables-or-polynomials.html
|
||||
EMITTER(POW2_F32, MATCH(I<OPCODE_POW2, F32<>, F32<>>)) {
|
||||
static __m128 EmulatePow2(__m128 src) {
|
||||
float result = static_cast<float>(pow(2, src.m128_f32[0]));
|
||||
float src_value;
|
||||
_mm_store_ss(&src_value, src);
|
||||
float result = std::pow(2, src_value);
|
||||
return _mm_load_ss(&result);
|
||||
}
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
assert_always();
|
||||
e.lea(e.r8, e.StashXmm(i.src1));
|
||||
e.CallNativeSafe(EmulatePow2);
|
||||
e.CallNativeSafe(reinterpret_cast<void*>(EmulatePow2));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
}
|
||||
};
|
||||
EMITTER(POW2_F64, MATCH(I<OPCODE_POW2, F64<>, F64<>>)) {
|
||||
static __m128d EmulatePow2(__m128 src) {
|
||||
double result = pow(2, src.m128_f32[0]);
|
||||
double src_value;
|
||||
_mm_store_sd(&src_value, src);
|
||||
double result = std::pow(2, src_value);
|
||||
return _mm_load_sd(&result);
|
||||
}
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
assert_always();
|
||||
e.lea(e.r8, e.StashXmm(i.src1));
|
||||
e.CallNativeSafe(EmulatePow2);
|
||||
e.CallNativeSafe(reinterpret_cast<void*>(EmulatePow2));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
}
|
||||
};
|
||||
EMITTER(POW2_V128, MATCH(I<OPCODE_POW2, V128<>, V128<>>)) {
|
||||
static __m128 EmulatePow2(__m128 src) {
|
||||
__m128 result;
|
||||
alignas(16) float values[4];
|
||||
_mm_store_ps(values, src);
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
result.m128_f32[i] = static_cast<float>(pow(2, src.m128_f32[i]));
|
||||
values[i] = std::pow(2, values[i]);
|
||||
}
|
||||
return result;
|
||||
return _mm_load_ps(values);
|
||||
}
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
e.lea(e.r8, e.StashXmm(i.src1));
|
||||
e.CallNativeSafe(EmulatePow2);
|
||||
e.CallNativeSafe(reinterpret_cast<void*>(EmulatePow2));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
}
|
||||
};
|
||||
|
@ -3530,39 +3531,44 @@ EMITTER_OPCODE_TABLE(
|
|||
// TODO(benvanik): this emulated fn destroys all xmm registers! don't do it!
|
||||
EMITTER(LOG2_F32, MATCH(I<OPCODE_LOG2, F32<>, F32<>>)) {
|
||||
static __m128 EmulateLog2(__m128 src) {
|
||||
float result = log2(src.m128_f32[0]);
|
||||
float src_value;
|
||||
_mm_store_ss(&src_value, src);
|
||||
float result = std::log2(src_value);
|
||||
return _mm_load_ss(&result);
|
||||
}
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
assert_always();
|
||||
e.lea(e.r8, e.StashXmm(i.src1));
|
||||
e.CallNativeSafe(EmulateLog2);
|
||||
e.CallNativeSafe(reinterpret_cast<void*>(EmulateLog2));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
}
|
||||
};
|
||||
EMITTER(LOG2_F64, MATCH(I<OPCODE_LOG2, F64<>, F64<>>)) {
|
||||
static __m128d EmulateLog2(__m128d src) {
|
||||
double result = log2(src.m128d_f64[0]);
|
||||
double src_value;
|
||||
_mm_store_sd(&src_value, src);
|
||||
double result = std::log2(src_value);
|
||||
return _mm_load_sd(&result);
|
||||
}
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
assert_always();
|
||||
e.lea(e.r8, e.StashXmm(i.src1));
|
||||
e.CallNativeSafe(EmulateLog2);
|
||||
e.CallNativeSafe(reinterpret_cast<void*>(EmulateLog2));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
}
|
||||
};
|
||||
EMITTER(LOG2_V128, MATCH(I<OPCODE_LOG2, V128<>, V128<>>)) {
|
||||
static __m128 EmulateLog2(__m128 src) {
|
||||
__m128 result;
|
||||
alignas(16) float values[4];
|
||||
_mm_store_ps(values, src);
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
result.m128_f32[i] = log2(src.m128_f32[i]);
|
||||
values[i] = std::log2(values[i]);
|
||||
}
|
||||
return result;
|
||||
return _mm_load_ps(values);
|
||||
}
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
e.lea(e.r8, e.StashXmm(i.src1));
|
||||
e.CallNativeSafe(EmulateLog2);
|
||||
e.CallNativeSafe(reinterpret_cast<void*>(EmulateLog2));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
}
|
||||
};
|
||||
|
@ -4996,7 +5002,7 @@ EMITTER_OPCODE_TABLE(
|
|||
|
||||
|
||||
|
||||
void alloy::backend::x64::RegisterSequences() {
|
||||
void RegisterSequences() {
|
||||
#define REGISTER_EMITTER_OPCODE_TABLE(opcode) Register_##opcode()
|
||||
REGISTER_EMITTER_OPCODE_TABLE(OPCODE_COMMENT);
|
||||
REGISTER_EMITTER_OPCODE_TABLE(OPCODE_NOP);
|
||||
|
@ -5109,7 +5115,7 @@ void alloy::backend::x64::RegisterSequences() {
|
|||
//REGISTER_EMITTER_OPCODE_TABLE(OPCODE_ATOMIC_SUB);
|
||||
}
|
||||
|
||||
bool alloy::backend::x64::SelectSequence(X64Emitter& e, const Instr* i, const Instr** new_tail) {
|
||||
bool SelectSequence(X64Emitter& e, const Instr* i, const Instr** new_tail) {
|
||||
const InstrKey key(i);
|
||||
const auto its = sequence_table.equal_range(key);
|
||||
for (auto it = its.first; it != its.second; ++it) {
|
||||
|
|
|
@ -43,7 +43,7 @@ void ValueReductionPass::ComputeLastUse(Value* value) {
|
|||
// Note that this list isn't sorted (unfortunately), so we have to scan
|
||||
// them all.
|
||||
uint32_t max_ordinal = 0;
|
||||
Value::Use* last_use = NULL;
|
||||
Value::Use* last_use = nullptr;
|
||||
auto use = value->use_head;
|
||||
while (use) {
|
||||
if (!last_use || use->instr->ordinal >= max_ordinal) {
|
||||
|
@ -52,7 +52,7 @@ void ValueReductionPass::ComputeLastUse(Value* value) {
|
|||
}
|
||||
use = use->next;
|
||||
}
|
||||
value->last_use = last_use->instr;
|
||||
value->last_use = last_use ? last_use->instr : nullptr;
|
||||
}
|
||||
|
||||
int ValueReductionPass::Run(HIRBuilder* builder) {
|
||||
|
|
|
@ -248,6 +248,9 @@ void Disasm_dcbf(InstrData& i, StringBuffer* str) {
|
|||
case 3:
|
||||
name = "dcbflp";
|
||||
break;
|
||||
default:
|
||||
name = "dcbf.??";
|
||||
break;
|
||||
}
|
||||
str->Append("%-8s r%d, r%d", name, i.X.RA, i.X.RB);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ enum TypeName {
|
|||
MAX_TYPENAME,
|
||||
};
|
||||
|
||||
static size_t GetTypeSize(TypeName type_name) {
|
||||
inline size_t GetTypeSize(TypeName type_name) {
|
||||
switch (type_name) {
|
||||
case INT8_TYPE:
|
||||
return 1;
|
||||
|
|
|
@ -23,6 +23,13 @@
|
|||
#define thread_local __thread
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
// C++11 alignas keyword.
|
||||
// This will hopefully be coming soon, as most of the alignment spec is in the
|
||||
// latest CTP.
|
||||
#if XE_COMPILER_MSVC
|
||||
#define alignas(N) __declspec(align(N))
|
||||
#endif // XE_COMPILER_MSVC
|
||||
|
||||
namespace poly {} // namespace poly
|
||||
|
||||
#endif // POLY_CXX_COMPAT_H_
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
namespace poly {
|
||||
namespace threading {
|
||||
|
||||
// Gets the current high-perforance tick count.
|
||||
// Gets the current high-performance tick count.
|
||||
uint64_t ticks();
|
||||
|
||||
// Gets a stable thread-specific ID, but may not be. Use for informative
|
||||
|
|
Loading…
Reference in New Issue