Implementing dcbz.
This commit is contained in:
parent
50b84203c5
commit
c1a0f46ea8
|
@ -1673,6 +1673,49 @@ EMITTER_OPCODE_TABLE(
|
|||
PREFETCH);
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// OPCODE_MEMSET
|
||||
// ============================================================================
|
||||
EMITTER(MEMSET_I64_I8_I64, MATCH(I<OPCODE_MEMSET, VoidOp, I64<>, I8<>, I64<>>)) {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
assert_true(i.src2.is_constant);
|
||||
assert_true(i.src3.is_constant);
|
||||
assert_true(i.src2.constant() == 0);
|
||||
e.vpxor(e.xmm0, e.xmm0);
|
||||
auto addr = ComputeMemoryAddress(e, i.src1);
|
||||
switch (i.src3.constant()) {
|
||||
case 32:
|
||||
e.vmovaps(e.ptr[addr + 0 * 16], e.xmm0);
|
||||
e.vmovaps(e.ptr[addr + 1 * 16], e.xmm0);
|
||||
break;
|
||||
case 128:
|
||||
e.vmovaps(e.ptr[addr + 0 * 16], e.xmm0);
|
||||
e.vmovaps(e.ptr[addr + 1 * 16], e.xmm0);
|
||||
e.vmovaps(e.ptr[addr + 2 * 16], e.xmm0);
|
||||
e.vmovaps(e.ptr[addr + 3 * 16], e.xmm0);
|
||||
e.vmovaps(e.ptr[addr + 4 * 16], e.xmm0);
|
||||
e.vmovaps(e.ptr[addr + 5 * 16], e.xmm0);
|
||||
e.vmovaps(e.ptr[addr + 6 * 16], e.xmm0);
|
||||
e.vmovaps(e.ptr[addr + 7 * 16], e.xmm0);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(i.src3.constant());
|
||||
break;
|
||||
}
|
||||
if (IsTracingData()) {
|
||||
addr = ComputeMemoryAddress(e, i.src1);
|
||||
e.mov(e.r9, i.src3.constant());
|
||||
e.mov(e.r8, i.src2.constant());
|
||||
e.lea(e.rdx, e.ptr[addr]);
|
||||
e.CallNative(reinterpret_cast<void*>(TraceMemset));
|
||||
}
|
||||
}
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(
|
||||
OPCODE_MEMSET,
|
||||
MEMSET_I64_I8_I64);
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// OPCODE_MAX
|
||||
// ============================================================================
|
||||
|
@ -6335,6 +6378,7 @@ void RegisterSequences() {
|
|||
REGISTER_EMITTER_OPCODE_TABLE(OPCODE_STORE_CONTEXT);
|
||||
REGISTER_EMITTER_OPCODE_TABLE(OPCODE_LOAD);
|
||||
REGISTER_EMITTER_OPCODE_TABLE(OPCODE_STORE);
|
||||
REGISTER_EMITTER_OPCODE_TABLE(OPCODE_MEMSET);
|
||||
REGISTER_EMITTER_OPCODE_TABLE(OPCODE_PREFETCH);
|
||||
REGISTER_EMITTER_OPCODE_TABLE(OPCODE_MAX);
|
||||
REGISTER_EMITTER_OPCODE_TABLE(OPCODE_VECTOR_MAX);
|
||||
|
|
|
@ -28,10 +28,11 @@ namespace x64 {
|
|||
|
||||
#define TARGET_THREAD 1
|
||||
|
||||
#define IFLUSH() fflush(stdout)
|
||||
#define IFLUSH() \
|
||||
if (thread_state->thread_id() == TARGET_THREAD) fflush(stdout)
|
||||
#define IPRINT \
|
||||
if (thread_state->thread_id() == TARGET_THREAD) printf
|
||||
#define DFLUSH() fflush(stdout)
|
||||
#define DFLUSH() IFLUSH()
|
||||
#define DPRINT \
|
||||
DFLUSH(); \
|
||||
if (thread_state->thread_id() == TARGET_THREAD) printf
|
||||
|
@ -194,6 +195,13 @@ void TraceMemoryStoreV128(void* raw_context, uint32_t address, __m128 value) {
|
|||
xe::m128_i32<3>(value));
|
||||
}
|
||||
|
||||
void TraceMemset(void* raw_context, uint32_t address, uint8_t value,
|
||||
uint32_t length) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("memset %.8X-%.8X (%d) = %.2X", address, address + length, length,
|
||||
value);
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace cpu
|
||||
|
|
|
@ -64,6 +64,9 @@ void TraceMemoryStoreF32(void* raw_context, uint32_t address, __m128 value);
|
|||
void TraceMemoryStoreF64(void* raw_context, uint32_t address, __m128 value);
|
||||
void TraceMemoryStoreV128(void* raw_context, uint32_t address, __m128 value);
|
||||
|
||||
void TraceMemset(void* raw_context, uint32_t address, uint8_t value,
|
||||
uint32_t length);
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace cpu
|
||||
|
|
|
@ -984,11 +984,24 @@ XEEMITTER(dcbtst, 0x7C0001EC, X)(PPCHIRBuilder& f, InstrData& i) {
|
|||
}
|
||||
|
||||
XEEMITTER(dcbz, 0x7C0007EC, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||
// No-op for now.
|
||||
// TODO(benvanik): use prefetch
|
||||
// or dcbz128 0x7C2007EC
|
||||
// XEINSTRNOTIMPLEMENTED();
|
||||
f.Nop();
|
||||
// EA <- (RA) + (RB)
|
||||
// memset(EA & ~31, 0, 32)
|
||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||
int block_size;
|
||||
int address_mask;
|
||||
if (i.X.RT == 1) {
|
||||
// dcbz128 - 128 byte set
|
||||
block_size = 128;
|
||||
address_mask = ~127;
|
||||
}
|
||||
else {
|
||||
// dcbz - 32 byte set
|
||||
block_size = 32;
|
||||
address_mask = ~31;
|
||||
}
|
||||
f.Memset(f.And(ea, f.LoadConstant(int64_t(address_mask))),
|
||||
f.LoadZero(INT8_TYPE), f.LoadConstant(int64_t(block_size)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,15 +20,27 @@ namespace xe {
|
|||
namespace cpu {
|
||||
namespace hir {
|
||||
|
||||
#define ASSERT_ADDRESS_TYPE(value)
|
||||
#define ASSERT_INTEGER_TYPE(value)
|
||||
#define ASSERT_FLOAT_TYPE(value)
|
||||
#define ASSERT_NON_VECTOR_TYPE(value)
|
||||
#define ASSERT_VECTOR_TYPE(value)
|
||||
#define ASSERT_ADDRESS_TYPE(value) \
|
||||
\
|
||||
assert_true((value->type) == INT32_TYPE || (value->type) == INT64_TYPE)
|
||||
#define ASSERT_INTEGER_TYPE(value) \
|
||||
\
|
||||
assert_true((value->type) == INT8_TYPE || (value->type) == INT16_TYPE || \
|
||||
(value->type) == INT32_TYPE || (value->type) == INT64_TYPE)
|
||||
#define ASSERT_FLOAT_TYPE(value) \
|
||||
assert_true((value->type) == FLOAT32_TYPE || (value->type) == FLOAT64_TYPE)
|
||||
#define ASSERT_NON_FLOAT_TYPE(value) \
|
||||
\
|
||||
assert_true((value->type) != FLOAT32_TYPE && (value->type) != FLOAT64_TYPE)
|
||||
#define ASSERT_NON_VECTOR_TYPE(value) assert_false((value->type) == VEC128_TYPE)
|
||||
#define ASSERT_VECTOR_TYPE(value) assert_true((value->type) == VEC128_TYPE)
|
||||
#define ASSERT_FLOAT_OR_VECTOR_TYPE(value) \
|
||||
assert_true((value->type) == FLOAT32_TYPE || \
|
||||
(value->type) == FLOAT64_TYPE || (value->type) == VEC128_TYPE)
|
||||
#define ASSERT_TYPES_EQUAL(value1, value2) \
|
||||
assert_true((value1->type) == (value2->type))
|
||||
|
||||
HIRBuilder::HIRBuilder() {
|
||||
HIRBuilder::HIRBuilder() {
|
||||
arena_ = new Arena();
|
||||
Reset();
|
||||
}
|
||||
|
@ -755,7 +767,7 @@ void HIRBuilder::ReturnTrue(Value* cond) {
|
|||
return;
|
||||
}
|
||||
|
||||
ASSERT_ADDRESS_TYPE(value);
|
||||
ASSERT_ADDRESS_TYPE(cond);
|
||||
Instr* i = AppendInstr(OPCODE_RETURN_TRUE_info, 0);
|
||||
i->set_src1(cond);
|
||||
i->src2.value = i->src3.value = NULL;
|
||||
|
@ -873,8 +885,9 @@ Value* HIRBuilder::SignExtend(Value* value, TypeName target_type) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Truncate(Value* value, TypeName target_type) {
|
||||
ASSERT_INTEGER_TYPE(value->type);
|
||||
ASSERT_INTEGER_TYPE(target_type);
|
||||
ASSERT_INTEGER_TYPE(value);
|
||||
assert_true(target_type == INT8_TYPE || target_type == INT16_TYPE ||
|
||||
target_type == INT32_TYPE || target_type == INT64_TYPE);
|
||||
|
||||
if (value->type == target_type) {
|
||||
return value;
|
||||
|
@ -908,7 +921,7 @@ Value* HIRBuilder::Convert(Value* value, TypeName target_type,
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Round(Value* value, RoundMode round_mode) {
|
||||
ASSERT_FLOAT_TYPE(value);
|
||||
ASSERT_FLOAT_OR_VECTOR_TYPE(value);
|
||||
|
||||
if (value->IsConstant()) {
|
||||
Value* dest = CloneValue(value);
|
||||
|
@ -1090,6 +1103,16 @@ void HIRBuilder::Store(Value* address, Value* value, uint32_t store_flags) {
|
|||
i->src3.value = NULL;
|
||||
}
|
||||
|
||||
void HIRBuilder::Memset(Value* address, Value* value, Value* length) {
|
||||
ASSERT_ADDRESS_TYPE(address);
|
||||
ASSERT_TYPES_EQUAL(address, length);
|
||||
assert_true(value->type == INT8_TYPE);
|
||||
Instr* i = AppendInstr(OPCODE_MEMSET_info, 0);
|
||||
i->set_src1(address);
|
||||
i->set_src2(value);
|
||||
i->set_src3(length);
|
||||
}
|
||||
|
||||
void HIRBuilder::Prefetch(Value* address, size_t length,
|
||||
uint32_t prefetch_flags) {
|
||||
ASSERT_ADDRESS_TYPE(address);
|
||||
|
@ -1471,8 +1494,6 @@ Value* HIRBuilder::MulSub(Value* value1, Value* value2, Value* value3) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Neg(Value* value) {
|
||||
ASSERT_NON_VECTOR_TYPE(value);
|
||||
|
||||
Instr* i = AppendInstr(OPCODE_NEG_info, 0, AllocValue(value->type));
|
||||
i->set_src1(value);
|
||||
i->src2.value = i->src3.value = NULL;
|
||||
|
@ -1480,7 +1501,7 @@ Value* HIRBuilder::Neg(Value* value) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Abs(Value* value) {
|
||||
ASSERT_NON_VECTOR_TYPE(value);
|
||||
ASSERT_FLOAT_OR_VECTOR_TYPE(value);
|
||||
|
||||
Instr* i = AppendInstr(OPCODE_ABS_info, 0, AllocValue(value->type));
|
||||
i->set_src1(value);
|
||||
|
@ -1489,7 +1510,7 @@ Value* HIRBuilder::Abs(Value* value) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Sqrt(Value* value) {
|
||||
ASSERT_FLOAT_TYPE(value);
|
||||
ASSERT_FLOAT_OR_VECTOR_TYPE(value);
|
||||
|
||||
Instr* i = AppendInstr(OPCODE_SQRT_info, 0, AllocValue(value->type));
|
||||
i->set_src1(value);
|
||||
|
@ -1498,7 +1519,7 @@ Value* HIRBuilder::Sqrt(Value* value) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::RSqrt(Value* value) {
|
||||
ASSERT_FLOAT_TYPE(value);
|
||||
ASSERT_FLOAT_OR_VECTOR_TYPE(value);
|
||||
|
||||
Instr* i = AppendInstr(OPCODE_RSQRT_info, 0, AllocValue(value->type));
|
||||
i->set_src1(value);
|
||||
|
@ -1507,7 +1528,7 @@ Value* HIRBuilder::RSqrt(Value* value) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Pow2(Value* value) {
|
||||
ASSERT_FLOAT_TYPE(value);
|
||||
ASSERT_FLOAT_OR_VECTOR_TYPE(value);
|
||||
|
||||
Instr* i = AppendInstr(OPCODE_POW2_info, 0, AllocValue(value->type));
|
||||
i->set_src1(value);
|
||||
|
@ -1516,7 +1537,7 @@ Value* HIRBuilder::Pow2(Value* value) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Log2(Value* value) {
|
||||
ASSERT_FLOAT_TYPE(value);
|
||||
ASSERT_FLOAT_OR_VECTOR_TYPE(value);
|
||||
|
||||
Instr* i = AppendInstr(OPCODE_LOG2_info, 0, AllocValue(value->type));
|
||||
i->set_src1(value);
|
||||
|
@ -1551,8 +1572,8 @@ Value* HIRBuilder::DotProduct4(Value* value1, Value* value2) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::And(Value* value1, Value* value2) {
|
||||
ASSERT_INTEGER_TYPE(value1);
|
||||
ASSERT_INTEGER_TYPE(value2);
|
||||
ASSERT_NON_FLOAT_TYPE(value1);
|
||||
ASSERT_NON_FLOAT_TYPE(value2);
|
||||
ASSERT_TYPES_EQUAL(value1, value2);
|
||||
|
||||
if (value1 == value2) {
|
||||
|
@ -1571,8 +1592,8 @@ Value* HIRBuilder::And(Value* value1, Value* value2) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Or(Value* value1, Value* value2) {
|
||||
ASSERT_INTEGER_TYPE(value1);
|
||||
ASSERT_INTEGER_TYPE(value2);
|
||||
ASSERT_NON_FLOAT_TYPE(value1);
|
||||
ASSERT_NON_FLOAT_TYPE(value2);
|
||||
ASSERT_TYPES_EQUAL(value1, value2);
|
||||
|
||||
if (value1 == value2) {
|
||||
|
@ -1591,8 +1612,8 @@ Value* HIRBuilder::Or(Value* value1, Value* value2) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Xor(Value* value1, Value* value2) {
|
||||
ASSERT_INTEGER_TYPE(value1);
|
||||
ASSERT_INTEGER_TYPE(value2);
|
||||
ASSERT_NON_FLOAT_TYPE(value1);
|
||||
ASSERT_NON_FLOAT_TYPE(value2);
|
||||
ASSERT_TYPES_EQUAL(value1, value2);
|
||||
|
||||
if (value1 == value2) {
|
||||
|
@ -1607,7 +1628,7 @@ Value* HIRBuilder::Xor(Value* value1, Value* value2) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Not(Value* value) {
|
||||
ASSERT_INTEGER_TYPE(value);
|
||||
ASSERT_NON_FLOAT_TYPE(value);
|
||||
|
||||
if (value->IsConstant()) {
|
||||
Value* dest = CloneValue(value);
|
||||
|
@ -1657,7 +1678,7 @@ Value* HIRBuilder::VectorShl(Value* value1, Value* value2, TypeName part_type) {
|
|||
}
|
||||
|
||||
Value* HIRBuilder::Shr(Value* value1, Value* value2) {
|
||||
ASSERT_INTEGER_TYPE(value1);
|
||||
ASSERT_NON_FLOAT_TYPE(value1);
|
||||
ASSERT_INTEGER_TYPE(value2);
|
||||
|
||||
if (value2->IsConstantZero()) {
|
||||
|
|
|
@ -132,6 +132,7 @@ class HIRBuilder {
|
|||
|
||||
Value* Load(Value* address, TypeName type, uint32_t load_flags = 0);
|
||||
void Store(Value* address, Value* value, uint32_t store_flags = 0);
|
||||
void Memset(Value* address, Value* value, Value* length);
|
||||
void Prefetch(Value* address, size_t length, uint32_t prefetch_flags = 0);
|
||||
|
||||
Value* Max(Value* value1, Value* value2);
|
||||
|
|
|
@ -142,6 +142,7 @@ enum Opcode {
|
|||
OPCODE_STORE_CONTEXT,
|
||||
OPCODE_LOAD,
|
||||
OPCODE_STORE,
|
||||
OPCODE_MEMSET,
|
||||
OPCODE_PREFETCH,
|
||||
OPCODE_MAX,
|
||||
OPCODE_VECTOR_MAX,
|
||||
|
|
|
@ -224,6 +224,12 @@ DEFINE_OPCODE(
|
|||
OPCODE_SIG_X_V_V,
|
||||
OPCODE_FLAG_MEMORY)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_MEMSET,
|
||||
"memset",
|
||||
OPCODE_SIG_X_V_V_V,
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_PREFETCH,
|
||||
"prefetch",
|
||||
|
|
|
@ -323,7 +323,6 @@ SHIM_CALL MmAllocatePhysicalMemoryEx_shim(PPCContext* ppc_state,
|
|||
}
|
||||
XELOGD("MmAllocatePhysicalMemoryEx = %.8X", base_address);
|
||||
|
||||
|
||||
SHIM_SET_RETURN_64(base_address);
|
||||
}
|
||||
|
||||
|
|
|
@ -191,13 +191,10 @@ int Memory::Initialize() {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// I have no idea what this is, but games try to read/write there.
|
||||
heaps_.v40000000.AllocFixed(
|
||||
0x40000000, 0x00010000, 32,
|
||||
kMemoryAllocationReserve | kMemoryAllocationCommit,
|
||||
kMemoryProtectRead | kMemoryProtectWrite);
|
||||
xe::store_and_swap<uint32_t>(TranslateVirtual(0x40000000), 0x00C40000);
|
||||
xe::store_and_swap<uint32_t>(TranslateVirtual(0x40000004), 0x00010000);
|
||||
// ?
|
||||
uint32_t unk_phys_alloc;
|
||||
heaps_.vA0000000.Alloc(0x340000, 64 * 1024, kMemoryAllocationReserve,
|
||||
kMemoryProtectNoAccess, true, &unk_phys_alloc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue