Implementing dcbz.

This commit is contained in:
Ben Vanik 2015-05-17 16:40:38 -07:00
parent 50b84203c5
commit c1a0f46ea8
10 changed files with 132 additions and 39 deletions

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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()) {

View File

@ -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);

View File

@ -142,6 +142,7 @@ enum Opcode {
OPCODE_STORE_CONTEXT,
OPCODE_LOAD,
OPCODE_STORE,
OPCODE_MEMSET,
OPCODE_PREFETCH,
OPCODE_MAX,
OPCODE_VECTOR_MAX,

View File

@ -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",

View File

@ -323,7 +323,6 @@ SHIM_CALL MmAllocatePhysicalMemoryEx_shim(PPCContext* ppc_state,
}
XELOGD("MmAllocatePhysicalMemoryEx = %.8X", base_address);
SHIM_SET_RETURN_64(base_address);
}

View File

@ -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;
}