From cbc74c92f40a68bd3f0f7ab9f6f276014288905c Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Wed, 30 Dec 2015 10:04:57 -0800 Subject: [PATCH] Fixing CR update for divwu/divdu/mulhwu. --- src/xenia/cpu/ppc/ppc_context.cc | 27 ++++++++++++++++++++++++ src/xenia/cpu/ppc/ppc_context.h | 6 ++++-- src/xenia/cpu/ppc/ppc_emit_alu.cc | 6 +++--- src/xenia/cpu/ppc/testing/instr_divdu.s | 18 ++++++++++++++++ src/xenia/cpu/ppc/testing/instr_divwu.s | 18 ++++++++++++++++ src/xenia/cpu/ppc/testing/instr_mulhwu.s | 18 ++++++++++++++++ 6 files changed, 88 insertions(+), 5 deletions(-) diff --git a/src/xenia/cpu/ppc/ppc_context.cc b/src/xenia/cpu/ppc/ppc_context.cc index ffdc484c3..5e6594bcd 100644 --- a/src/xenia/cpu/ppc/ppc_context.cc +++ b/src/xenia/cpu/ppc/ppc_context.cc @@ -19,6 +19,23 @@ namespace xe { namespace cpu { namespace ppc { +uint64_t PPCContext::cr() const { + uint64_t final_bits = 0; + for (int i = 0; i < 8; ++i) { + uint32_t crf = *(&cr0.value + i); + uint64_t bits = (crf & 0x1) << (4 * (7 - i) + 3) | + ((crf >> 8) & 0x1) << (4 * (7 - i) + 2) | + ((crf >> 16) & 0x1) << (4 * (7 - i) + 1) | + ((crf >> 24) & 0x1) << (4 * (7 - i) + 0); + final_bits |= bits << (i * 4); + } + return final_bits; +} + +void PPCContext::set_cr(uint64_t value) { + assert_always("not yet implemented"); +} + std::string PPCContext::GetRegisterName(PPCRegister reg) { switch (reg) { case PPCRegister::kLR: @@ -111,6 +128,8 @@ void PPCContext::SetRegFromString(const char* name, const char* value) { this->f[n] = string_util::from_string(value); } else if (sscanf(name, "v%d", &n) == 1) { this->v[n] = string_util::from_string(value); + } else if (std::strcmp(name, "cr") == 0) { + this->set_cr(string_util::from_string(value)); } else { printf("Unrecognized register name: %s\n", name); } @@ -144,6 +163,14 @@ bool PPCContext::CompareRegWithString(const char* name, const char* value, return false; } return true; + } else if (std::strcmp(name, "cr") == 0) { + uint64_t actual = this->cr(); + uint64_t expected = string_util::from_string(value); + if (actual != expected) { + std::snprintf(out_value, out_value_size, "%016" PRIX64, actual); + return false; + } + return true; } else { assert_always("Unrecognized register name: %s\n", name); return false; diff --git a/src/xenia/cpu/ppc/ppc_context.h b/src/xenia/cpu/ppc/ppc_context.h index 7146972bc..b37f4cda4 100644 --- a/src/xenia/cpu/ppc/ppc_context.h +++ b/src/xenia/cpu/ppc/ppc_context.h @@ -260,14 +260,16 @@ typedef struct PPCContext_s { double f[32]; // Floating-point registers vec128_t v[128]; // VMX128 vector registers - // XER register + // XER register: // Split to make it easier to do individual updates. uint8_t xer_ca; uint8_t xer_ov; uint8_t xer_so; - // Condition registers + // Condition registers: // These are split to make it easier to do DCE on unused stores. + uint64_t cr() const; + void set_cr(uint64_t value); union { uint32_t value; struct { diff --git a/src/xenia/cpu/ppc/ppc_emit_alu.cc b/src/xenia/cpu/ppc/ppc_emit_alu.cc index b5f1579bd..265fb1267 100644 --- a/src/xenia/cpu/ppc/ppc_emit_alu.cc +++ b/src/xenia/cpu/ppc/ppc_emit_alu.cc @@ -234,7 +234,7 @@ int InstrEmit_divdux(PPCHIRBuilder& f, const InstrData& i) { return 1; } if (i.XO.Rc) { - f.UpdateCR(0, v, false); + f.UpdateCR(0, v); } return 0; } @@ -291,7 +291,7 @@ int InstrEmit_divwux(PPCHIRBuilder& f, const InstrData& i) { return 1; } if (i.XO.Rc) { - f.UpdateCR(0, v, false); + f.UpdateCR(0, v); } return 0; } @@ -357,7 +357,7 @@ int InstrEmit_mulhwux(PPCHIRBuilder& f, const InstrData& i) { INT64_TYPE); f.StoreGPR(i.XO.RT, v); if (i.XO.Rc) { - f.UpdateCR(0, v, false); + f.UpdateCR(0, v); } return 0; } diff --git a/src/xenia/cpu/ppc/testing/instr_divdu.s b/src/xenia/cpu/ppc/testing/instr_divdu.s index be08b67a1..4288f28fd 100644 --- a/src/xenia/cpu/ppc/testing/instr_divdu.s +++ b/src/xenia/cpu/ppc/testing/instr_divdu.s @@ -163,3 +163,21 @@ test_divdu_9_constant: #_ REGISTER_OUT r3 0 #_ REGISTER_OUT r4 0x8000000000000000 #_ REGISTER_OUT r5 -1 + +test_divdu_10: + #_ REGISTER_IN r0 0x1 + #_ REGISTER_IN r3 0xFFFFFFFF + divdu. r0, r3, r0 + blr + #_ REGISTER_OUT r0 0xFFFFFFFF + #_ REGISTER_OUT r3 0xFFFFFFFF + #_ REGISTER_OUT cr 0x0000000080000000 + +test_divdu_11: + #_ REGISTER_IN r0 0 + #_ REGISTER_IN r3 0xFFFFFFFF + divdu. r0, r0, r3 + blr + #_ REGISTER_OUT r0 0xFFFFFFFF + #_ REGISTER_OUT r3 0xFFFFFFFF + #_ REGISTER_OUT cr 0x0000000020000000 diff --git a/src/xenia/cpu/ppc/testing/instr_divwu.s b/src/xenia/cpu/ppc/testing/instr_divwu.s index 56e45dd94..a3e1b12a3 100644 --- a/src/xenia/cpu/ppc/testing/instr_divwu.s +++ b/src/xenia/cpu/ppc/testing/instr_divwu.s @@ -219,3 +219,21 @@ test_divwu_12_constant: #_ REGISTER_OUT r3 0 #_ REGISTER_OUT r4 0x80000000 #_ REGISTER_OUT r5 -1 + +test_divwu_13: + #_ REGISTER_IN r0 0x1 + #_ REGISTER_IN r3 0xFFFFFFFF + divwu. r0, r3, r0 + blr + #_ REGISTER_OUT r0 0xFFFFFFFF + #_ REGISTER_OUT r3 0xFFFFFFFF + #_ REGISTER_OUT cr 0x0000000080000000 + +test_divwu_14: + #_ REGISTER_IN r0 0x1 + #_ REGISTER_IN r3 0xFFFFFFFF + divwu. r0, r0, r3 + blr + #_ REGISTER_OUT r0 0 + #_ REGISTER_OUT r3 0xFFFFFFFF + #_ REGISTER_OUT cr 0x0000000020000000 diff --git a/src/xenia/cpu/ppc/testing/instr_mulhwu.s b/src/xenia/cpu/ppc/testing/instr_mulhwu.s index dec3a314b..5f5fdd695 100644 --- a/src/xenia/cpu/ppc/testing/instr_mulhwu.s +++ b/src/xenia/cpu/ppc/testing/instr_mulhwu.s @@ -111,3 +111,21 @@ test_mulhwu_6_constant: #_ REGISTER_OUT r3 0x00000000FFFFFFFE #_ REGISTER_OUT r4 0xFFFFFFFFFFFFFFFF #_ REGISTER_OUT r5 0xFFFFFFFFFFFFFFFF + +test_mulhwu_7: + #_ REGISTER_IN r0 0x1 + #_ REGISTER_IN r3 0xFFFFFFFF + mulhwu. r0, r3, r0 + blr + #_ REGISTER_OUT r0 0 + #_ REGISTER_OUT r3 0xFFFFFFFF + #_ REGISTER_OUT cr 0x0000000020000000 + +test_mulhwu_8: + #_ REGISTER_IN r0 0x1 + #_ REGISTER_IN r3 0x1FFFFFFFF + mulhwu. r0, r3, r0 + blr + #_ REGISTER_OUT r0 0 + #_ REGISTER_OUT r3 0x1FFFFFFFF + #_ REGISTER_OUT cr 0x0000000020000000