diff --git a/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc b/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc index 468e35ce0..c8a5ef632 100644 --- a/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc +++ b/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc @@ -153,6 +153,14 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) { i->Remove(); } break; + case OPCODE_CONVERT: + if (i->src1.value->IsConstant()) { + TypeName target_type = v->type; + v->set_from(i->src1.value); + v->Convert(target_type, RoundMode(i->flags)); + i->Remove(); + } + break; case OPCODE_ZERO_EXTEND: if (i->src1.value->IsConstant()) { TypeName target_type = v->type; @@ -195,10 +203,29 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) { !(protect & kMemoryProtectWrite) && (protect & kMemoryProtectRead)) { // Memory is readonly - can just return the value. + auto host_addr = memory->TranslateVirtual(address); switch (v->type) { + case INT8_TYPE: + v->set_constant(xe::load(host_addr)); + i->Remove(); + break; + case INT16_TYPE: + v->set_constant(xe::load(host_addr)); + i->Remove(); + break; case INT32_TYPE: - v->set_constant(xe::load_and_swap( - memory->TranslateVirtual(address))); + v->set_constant(xe::load(host_addr)); + i->Remove(); + break; + case INT64_TYPE: + v->set_constant(xe::load(host_addr)); + i->Remove(); + break; + case VEC128_TYPE: + vec128_t val; + val.low = xe::load(host_addr); + val.high = xe::load(host_addr + 8); + v->set_constant(val); i->Remove(); break; default: diff --git a/src/xenia/cpu/hir/value.cc b/src/xenia/cpu/hir/value.cc index d8f614a7e..e0be35b58 100644 --- a/src/xenia/cpu/hir/value.cc +++ b/src/xenia/cpu/hir/value.cc @@ -77,8 +77,8 @@ uint64_t Value::AsUint64() { } void Value::Cast(TypeName target_type) { - // TODO(benvanik): big matrix. - assert_always(); + // Only need a type change. + type = target_type; } void Value::ZeroExtend(TypeName target_type) { @@ -199,8 +199,25 @@ void Value::Truncate(TypeName target_type) { } void Value::Convert(TypeName target_type, RoundMode round_mode) { - // TODO(benvanik): big matrix. - assert_always(); + switch (type) { + case FLOAT32_TYPE: + switch (target_type) { + case FLOAT64_TYPE: + type = target_type; + constant.f64 = constant.f32; + return; + } + case FLOAT64_TYPE: + switch (target_type) { + case FLOAT32_TYPE: + type = target_type; + constant.f32 = (float)constant.f64; + return; + } + default: + assert_unhandled_case(target_type); + return; + } } void Value::Round(RoundMode round_mode) { diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index 07730e211..ba2a24184 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -281,6 +281,34 @@ bool XexModule::Load(const std::string& name, const std::string& path, } } + // Setup memory protection. + // TODO: This introduces a load of constants into the JIT, and Xenia isn't + // quite set-up to handle constants yet... + /* + auto sec_header = xex_security_info(); + auto heap = memory()->LookupHeap(sec_header->load_address); + auto page_size = heap->page_size(); + for (uint32_t i = 0, page = 0; i < sec_header->page_descriptor_count; i++) { + // Byteswap the bitfield manually. + xex2_page_descriptor desc; + desc.value = xe::byte_swap(sec_header->page_descriptors[i].value); + + auto address = sec_header->load_address + (page * page_size); + auto size = desc.size * page_size; + switch (desc.info) { + case XEX_SECTION_CODE: + case XEX_SECTION_READONLY_DATA: + heap->Protect(address, size, kMemoryProtectRead); + break; + case XEX_SECTION_DATA: + heap->Protect(address, size, kMemoryProtectRead | kMemoryProtectWrite); + break; + } + + page += desc.size; + } + */ + return true; }