diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 62a4838c27..0e4f3a55e8 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -99,7 +99,7 @@ void ARMv7Interpreter::ADD_IMM(const u32 data, const ARMv7_encoding type) if (set_flags) { bool carry, overflow; - u32 res = AddWithCarry(CPU.read_gpr(n), imm32, false, carry, overflow); + const u32 res = AddWithCarry(CPU.read_gpr(n), imm32, false, carry, overflow); CPU.write_gpr(d, res); CPU.APSR.N = res >> 31; CPU.APSR.Z = res == 0; @@ -504,11 +504,37 @@ void ARMv7Interpreter::CMN_RSR(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::CMP_IMM(const u32 data, const ARMv7_encoding type) { + u32 cond = CPU.ITSTATE.advance(); + u32 n = 0; + u32 imm32 = 0; + switch (type) { + case T1: + { + n = (data & 0x700) >> 8; + imm32 = (data & 0xff); + break; + } + case T2: + { + n = (data & 0xf0000) >> 16; + imm32 = ThumbExpandImm((data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff)); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + bool carry, overflow; + const u32 res = AddWithCarry(CPU.read_gpr(n), ~imm32, true, carry, overflow); + CPU.APSR.N = res >> 31; + CPU.APSR.Z = res == 0; + CPU.APSR.C = carry; + CPU.APSR.V = overflow; + } } void ARMv7Interpreter::CMP_REG(const u32 data, const ARMv7_encoding type) @@ -1027,7 +1053,7 @@ void ARMv7Interpreter::MOV_REG(const u32 data, const ARMv7_encoding type) if (ConditionPassed(cond)) { - u32 res = CPU.read_gpr(m); + const u32 res = CPU.read_gpr(m); CPU.write_gpr(d, res); if (set_flags) { @@ -2096,11 +2122,82 @@ void ARMv7Interpreter::STRH_REG(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::SUB_IMM(const u32 data, const ARMv7_encoding type) { + bool set_flags = !CPU.ITSTATE; + u32 cond = CPU.ITSTATE.advance(); + u32 d = 0; + u32 n = 0; + u32 imm32 = 0; + switch (type) { + case T1: + { + d = (data & 0x7); + n = (data & 0x38) >> 3; + imm32 = (data & 0x1c) >> 6; + break; + } + case T2: + { + d = n = (data & 0x700) >> 8; + imm32 = (data & 0xff); + break; + } + case T3: + { + d = (data & 0xf00) >> 8; + n = (data & 0xf0000) >> 16; + set_flags = (data & 0x100000); + imm32 = ThumbExpandImm((data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff)); + + if (d == 15 && set_flags) + { + throw "CMP (immediate)"; + } + if (n == 13) + { + throw "SUB (SP minus immediate)"; + } + break; + } + case T4: + { + d = (data & 0xf00) >> 8; + n = (data & 0xf0000) >> 16; + set_flags = false; + imm32 = (data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff); + + if (d == 15) + { + throw "ADR"; + } + if (n == 13) + { + throw "SUB (SP minus immediate)"; + } + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + if (set_flags) + { + bool carry, overflow; + const u32 res = AddWithCarry(CPU.read_gpr(n), ~imm32, true, carry, overflow); + CPU.write_gpr(d, res); + CPU.APSR.N = res >> 31; + CPU.APSR.Z = res == 0; + CPU.APSR.C = carry; + CPU.APSR.V = overflow; + } + else + { + CPU.write_gpr(d, CPU.read_gpr(n) - imm32); + } + } } void ARMv7Interpreter::SUB_REG(const u32 data, const ARMv7_encoding type) @@ -2146,11 +2243,11 @@ void ARMv7Interpreter::SUB_REG(const u32 data, const ARMv7_encoding type) if (ConditionPassed(cond)) { - u32 shifted = Shift(CPU.read_gpr(m), shift_t, shift_n, CPU.APSR.C); + const u32 shifted = Shift(CPU.read_gpr(m), shift_t, shift_n, CPU.APSR.C); if (set_flags) { bool carry, overflow; - u32 res = AddWithCarry(CPU.read_gpr(n), ~shifted, true, carry, overflow); + const u32 res = AddWithCarry(CPU.read_gpr(n), ~shifted, true, carry, overflow); CPU.write_gpr(d, res); CPU.APSR.N = res >> 31; CPU.APSR.Z = res == 0; @@ -2177,8 +2274,8 @@ void ARMv7Interpreter::SUB_SPI(const u32 data, const ARMv7_encoding type) { u32 cond = CPU.ITSTATE.advance(); u32 d = 13; - u32 imm32 = 0; bool set_flags = false; + u32 imm32 = 0; switch (type) { @@ -2187,6 +2284,26 @@ void ARMv7Interpreter::SUB_SPI(const u32 data, const ARMv7_encoding type) imm32 = (data & 0x7f) << 2; break; } + case T2: + { + d = (data & 0xf00) >> 8; + set_flags = (data & 0x100000); + imm32 = ThumbExpandImm((data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff)); + + if (d == 15 && set_flags) + { + throw "CMP (immediate)"; + } + break; + } + case T3: + { + d = (data & 0xf00) >> 8; + set_flags = false; + imm32 = (data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff); + break; + } + case A1: throw __FUNCTION__; default: throw __FUNCTION__; } @@ -2195,7 +2312,7 @@ void ARMv7Interpreter::SUB_SPI(const u32 data, const ARMv7_encoding type) if (set_flags) { bool carry, overflow; - u32 res = AddWithCarry(CPU.SP, ~imm32, true, carry, overflow); + const u32 res = AddWithCarry(CPU.SP, ~imm32, true, carry, overflow); CPU.write_gpr(d, res); CPU.APSR.N = res >> 31; CPU.APSR.Z = res == 0; diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index da1b437c61..e9678fe245 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -262,6 +262,12 @@ public: } } + u32 ThumbExpandImm(u32 imm12) + { + bool carry = CPU.APSR.C; + return ThumbExpandImm_C(imm12, carry, carry); + } + bool ConditionPassed(u32 cond) const { bool result = false; diff --git a/rpcs3/Emu/ARMv7/ARMv7Opcodes.h b/rpcs3/Emu/ARMv7/ARMv7Opcodes.h index 963e026ef5..fb46013f1b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Opcodes.h +++ b/rpcs3/Emu/ARMv7/ARMv7Opcodes.h @@ -673,6 +673,12 @@ static const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xfff0, 0x0fc0, 0xf820, 0x0000, T2, STRH_REG), ARMv7_OP4(0x0e50, 0x0ff0, 0x0000, 0x00b0, A1, STRH_REG), + ARMv7_OP2(0xff80, 0xb080, T1, SUB_SPI), + ARMv7_OP4(0xfbef, 0x8000, 0xf1ad, 0x0000, T2, SUB_SPI), + ARMv7_OP4(0xfbff, 0x8000, 0xf2ad, 0x0000, T3, SUB_SPI), + ARMv7_OP4(0x0fef, 0x0000, 0x024d, 0x0000, A1, SUB_SPI), + ARMv7_OP4(0xffef, 0x8000, 0xebad, 0x0000, T1, SUB_SPR), + ARMv7_OP4(0x0fef, 0x0010, 0x004d, 0x0000, A1, SUB_SPR), ARMv7_OP2(0xfe00, 0x1e00, T1, SUB_IMM), ARMv7_OP2(0xf800, 0x3800, T2, SUB_IMM), ARMv7_OP4(0xfbe0, 0x8000, 0xf1a0, 0x0000, T3, SUB_IMM), @@ -682,12 +688,6 @@ static const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xffe0, 0x8000, 0xeba0, 0x0000, T2, SUB_REG), ARMv7_OP4(0x0fe0, 0x0010, 0x0040, 0x0000, A1, SUB_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0040, 0x0010, A1, SUB_RSR), - ARMv7_OP2(0xff80, 0xb080, T1, SUB_SPI), - ARMv7_OP4(0xfbef, 0x8000, 0xf1ad, 0x0000, T2, SUB_SPI), - ARMv7_OP4(0xfbff, 0x8000, 0xf2ad, 0x0000, T3, SUB_SPI), - ARMv7_OP4(0x0fef, 0x0000, 0x024d, 0x0000, A1, SUB_SPI), - ARMv7_OP4(0xffef, 0x8000, 0xebad, 0x0000, T1, SUB_SPR), - ARMv7_OP4(0x0fef, 0x0010, 0x004d, 0x0000, A1, SUB_SPR), ARMv7_OP2(0xff00, 0xdf00, T1, SVC), ARMv7_OP4(0x0f00, 0x0000, 0x0f00, 0x0000, A1, SVC), diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index cdf34ab487..1bd1fea494 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -1,7 +1,28 @@ #include "stdafx.h" +#include "Emu/System.h" #include "PSVFuncList.h" -std::vector g_psv_func_list; +std::vector& g_psv_func_list = []() -> std::vector& +{ + auto v = new std::vector; + + psv_func f = + { + 0xdeadbeef, + "INVALID FUNCTION", + new psv_func_detail::func_binder([]() -> u32 + { + LOG_ERROR(HLE, "Unimplemented function found"); + Emu.Pause(); + + return 0xffffffffu; + }), + nullptr, + }; + v->push_back(f); + + return *v; +}(); void add_psv_func(psv_func& data) { diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 973a045334..1d35143e01 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -556,10 +556,13 @@ bool ELF32Loader::LoadShdrData(u64 offset) if (auto func = get_psv_func_by_nid(nid)) { - func->module->Notice("Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); + if (func->module) + func->module->Notice("Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); + else + LOG_NOTICE(LOADER, "Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); // writing Thumb code (temporarily, because it should be ARM) - vm::psv::write16(addr + 0, 0xf870); // HACK (special instruction that calls HLE function + vm::psv::write16(addr + 0, 0xf870); // HACK (special instruction that calls HLE function) vm::psv::write16(addr + 2, (u16)get_psv_func_index(func)); vm::psv::write16(addr + 4, 0x4770); // BX LR vm::psv::write16(addr + 6, 0); // null @@ -568,9 +571,8 @@ bool ELF32Loader::LoadShdrData(u64 offset) { LOG_ERROR(LOADER, "Unimplemented function 0x%08x (addr=0x%x)", nid, addr); - // writing Thumb code (temporarily - it shouldn't be written in this case) - vm::psv::write16(addr + 0, 0xf06f); // MVN r0,#0x0 - vm::psv::write16(addr + 2, 0x0000); + vm::psv::write16(addr + 0, 0xf870); // HACK (special instruction that calls HLE function) + vm::psv::write16(addr + 2, 0x0000); // (zero index) vm::psv::write16(addr + 4, 0x4770); // BX LR vm::psv::write16(addr + 6, 0); // null }