From 5225ca8fc2154c506cb91bdfdb56cf38087fdef2 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 3 Feb 2015 00:00:05 +0300 Subject: [PATCH 01/15] ARMv7: branch instrs fixed, new instructions BIC_IMM, BIC_REG, RSB_IMM, LDR_LIT, STRB_REG, STRH_REG Fixed initial stack size --- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 290 ++++++++++++++++++++--- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 8 +- rpcs3/Emu/ARMv7/ARMv7Thread.h | 2 +- rpcs3/Emu/ARMv7/Modules/psv_event_flag.h | 1 + rpcs3/Emu/ARMv7/Modules/psv_sema.h | 1 + rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 126 +++++----- rpcs3/Emu/ARMv7/PSVObjectList.h | 34 ++- rpcs3/Emu/Memory/vm.cpp | 6 +- rpcs3/Loader/ELF32.cpp | 4 +- 9 files changed, 367 insertions(+), 105 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index d7b1c9adf8..6ec1bbebf1 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -228,9 +228,9 @@ namespace ARMv7_instrs } } - u32 ThumbExpandImm(ARMv7Context& context, u32 imm12) + u32 ThumbExpandImm(u32 imm12) { - bool carry = context.APSR.C; + bool carry; return ThumbExpandImm_C(imm12, carry, carry); } @@ -418,7 +418,7 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR d = (code.data & 0xf00) >> 8; n = (code.data & 0xf0000) >> 16; set_flags = (code.data & 0x100000); - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(d == 15 && set_flags, "CMN (immediate)"); reject(n == 13, "ADD (SP plus immediate)"); @@ -567,7 +567,7 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR cond = context.ITSTATE.advance(); d = (code.data & 0xf00) >> 8; set_flags = (code.data & 0x100000); - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(d == 15 && set_flags, "CMN (immediate)"); reject(d == 15, "UNPREDICTABLE"); @@ -770,14 +770,14 @@ void ARMv7_instrs::ASR_REG(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { - u32 cond, jump; + u32 cond, imm32; switch (type) { case T1: { cond = (code.data >> 8) & 0xf; - jump = 4 + sign<9, u32>((code.data & 0xff) << 1); + imm32 = sign<9, u32>((code.data & 0xff) << 1); reject(cond == 14, "UNDEFINED"); reject(cond == 15, "SVC"); @@ -787,7 +787,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en case T2: { cond = context.ITSTATE.advance(); - jump = 4 + sign<12, u32>((code.data & 0x7ff) << 1); + imm32 = sign<12, u32>((code.data & 0x7ff) << 1); reject(context.ITSTATE, "UNPREDICTABLE"); break; @@ -799,7 +799,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en const u32 s = (code.data >> 26) & 0x1; const u32 j1 = (code.data >> 13) & 0x1; const u32 j2 = (code.data >> 11) & 0x1; - jump = 4 + sign<21, u32>(s << 20 | j2 << 19 | j1 << 18 | (code.data & 0x3f0000) >> 4 | (code.data & 0x7ff) << 1); + imm32 = sign<21, u32>(s << 20 | j2 << 19 | j1 << 18 | (code.data & 0x3f0000) >> 4 | (code.data & 0x7ff) << 1); } reject(cond >= 14, "Related encodings"); @@ -813,7 +813,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en const u32 s = (code.data >> 26) & 0x1; const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1; const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; - jump = 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); + imm32 = sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); } reject(context.ITSTATE, "UNPREDICTABLE"); @@ -822,7 +822,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en case A1: { cond = code.data >> 28; - jump = 1 + 4 + sign<26, u32>((code.data & 0xffffff) << 2); + imm32 = sign<26, u32>((code.data & 0xffffff) << 2); break; } default: throw __FUNCTION__; @@ -830,8 +830,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en if (ConditionPassed(context, cond)) { - //LOG_NOTICE(ARMv7, "Branch to 0x%x (cond=0x%x)", context.thread.PC + jump, cond); - context.thread.SetBranch(context.thread.PC + jump); + context.thread.SetBranch(context.read_pc() + imm32); } } @@ -857,20 +856,86 @@ void ARMv7_instrs::BFI(ARMv7Context& context, const ARMv7Code code, const ARMv7_ void ARMv7_instrs::BIC_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags, carry = context.APSR.C; + u32 cond, d, n, imm32; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) & ~imm32; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::BIC_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 13 || d == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shifted = Shift_C(context.read_gpr(m), shift_t, shift_n, context.APSR.C, carry); + const u32 result = context.read_gpr(n) & ~shifted; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::BIC_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -895,19 +960,18 @@ void ARMv7_instrs::BKPT(ARMv7Context& context, const ARMv7Code code, const ARMv7 void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { - u32 cond, imm32, newLR; + u32 cond, imm32; switch (type) { case T1: { cond = context.ITSTATE.advance(); - newLR = (context.thread.PC + 4) | 1; { const u32 s = (code.data >> 26) & 0x1; const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1; const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; - imm32 = 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); + imm32 = sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); } reject(context.ITSTATE, "UNPREDICTABLE"); @@ -916,8 +980,7 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e case A1: { cond = code.data >> 28; - newLR = (context.thread.PC + 4) - 4; - imm32 = 4 + sign<26, u32>((code.data & 0xffffff) << 2); + imm32 = sign<26, u32>((code.data & 0xffffff) << 2); break; } default: throw __FUNCTION__; @@ -925,8 +988,16 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e if (ConditionPassed(context, cond)) { - context.LR = newLR; - context.thread.SetBranch(context.thread.PC + imm32); + if (context.ISET == ARM) + { + context.LR = context.read_pc() - 4; + context.thread.SetBranch((context.read_pc() & ~3) + imm32); + } + else + { + context.LR = context.read_pc() | 1; + context.thread.SetBranch(context.read_pc() + imm32); + } } } @@ -939,7 +1010,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ case T1: { cond = context.ITSTATE.advance(); - newLR = (context.thread.PC + 2) | 1; // ??? + newLR = (context.thread.PC + 2) | 1; { const u32 m = (code.data >> 3) & 0xf; reject(m == 15, "UNPREDICTABLE"); @@ -957,7 +1028,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ const u32 s = (code.data >> 26) & 0x1; const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1; const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; - target = (context.thread.PC + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); + target = ~3 & context.thread.PC + 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); } reject(context.ITSTATE, "UNPREDICTABLE"); @@ -966,15 +1037,15 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ case A1: { cond = code.data >> 28; - newLR = (context.thread.PC + 4) - 4; + newLR = context.thread.PC + 4; target = context.read_gpr(code.data & 0xf); break; } case A2: { cond = 0xe; // always true - newLR = (context.thread.PC + 4) - 4; - target = (context.thread.PC + 4 | 1) + sign<25, u32>((code.data & 0xffffff) << 2 | (code.data & 0x1000000) >> 23); + newLR = context.thread.PC + 4; + target = 1 | context.thread.PC + 8 + sign<25, u32>((code.data & 0xffffff) << 2 | (code.data & 0x1000000) >> 23); break; } default: throw __FUNCTION__; @@ -1038,7 +1109,7 @@ void ARMv7_instrs::CB_Z(ARMv7Context& context, const ARMv7Code code, const ARMv7 if ((context.read_gpr(n) == 0) ^ nonzero) { - context.thread.SetBranch(context.thread.PC + 2 + imm32); + context.thread.SetBranch(context.read_pc() + imm32); } } @@ -1115,7 +1186,7 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR { cond = context.ITSTATE.advance(); n = (code.data & 0xf0000) >> 16; - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(n == 15, "UNPREDICTABLE"); break; @@ -1127,11 +1198,14 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), ~imm32, true, carry, overflow); + const u32 n_value = context.read_gpr(n); + const u32 res = AddWithCarry(n_value, ~imm32, true, carry, overflow); context.APSR.N = res >> 31; context.APSR.Z = res == 0; context.APSR.C = carry; context.APSR.V = overflow; + + //LOG_NOTICE(ARMv7, "CMP: r%d=0x%08x <> 0x%08x, res=0x%08x", n, n_value, imm32, res); } } @@ -1369,11 +1443,40 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::LDR_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, imm32; + bool add; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x700) >> 8; + imm32 = (code.data & 0xff) << 2; + add = true; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + imm32 = (code.data & 0xfff); + add = (code.data & 0x800000); + + reject(t == 15 && context.ITSTATE, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 base = context.read_pc() & ~3; + const u32 addr = add ? base + imm32 : base - imm32; + const u32 data = vm::psv::read32(addr); + context.write_gpr(t, data); + } } void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -2544,11 +2647,48 @@ void ARMv7_instrs::RRX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ void ARMv7_instrs::RSB_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, imm32; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + imm32 = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry, overflow; + const u32 result = AddWithCarry(~context.read_gpr(n), imm32, true, carry, overflow); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + context.APSR.V = overflow; + } + } } void ARMv7_instrs::RSB_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3167,11 +3307,57 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, m, shift_t, shift_n; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + m = (code.data & 0x1c0) >> 6; + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = (code.data & 0x30) >> 4; + + reject(n == 15, "UNDEFINED"); + reject(t == 13 || t == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + vm::psv::write8(addr, (u8)context.read_gpr(t)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } @@ -3205,11 +3391,57 @@ void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, m, shift_t, shift_n; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + m = (code.data & 0x1c0) >> 6; + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = (code.data & 0x30) >> 4; + + reject(n == 15, "UNDEFINED"); + reject(t == 13 || t == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + vm::psv::write16(addr, (u16)context.read_gpr(t)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } @@ -3302,7 +3534,7 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR d = (code.data & 0xf00) >> 8; n = (code.data & 0xf0000) >> 16; set_flags = (code.data & 0x100000); - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(d == 15 && set_flags, "CMP (immediate)"); reject(n == 13, "SUB (SP minus immediate)"); @@ -3429,7 +3661,7 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR cond = context.ITSTATE.advance(); d = (code.data & 0xf00) >> 8; set_flags = (code.data & 0x100000); - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(d == 15 && set_flags, "CMP (immediate)"); reject(d == 15, "UNPREDICTABLE"); diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 9fe72a3d49..12b7c7b0b3 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -18,7 +18,7 @@ void ARMv7Context::write_pc(u32 value) u32 ARMv7Context::read_pc() { - return thread.PC; + return ISET == ARM ? thread.PC + 8 : thread.PC + 4; } u32 ARMv7Context::get_stack_arg(u32 pos) @@ -230,14 +230,14 @@ void ARMv7Thread::FastStop() m_status = Stopped; } -armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) +armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio) { thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7); thread->SetName(name); thread->SetEntry(entry); - thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize); - thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio); + thread->SetStackSize(stack_size); + thread->SetPrio(prio); argc = 0; } diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index a8a0f75311..5bbc4a564c 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -39,7 +39,7 @@ class armv7_thread : cpu_thread u32 argc; public: - armv7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0); + armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio); cpu_thread& args(std::initializer_list values) override; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h index bc1cb2d4e9..ad69269a1a 100644 --- a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h +++ b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h @@ -2,6 +2,7 @@ struct psv_event_flag_t { + s32 id; char name[32]; u32 attr; u32 pattern; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema.h b/rpcs3/Emu/ARMv7/Modules/psv_sema.h index 30b3fa6c4c..83b3b99b24 100644 --- a/rpcs3/Emu/ARMv7/Modules/psv_sema.h +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema.h @@ -2,6 +2,7 @@ struct psv_sema_t { + s32 id; char name[32]; u32 attr; s32 value; diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index d280e3dc24..cf3725a3f9 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -2,6 +2,7 @@ #include "Utilities/Log.h" #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/ARMv7Thread.h" #include "Emu/ARMv7/ARMv7Callback.h" extern psv_log_base sceLibc; @@ -12,6 +13,70 @@ typedef void(atexit_func_t)(vm::psv::ptr); std::vector> g_atexit; +std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g_count, u32 f_count, u32 v_count) +{ + std::string result; + + for (char c = *fmt++; c; c = *fmt++) + { + switch (c) + { + case '%': + { + const auto start = fmt - 1; + const bool number_sign = *fmt == '#' ? fmt++, true : false; + + switch (*fmt++) + { + case '%': + { + result += '%'; + continue; + } + case 'd': + case 'i': + { + // signed decimal + const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count); + + result += fmt::to_sdec(value); + continue; + } + case 'x': + { + // hexadecimal + const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count); + + if (number_sign && value) + { + result += "0x"; + } + + result += fmt::to_hex(value); + continue; + } + case 's': + { + // string + auto string = vm::psv::ptr::make(context.get_next_gpr_arg(g_count, f_count, v_count)); + + result += string.get_ptr(); + continue; + } + default: + { + throw fmt::Format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr()); + } + } + } + } + + result += c; + } + + return result; +} + namespace sce_libc_func { void __cxa_atexit(vm::psv::ptr func, vm::psv::ptr arg, vm::psv::ptr dso) @@ -59,62 +124,6 @@ namespace sce_libc_func }); } - std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g_count, u32 f_count, u32 v_count) - { - std::string result; - - for (char c = *fmt++; c; c = *fmt++) - { - switch (c) - { - case '%': - { - const auto start = fmt - 1; - const bool number_sign = *fmt == '#' ? fmt++, true : false; - - switch (*fmt++) - { - case '%': - { - result += '%'; - continue; - } - case 'd': - case 'i': - { - // signed decimal - const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count); - - result += fmt::to_sdec(value); - continue; - } - case 'x': - { - // hexadecimal - const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count); - - if (number_sign && value) - { - result += "0x"; - } - - result += fmt::to_hex(value); - continue; - } - default: - { - throw fmt::Format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr()); - } - } - } - } - - result += c; - } - - return result; - } - void printf(ARMv7Context& context, vm::psv::ptr fmt) // va_args... { sceLibc.Warning("printf(fmt=0x%x)", fmt); @@ -158,11 +167,12 @@ namespace sce_libc_func ::memset(dst.get_ptr(), value, size); } - void _Assert(vm::psv::ptr text, vm::psv::ptr func) + void _Assert(ARMv7Context& context, vm::psv::ptr text, vm::psv::ptr func) { - sceLibc.Warning("_Assert(text=0x%x, func=0x%x)", text, func); + sceLibc.Error("_Assert(text=0x%x, func=0x%x)", text, func); LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr()); + LOG_NOTICE(ARMv7, context.thread.RegsToString()); Emu.Pause(); } } diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h index d25c6e39ce..278bc521dd 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.h +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -25,8 +25,18 @@ template class psv_object_list_t // Class for managing object data { std::array, 0x8000> m_data; + std::atomic m_hint; // guessing next free position std::mutex m_mutex; // TODO: remove it when shared_ptr atomic ops are fully available +public: + psv_object_list_t() : m_hint(0) {} + + psv_object_list_t(const psv_object_list_t&) = delete; + psv_object_list_t(psv_object_list_t&&) = delete; + + psv_object_list_t& operator =(const psv_object_list_t&) = delete; + psv_object_list_t& operator =(psv_object_list_t&&) = delete; + public: static const u32 uid_class = type; @@ -60,18 +70,18 @@ public: { std::lock_guard lock(m_mutex); - for (auto& value : m_data) + for (u32 i = 0, j = m_hint % m_data.size(); i < m_data.size(); i++, j = (j + 1) % m_data.size()) { - // find an empty position and move the pointer - //std::shared_ptr old_ptr = nullptr; - //if (std::atomic_compare_exchange_strong(&value, &old_ptr, data)) - if (!value) + // find an empty position and copy the pointer + if (!m_data[j]) { - value = data; + m_data[j] = data; + m_hint = j + 1; // guess next position psv_uid_t id = psv_uid_t::make(1); // odd number id.type = uid_class; // set type - id.number = &value - m_data.data(); // set position - return id.uid; + id.number = j; // set position + data->id = id.uid; // save UID + return id.uid; // return UID } } @@ -86,12 +96,14 @@ public: return nullptr; } + const u32 pos = psv_uid_t::make(uid).number; + std::lock_guard lock(m_mutex); std::shared_ptr old_ptr = nullptr; - m_data[psv_uid_t::make(uid).number].swap(old_ptr); + m_data[pos].swap(old_ptr); + m_hint = pos; return old_ptr; - //return std::atomic_exchange>(&m_data[psv_uid_t::make(uid).number], nullptr); } // remove all objects @@ -103,6 +115,8 @@ public: { value = nullptr; } + + m_hint = 0; } }; diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 04d3a0f90a..9a5f9eec9e 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -63,7 +63,11 @@ namespace vm return res; } - assert(!real_pointer); + if (real_pointer) + { + throw fmt::format("vm::get_addr(0x%016llx) failed: not a part of virtual memory", (u64)real_pointer); + } + return 0; } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 89112c8692..1d0ea7a16e 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -401,8 +401,8 @@ namespace loader armv7_decoder_initialize(code_start, code_end); const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread"; - const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 0; - const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0; + const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 256 * 1024; + const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 160; armv7_thread(entry, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run(); break; From 2494fcf8d842d0e69d49361f859854f1ace641c7 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 3 Feb 2015 17:48:20 +0300 Subject: [PATCH 02/15] ARMv7: new instructions, bugfix LDRD_LIT, LDRH_IMM, LDRH_LIT, LSR_IMM, ORR_IMM, STRD_IMM, STRD_REG, UMULL --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 11 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 390 ++++++++++++++++++----- rpcs3/Emu/ARMv7/Modules/psv_event_flag.h | 4 +- rpcs3/Emu/ARMv7/Modules/psv_sema.h | 3 +- rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp | 6 +- rpcs3/Emu/ARMv7/PSVObjectList.h | 11 +- 6 files changed, 342 insertions(+), 83 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 2c0c976697..09ac2275d8 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1105,6 +1105,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = struct ARMv7_op2_table_t { const ARMv7_opcode_t* data[0x10000]; + u32 null_ops; ARMv7_op2_table_t() { @@ -1123,6 +1124,8 @@ struct ARMv7_op2_table_t } } + null_ops = 0x10000; + for (u32 i = 0; i < 0x10000; i++) { data[i] = nullptr; @@ -1132,6 +1135,7 @@ struct ARMv7_op2_table_t if (((i << 16) & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(i))) { data[i] = opcode; + null_ops--; break; } } @@ -1201,11 +1205,12 @@ std::unordered_map g_opct; void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) { - // 1. Find every 4-byte thumb instruction and cache it + // 1. Find every 4-byte Thumb instruction and cache it // 2. If some instruction is not recognized, print the error // 3. Possibly print disasm - g_opct.clear(); + //g_opct.clear(); + //g_opct.reserve(end_addr - addr); while (addr < end_addr) { @@ -1297,7 +1302,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) addr += found->length; } - LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size()); + LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld, g_op2t.null_ops=0x%x", (u64)g_opct.size(), g_op2t.null_ops); } u32 ARMv7Decoder::DecodeMemory(const u32 address) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 6ec1bbebf1..eabed09520 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -444,20 +444,17 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; + const u32 result = AddWithCarry(context.read_gpr(n), imm32, false, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), imm32, false, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.read_gpr(n) + imm32); - } } } @@ -512,21 +509,18 @@ void ARMv7_instrs::ADD_REG(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, true); + const u32 result = AddWithCarry(context.read_gpr(n), shifted, false, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), shifted, false, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.read_gpr(n) + shifted); - } } } @@ -589,20 +583,17 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; + const u32 result = AddWithCarry(context.SP, imm32, false, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.SP, imm32, false, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.SP + imm32); - } } } @@ -652,21 +643,18 @@ void ARMv7_instrs::ADD_SPR(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 result = AddWithCarry(context.SP, shifted, false, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.SP, shifted, false, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.SP + context.read_gpr(m)); - } } } @@ -1549,7 +1537,7 @@ void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const A cond = context.ITSTATE.advance(); t = (code.data & 0x7); n = (code.data & 0x38) >> 3; - imm32 = (code.data & 0x7c0) >> 4; + imm32 = (code.data & 0x7c0) >> 6; index = true; add = true; wback = false; @@ -1657,7 +1645,6 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); const u64 value = vm::psv::read64(addr); - context.write_gpr(t, (u32)(value)); context.write_gpr(t2, (u32)(value >> 32)); @@ -1670,11 +1657,35 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::LDRD_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, t2, imm32; + bool add; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + t2 = (code.data & 0xf00) >> 8; + imm32 = (code.data & 0xff) << 2; + add = (code.data & 0x800000); + + reject(!(code.data & 0x1000000), "Related encodings"); // ??? + reject(t == 13 || t == 15 || t2 == 13 || t2 == 15 || t == t2, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 base = context.read_pc() & ~3; + const u32 addr = add ? base + imm32 : base - imm32; + const u64 value = vm::psv::read64(addr); + context.write_gpr(t, (u32)(value)); + context.write_gpr(t2, (u32)(value >> 32)); + } } void ARMv7_instrs::LDRD_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1689,11 +1700,70 @@ void ARMv7_instrs::LDRD_REG(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::LDRH_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + imm32 = (code.data & 0x7c0) >> 5; + index = true; + add = true; + wback = false; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xfff); + index = true; + add = true; + wback = false; + + reject(t == 15, "Unallocated memory hints"); + reject(n == 15, "LDRH (literal)"); + reject(t == 13, "UNPREDICTABLE"); + break; + } + case T3: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff); + index = (code.data & 0x400); + add = (code.data & 0x200); + wback = (code.data & 0x100); + + reject(n == 15, "LDRH (literal)"); + reject(t == 15 && index && !add && !wback, "Unallocated memory hints"); + reject(index && add && !wback, "LDRHT"); + reject(!index && !wback, "UNDEFINED"); + reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + context.write_gpr(t, vm::psv::read16(addr)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } void ARMv7_instrs::LDRH_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1891,7 +1961,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR cond = context.ITSTATE.advance(); d = (code.data & 0x7); m = (code.data & 0x38) >> 3; - shift_n = (code.data & 0x7c0) >> 6; + DecodeImmShift(0, (code.data & 0x7c0) >> 6, &shift_n); reject(!shift_n, "MOV (register)"); break; @@ -1902,7 +1972,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR d = (code.data & 0xf00) >> 8; m = (code.data & 0xf); set_flags = (code.data & 0x100000); - shift_n = (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6; + DecodeImmShift(0, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); reject(!shift_n, "MOV (register)"); reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); @@ -1917,6 +1987,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR bool carry; const u32 res = Shift_C(context.read_gpr(m), SRType_LSL, shift_n, context.APSR.C, carry); context.write_gpr(d, res); + if (set_flags) { context.APSR.N = res >> 31; @@ -1960,6 +2031,7 @@ void ARMv7_instrs::LSL_REG(ARMv7Context& context, const ARMv7Code code, const AR bool carry; const u32 res = Shift_C(context.read_gpr(n), SRType_LSL, (context.read_gpr(m) & 0xff), context.APSR.C, carry); context.write_gpr(d, res); + if (set_flags) { context.APSR.N = res >> 31; @@ -1972,11 +2044,47 @@ void ARMv7_instrs::LSL_REG(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::LSR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, m, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + DecodeImmShift(1, (code.data & 0x7c0) >> 6, &shift_n); + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + DecodeImmShift(1, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 result = Shift_C(context.read_gpr(m), SRType_LSR, shift_n, context.APSR.C, carry); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::LSR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -2049,6 +2157,7 @@ void ARMv7_instrs::MOV_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { context.write_gpr(d, imm32); + if (set_flags) { context.APSR.N = imm32 >> 31; @@ -2102,12 +2211,13 @@ void ARMv7_instrs::MOV_REG(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { - const u32 res = context.read_gpr(m); - context.write_gpr(d, res); + const u32 result = context.read_gpr(m); + context.write_gpr(d, result); + if (set_flags) { - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; //context.APSR.C = ? } } @@ -2319,11 +2429,39 @@ void ARMv7_instrs::ORN_REG(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, n, imm32; + bool set_flags, carry = context.APSR.C; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(n == 15, "MOV (immediate)"); + reject(d == 13 || d == 15 || n == 13, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) | imm32; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::ORR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3252,7 +3390,7 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A cond = context.ITSTATE.advance(); t = (code.data & 0x7); n = (code.data & 0x38) >> 3; - imm32 = (code.data & 0x7c0) >> 4; + imm32 = (code.data & 0x7c0) >> 6; index = true; add = true; wback = false; @@ -3363,11 +3501,43 @@ void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::STRD_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, t2, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + t2 = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff) << 2; + index = (code.data & 0x1000000); + add = (code.data & 0x800000); + wback = (code.data & 0x200000); + + reject(!index && !wback, "Related encodings"); + reject(wback && (n == t || n == t2), "UNPREDICTABLE"); + reject(n == 15 || t == 13 || t == 15 || t2 == 13 || t2 == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 n_value = context.read_gpr(n); + const u32 offset = add ? n_value + imm32 : n_value - imm32; + const u32 addr = index ? offset : n_value; + vm::psv::write64(addr, (u64)context.read_gpr(t2) << 32 | context.read_gpr(t)); + + if (wback) + { + context.write_gpr(n, offset); + } + } } void ARMv7_instrs::STRD_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3382,11 +3552,67 @@ void ARMv7_instrs::STRD_REG(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + imm32 = (code.data & 0x7c0) >> 5; + index = true; + add = true; + wback = false; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xfff); + index = true; + add = true; + wback = false; + + reject(n == 15, "UNDEFINED"); + reject(t == 13 || t == 15, "UNPREDICTABLE"); + break; + } + case T3: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff); + index = (code.data & 0x400); + add = (code.data & 0x200); + wback = (code.data & 0x100); + + reject(index && add && !wback, "STRHT"); + reject(n == 15 || (!index && !wback), "UNDEFINED"); + reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + vm::psv::write16(addr, (u16)context.read_gpr(t)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3560,20 +3786,17 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; + const u32 result = AddWithCarry(context.read_gpr(n), ~imm32, true, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), ~imm32, true, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.read_gpr(n) - imm32); - } } } @@ -3614,21 +3837,18 @@ void ARMv7_instrs::SUB_REG(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 result = AddWithCarry(context.read_gpr(n), ~shifted, true, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), ~shifted, true, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.read_gpr(n) - shifted); - } } } @@ -3683,20 +3903,17 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; + const u32 result = AddWithCarry(context.SP, ~imm32, true, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.SP, ~imm32, true, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.SP - imm32); - } } } @@ -3960,11 +4177,40 @@ void ARMv7_instrs::UMLAL(ARMv7Context& context, const ARMv7Code code, const ARMv void ARMv7_instrs::UMULL(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d0, d1, n, m; + bool set_flags; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d0 = (code.data & 0xf000) >> 12; + d1 = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = false; + + reject(d0 == 13 || d0 == 15 || d1 == 13 || d1 == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + reject(d0 == d1, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u64 result = (u64)context.read_gpr(n) * (u64)context.read_gpr(m); + context.write_gpr(d1, (u32)(result >> 32)); + context.write_gpr(d0, (u32)(result)); + + if (set_flags) + { + context.APSR.N = result >> 63 != 0; + context.APSR.Z = result == 0; + } + } } void ARMv7_instrs::UQADD16(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) diff --git a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h index ad69269a1a..44f1c8214b 100644 --- a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h +++ b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h @@ -2,7 +2,6 @@ struct psv_event_flag_t { - s32 id; char name[32]; u32 attr; u32 pattern; @@ -17,6 +16,9 @@ private: public: psv_event_flag_t(const char* name, u32 attr, u32 pattern); + void on_init(s32 id) {} + void on_stop() {} + }; extern psv_object_list_t g_psv_ef_list; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema.h b/rpcs3/Emu/ARMv7/Modules/psv_sema.h index 83b3b99b24..95608c3c04 100644 --- a/rpcs3/Emu/ARMv7/Modules/psv_sema.h +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema.h @@ -2,7 +2,6 @@ struct psv_sema_t { - s32 id; char name[32]; u32 attr; s32 value; @@ -18,6 +17,8 @@ private: public: psv_sema_t(const char* name, u32 attr, s32 init_value, s32 max_value); + void on_init(s32 id) {} + void on_stop() {} }; diff --git a/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp b/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp index a845595c87..51158c0226 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp @@ -6,21 +6,21 @@ extern psv_log_base sceSysmodule; s32 sceSysmoduleLoadModule(u16 id) { - sceSysmodule.Error("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id); + sceSysmodule.Warning("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id); return SCE_OK; // loading succeeded } s32 sceSysmoduleUnloadModule(u16 id) { - sceSysmodule.Error("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id); + sceSysmodule.Warning("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id); return SCE_OK; // unloading succeeded } s32 sceSysmoduleIsLoaded(u16 id) { - sceSysmodule.Error("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id); + sceSysmodule.Warning("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id); return SCE_OK; // module is loaded } diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h index 278bc521dd..5be66688e0 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.h +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -80,7 +80,7 @@ public: psv_uid_t id = psv_uid_t::make(1); // odd number id.type = uid_class; // set type id.number = j; // set position - data->id = id.uid; // save UID + data->on_init(id.uid); // save UID return id.uid; // return UID } } @@ -111,9 +111,14 @@ public: { std::lock_guard lock(m_mutex); - for (auto& value : m_data) + for (auto& object : m_data) { - value = nullptr; + if (object) + { + object->on_stop(); + } + + object = nullptr; } m_hint = 0; From d5bbea097badf32a2c3dcc002dd22b39f6055364 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 4 Feb 2015 00:34:18 +0300 Subject: [PATCH 03/15] ARMv7: new instructions, bugfix ADC_IMM, ADR, AND_IMM, EOR_REG, LDRB_REG --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 4 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 186 ++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 09ac2275d8..f143458d48 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -151,8 +151,8 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM), ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM), - ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM), - ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM), + ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM, SKIP_IF( BF(16, 19) == 15 )), + ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM, SKIP_IF( BF(16, 19) == 15 || BF(8, 10) == 6 || (c & 0xf07ff) == 0xd0304 || (c & 0x500) == 0 )), ARMv7_OP4(0x0e50, 0x0000, 0x0410, 0x0000, A1, LDR_IMM), ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT), ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT), diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index eabed09520..94c5f79e83 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -364,11 +364,40 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 void ARMv7_instrs::ADC_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, n, imm32; + bool set_flags; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry, overflow; + const u32 result = AddWithCarry(context.read_gpr(n), imm32, context.APSR.C, carry, overflow); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + context.APSR.V = overflow; + } + } } void ARMv7_instrs::ADC_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -661,21 +690,87 @@ void ARMv7_instrs::ADD_SPR(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::ADR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, imm32; + bool add; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x700) >> 8; + imm32 = (code.data & 0xff) << 2; + add = true; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + imm32 = (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff); + add = false; + + reject(d == 13 || d == 15, "UNPREDICTABLE"); + break; + } + case T3: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + imm32 = (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff); + add = true; + + reject(d == 13 || d == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 base = context.read_pc() & ~3; + const u32 result = add ? base + imm32 : base - imm32; + context.write_gpr(d, result); + } } void ARMv7_instrs::AND_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, n, imm32; + bool set_flags, carry = context.APSR.C; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(d == 15 && set_flags, "TST (immediate)"); + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) & imm32; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::AND_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1275,11 +1370,51 @@ void ARMv7_instrs::EOR_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::EOR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 15 && set_flags, "TEQ (register)"); + reject(d == 13 || d == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shifted = Shift_C(context.read_gpr(m), shift_t, shift_n, context.APSR.C, carry); + const u32 result = context.read_gpr(n) ^ shifted; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::EOR_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1496,8 +1631,8 @@ void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const AR index = true; add = true; wback = false; - shift_t = (code.data & 0x30) >> 4; - shift_n = 0; + shift_t = SRType_LSL; + shift_n = (code.data & 0x30) >> 4; reject(n == 15, "LDR (literal)"); reject(m == 13 || m == 15, "UNPREDICTABLE"); @@ -1583,7 +1718,6 @@ void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const A { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - context.write_gpr(t, vm::psv::read8(addr)); if (wback) @@ -1604,11 +1738,57 @@ void ARMv7_instrs::LDRB_LIT(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::LDRB_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, m, shift_t, shift_n; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + m = (code.data & 0x1c0) >> 6; + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = (code.data & 0x30) >> 4; + + reject(t == 15, "PLD"); + reject(n == 15, "LDRB (literal)"); + reject(t == 13 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; + const u32 addr = index ? offset_addr : context.read_gpr(n); + context.write_gpr(t, vm::psv::read8(addr)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } From e3f55a75a32cabfe7814fcc4c4cedc7be8cb15c3 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 4 Feb 2015 15:16:10 +0300 Subject: [PATCH 04/15] TTY output improved; ARMv7: new instructions ADC_REG, MVN_REG, ORR_REG, ROR_IMM, ROR_REG, TST_IMM, armv7_fmt improved --- Utilities/Log.cpp | 6 +- Utilities/StrFmt.cpp | 33 +++- Utilities/StrFmt.h | 2 + rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 130 ++++++++------- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 230 +++++++++++++++++++++++++++ rpcs3/Emu/ARMv7/ARMv7Interpreter.h | 4 + rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 97 +++++++++-- 7 files changed, 426 insertions(+), 76 deletions(-) diff --git a/Utilities/Log.cpp b/Utilities/Log.cpp index 44ed7dedf7..0b49521e09 100644 --- a/Utilities/Log.cpp +++ b/Utilities/Log.cpp @@ -109,7 +109,11 @@ struct FileListener : LogListener if (mPrependChannelName) { text.insert(0, gTypeNameTable[static_cast(msg.mType)].mName); - + + if (msg.mType == Log::TTY) + { + text = fmt::escape(text) + "\n"; + } } mFile.Write(text); } diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 6ae236b922..a4a43b8624 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -179,7 +179,7 @@ std::string fmt::replace_all(const std::string &src, const std::string& from, co pos += to.length(); } - return src; + return target; } //TODO: move this wx Stuff somewhere else @@ -339,3 +339,34 @@ std::string fmt::tolower(std::string source) return source; } + +std::string fmt::toupper(std::string source) +{ + std::transform(source.begin(), source.end(), source.begin(), ::toupper); + + return source; +} + +std::string fmt::escape(std::string source) +{ + const std::pair escape_list[] = + { + { "\\", "\\\\" }, + { "\a", "\\a" }, + { "\b", "\\b" }, + { "\f", "\\f" }, + { "\n", "\\n" }, + { "\r", "\\r" }, + { "\t", "\\t" }, + { "\v", "\\v" }, + }; + + source = fmt::replace_all(source, escape_list); + + for (char c = 0; c < 32; c++) + { + source = fmt::replace_all(source, std::string(1, c), fmt::Format("\\x%02X", c)); + } + + return source; +} diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index bd4059ab86..4015d5077b 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -579,4 +579,6 @@ namespace fmt std::string merge(std::vector source, const std::string& separator); std::string merge(std::initializer_list> sources, const std::string& separator); std::string tolower(std::string source); + std::string toupper(std::string source); + std::string escape(std::string source); } diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index f143458d48..cbc6a5d553 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -30,137 +30,147 @@ struct ARMv7_opcode_t const ARMv7_opcode_t ARMv7_opcode_table[] = { - ARMv7_OP4(0xffff, 0x0000, 0xf870, 0x0000, T1, HACK), // "Undefined" Thumb opcode used + ARMv7_OP4(0xffff, 0x0000, 0xf870, 0x0000, T1, HACK, nullptr), // "Undefined" Thumb opcode used ARMv7_OP4(0x0ff0, 0x00f0, 0x0070, 0x0090, A1, HACK), // "Undefined" ARM opcode used - ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM), + ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM, nullptr), ARMv7_OP4(0x0fe0, 0x0000, 0x02a0, 0x0000, A1, ADC_IMM), - ARMv7_OP2(0xffc0, 0x4040, T1, ADC_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG), + ARMv7_OP2(0xffc0, 0x4040, T1, ADC_REG, nullptr), + ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG, nullptr), ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR), - ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM), - ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM), + ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM, nullptr), + ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM, nullptr), ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )), ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM, SKIP_IF( (BF(16, 19) & 13) == 13 )), ARMv7_OP4(0x0fe0, 0x0000, 0x0280, 0x0000, A1, ADD_IMM), - ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG), + ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG, nullptr), ARMv7_OP2(0xff00, 0x4400, T2, ADD_REG, SKIP_IF( (c & 0x87) == 0x85 || BF(3, 6) == 13 )), ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )), ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR), - ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI), - ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI), + ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI, nullptr), + ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI, nullptr), ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI, SKIP_IF( BF(8, 11) == 15 && BT(20) )), - ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI), + ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI, nullptr), ARMv7_OP4(0x0fef, 0x0000, 0x028d, 0x0000, A1, ADD_SPI), - ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR), + ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR, nullptr), ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR, SKIP_IF( BF(3, 6) == 13 )), - ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR), + ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR, nullptr), ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR), - ARMv7_OP2(0xf800, 0xa000, T1, ADR), - ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR), - ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR), + ARMv7_OP2(0xf800, 0xa000, T1, ADR, nullptr), + ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR, nullptr), + ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR, nullptr), ARMv7_OP4(0x0fff, 0x0000, 0x028f, 0x0000, A1, ADR), ARMv7_OP4(0x0fff, 0x0000, 0x024f, 0x0000, A2, ADR), - ARMv7_OP4(0xfbe0, 0x8000, 0xf000, 0x0000, T1, AND_IMM), + ARMv7_OP4(0xfbe0, 0x8000, 0xf000, 0x0000, T1, AND_IMM, SKIP_IF( BF(8, 11) == 15 && BT(20) )), ARMv7_OP4(0x0fe0, 0x0000, 0x0200, 0x0000, A1, AND_IMM), - ARMv7_OP2(0xffc0, 0x4000, T1, AND_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xea00, 0x0000, T2, AND_REG), + ARMv7_OP2(0xffc0, 0x4000, T1, AND_REG, nullptr), + ARMv7_OP4(0xffe0, 0x8000, 0xea00, 0x0000, T2, AND_REG, SKIP_IF( BF(8, 11) == 15 && BT(20) )), ARMv7_OP4(0x0fe0, 0x0010, 0x0000, 0x0000, A1, AND_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0000, 0x0010, A1, AND_RSR), - ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM), - ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM), + ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM, nullptr), + ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM, nullptr), ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0040, A1, ASR_IMM), - ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG), - ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG), + ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG, nullptr), + ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG, nullptr), ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0050, A1, ASR_REG), - ARMv7_OP2(0xf000, 0xd000, T1, B), - ARMv7_OP2(0xf800, 0xe000, T2, B), - ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B), - ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B), + ARMv7_OP2(0xf000, 0xd000, T1, B, SKIP_IF( BF(9, 11) == 0x7 )), + ARMv7_OP2(0xf800, 0xe000, T2, B, nullptr), + ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B, SKIP_IF( BF(23, 25) == 0x7 )), + ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B, nullptr), ARMv7_OP4(0x0f00, 0x0000, 0x0a00, 0x0000, A1, B), - ARMv7_OP4(0xffff, 0x8020, 0xf36f, 0x0000, T1, BFC), + ARMv7_OP4(0xffff, 0x8020, 0xf36f, 0x0000, T1, BFC, nullptr), ARMv7_OP4(0x0fe0, 0x007f, 0x07c0, 0x001f, A1, BFC), - ARMv7_OP4(0xfff0, 0x8020, 0xf360, 0x0000, T1, BFI), + + ARMv7_OP4(0xfff0, 0x8020, 0xf360, 0x0000, T1, BFI, SKIP_IF( BF(16, 19) == 15 )), ARMv7_OP4(0x0fe0, 0x0070, 0x07c0, 0x0010, A1, BFI), - ARMv7_OP4(0xfbe0, 0x8000, 0xf020, 0x0000, T1, BIC_IMM), + ARMv7_OP4(0xfbe0, 0x8000, 0xf020, 0x0000, T1, BIC_IMM, nullptr), ARMv7_OP4(0x0fe0, 0x0000, 0x03c0, 0x0000, A1, BIC_IMM), - ARMv7_OP2(0xffc0, 0x4380, T1, BIC_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG), + ARMv7_OP2(0xffc0, 0x4380, T1, BIC_REG, nullptr), + ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG, nullptr), ARMv7_OP4(0x0fe0, 0x0010, 0x01c0, 0x0000, A1, BIC_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x01c0, 0x0010, A1, BIC_RSR), - ARMv7_OP2(0xff00, 0xbe00, T1, BKPT), + ARMv7_OP2(0xff00, 0xbe00, T1, BKPT, nullptr), ARMv7_OP4(0x0ff0, 0x00f0, 0x0120, 0x0070, A1, BKPT), - ARMv7_OP4(0xf800, 0xd000, 0xf000, 0xd000, T1, BL), + ARMv7_OP4(0xf800, 0xd000, 0xf000, 0xd000, T1, BL, nullptr), ARMv7_OP4(0x0f00, 0x0000, 0x0b00, 0x0000, A1, BL), - ARMv7_OP2(0xff80, 0x4780, T1, BLX), - ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX), + ARMv7_OP2(0xff80, 0x4780, T1, BLX, nullptr), + ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX, nullptr), ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff30, A1, BLX), ARMv7_OP4(0xfe00, 0x0000, 0xfa00, 0x0000, A2, BLX), - ARMv7_OP2(0xff87, 0x4700, T1, BX), + ARMv7_OP2(0xff87, 0x4700, T1, BX, nullptr), ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff10, A1, BX), - ARMv7_OP2(0xf500, 0xb100, T1, CB_Z), + ARMv7_OP2(0xf500, 0xb100, T1, CB_Z, nullptr), - ARMv7_OP4(0xfff0, 0xf0f0, 0xfab0, 0xf080, T1, CLZ), + ARMv7_OP4(0xfff0, 0xf0f0, 0xfab0, 0xf080, T1, CLZ, nullptr), ARMv7_OP4(0x0fff, 0x0ff0, 0x016f, 0x0f10, A1, CLZ), - ARMv7_OP4(0xfbf0, 0x8f00, 0xf110, 0x0f00, T1, CMN_IMM), + ARMv7_OP4(0xfbf0, 0x8f00, 0xf110, 0x0f00, T1, CMN_IMM, nullptr), ARMv7_OP4(0x0ff0, 0xf000, 0x0370, 0x0000, A1, CMN_IMM), - ARMv7_OP2(0xffc0, 0x42c0, T1, CMN_REG), - ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG), + ARMv7_OP2(0xffc0, 0x42c0, T1, CMN_REG, nullptr), + ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG, nullptr), ARMv7_OP4(0x0ff0, 0xf010, 0x0170, 0x0000, A1, CMN_REG), ARMv7_OP4(0x0ff0, 0xf090, 0x0170, 0x0010, A1, CMN_RSR), - ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM), - ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM), + ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM, nullptr), + ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM, nullptr), ARMv7_OP4(0x0ff0, 0xf000, 0x0350, 0x0000, A1, CMP_IMM), - ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG), - ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG), - ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG), + ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG, nullptr), + ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG, nullptr), + ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG, nullptr), ARMv7_OP4(0x0ff0, 0xf010, 0x0150, 0x0000, A1, CMP_REG), ARMv7_OP4(0x0ff0, 0xf090, 0x0150, 0x0010, A1, CMP_RSR), - ARMv7_OP4(0xfbe0, 0x8000, 0xf080, 0x0000, T1, EOR_IMM), + ARMv7_OP4(0xffff, 0xfff0, 0xf3af, 0x80f0, T1, DBG, nullptr), + ARMv7_OP4(0x0fff, 0xfff0, 0x0320, 0xf0f0, A1, DBG), + + ARMv7_OP4(0xffff, 0xfff0, 0xf3bf, 0x8f50, T1, DMB, nullptr), + ARMv7_OP4(0xffff, 0xfff0, 0xf57f, 0xf050, A1, DMB), + + ARMv7_OP4(0xffff, 0xfff0, 0xf3bf, 0x8f40, T1, DSB, nullptr), + ARMv7_OP4(0xffff, 0xfff0, 0xf57f, 0xf040, A1, DSB), + + ARMv7_OP4(0xfbe0, 0x8000, 0xf080, 0x0000, T1, EOR_IMM, SKIP_IF( BF(8, 11) == 15 && BT(20) )), ARMv7_OP4(0x0fe0, 0x0000, 0x0220, 0x0000, A1, EOR_IMM), - ARMv7_OP2(0xffc0, 0x4040, T1, EOR_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xea80, 0x0000, T2, EOR_REG), + ARMv7_OP2(0xffc0, 0x4040, T1, EOR_REG, nullptr), + ARMv7_OP4(0xffe0, 0x8000, 0xea80, 0x0000, T2, EOR_REG, SKIP_IF( BF(8, 11) == 15 && BT(20) )), ARMv7_OP4(0x0fe0, 0x0010, 0x0020, 0x0000, A1, EOR_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0020, 0x0010, A1, EOR_RSR), ARMv7_OP2(0xff00, 0xbf00, T1, IT, SKIP_IF( BF(0, 3) == 0 )), - ARMv7_OP2(0xf800, 0xc800, T1, LDM), - ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM), + ARMv7_OP2(0xf800, 0xc800, T1, LDM, nullptr), + ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM, SKIP_IF( BT(21) && BF(16, 19) == 13 )), ARMv7_OP4(0x0fd0, 0x0000, 0x0890, 0x0000, A1, LDM), ARMv7_OP4(0x0fd0, 0x0000, 0x0810, 0x0000, A1, LDMDA), - ARMv7_OP4(0xffd0, 0x2000, 0xe910, 0x0000, T1, LDMDB), + ARMv7_OP4(0xffd0, 0x2000, 0xe910, 0x0000, T1, LDMDB, nullptr), ARMv7_OP4(0x0fd0, 0x0000, 0x0910, 0x0000, A1, LDMDB), ARMv7_OP4(0x0fd0, 0x0000, 0x0990, 0x0000, A1, LDMIB), - ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM), - ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM), + ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM, nullptr), + ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM, nullptr), ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM, SKIP_IF( BF(16, 19) == 15 )), ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM, SKIP_IF( BF(16, 19) == 15 || BF(8, 10) == 6 || (c & 0xf07ff) == 0xd0304 || (c & 0x500) == 0 )), ARMv7_OP4(0x0e50, 0x0000, 0x0410, 0x0000, A1, LDR_IMM), - ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT), - ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT), + ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT, nullptr), + ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT, nullptr), ARMv7_OP4(0x0f7f, 0x0000, 0x051f, 0x0000, A1, LDR_LIT), - ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG), - ARMv7_OP4(0xfff0, 0x0fc0, 0xf850, 0x0000, T2, LDR_REG), + ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG, nullptr), + ARMv7_OP4(0xfff0, 0x0fc0, 0xf850, 0x0000, T2, LDR_REG, SKIP_IF( BF(16, 19) == 15 )), ARMv7_OP4(0x0e50, 0x0010, 0x0610, 0x0000, A1, LDR_REG), - + ARMv7_OP2(0xf800, 0x7800, T1, LDRB_IMM), ARMv7_OP4(0xfff0, 0x0000, 0xf890, 0x0000, T2, LDRB_IMM), ARMv7_OP4(0xfff0, 0x0800, 0xf810, 0x0800, T3, LDRB_IMM), @@ -280,7 +290,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xfbe0, 0x8000, 0xf040, 0x0000, T1, ORR_IMM), ARMv7_OP4(0x0fe0, 0x0000, 0x0380, 0x0000, A1, ORR_IMM), ARMv7_OP2(0xffc0, 0x4300, T1, ORR_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xea40, 0x0000, T2, ORR_REG), + ARMv7_OP4(0xffe0, 0x8000, 0xea40, 0x0000, T2, ORR_REG, SKIP_IF( BF(16, 19) == 15 )), ARMv7_OP4(0x0fe0, 0x0010, 0x0180, 0x0000, A1, ORR_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0180, 0x0010, A1, ORR_RSR), diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 94c5f79e83..aede0d0488 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -402,11 +402,51 @@ void ARMv7_instrs::ADC_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::ADC_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 13 || d == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry, overflow; + const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 result = AddWithCarry(context.read_gpr(n), shifted, context.APSR.C, carry, overflow); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + context.APSR.V = overflow; + } + } } void ARMv7_instrs::ADC_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1359,6 +1399,34 @@ void ARMv7_instrs::CMP_RSR(ARMv7Context& context, const ARMv7Code code, const AR } +void ARMv7_instrs::DBG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) +{ + switch (type) + { + case A1: throw __FUNCTION__; + default: throw __FUNCTION__; + } +} + +void ARMv7_instrs::DMB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) +{ + switch (type) + { + case A1: throw __FUNCTION__; + default: throw __FUNCTION__; + } +} + +void ARMv7_instrs::DSB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) +{ + switch (type) + { + case A1: throw __FUNCTION__; + default: throw __FUNCTION__; + } +} + + void ARMv7_instrs::EOR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { switch (type) @@ -2541,11 +2609,49 @@ void ARMv7_instrs::MVN_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::MVN_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shifted = Shift_C(context.read_gpr(m), shift_t, shift_n, context.APSR.C, carry); + const u32 result = ~shifted; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::MVN_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -2646,11 +2752,51 @@ void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::ORR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(n == 15, "ROR (immediate)"); + reject(d == 13 || d == 15 || n == 13 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shifted = Shift_C(context.read_gpr(m), shift_t, shift_n, context.APSR.C, carry); + const u32 result = context.read_gpr(n) | shifted; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::ORR_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -2936,20 +3082,84 @@ void ARMv7_instrs::REVSH(ARMv7Context& context, const ARMv7Code code, const ARMv void ARMv7_instrs::ROR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, m, shift_n; + bool set_flags; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + const u32 shift_t = DecodeImmShift(3, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(shift_t == SRType_RRX, "RRX"); + reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 result = Shift_C(context.read_gpr(m), SRType_ROR, shift_n, context.APSR.C, carry); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::ROR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + break; + } + case T2: + { + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + + reject(d == 13 || d == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shift_n = context.read_gpr(m) & 0xff; + const u32 result = Shift_C(context.read_gpr(n), SRType_ROR, shift_n, context.APSR.C, carry); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } @@ -4212,11 +4422,31 @@ void ARMv7_instrs::TEQ_RSR(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::TST_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool carry = context.APSR.C; + u32 cond, n, imm32; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0xf0000) >> 16; + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) & imm32; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } } void ARMv7_instrs::TST_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index 2a18646d42..01521ce9d5 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -79,6 +79,10 @@ namespace ARMv7_instrs void CMP_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); void CMP_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); + void DBG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); + void DMB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); + void DSB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); + void EOR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); void EOR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); void EOR_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index cf3725a3f9..3e5b21c44e 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -24,12 +24,63 @@ std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g case '%': { const auto start = fmt - 1; - const bool number_sign = *fmt == '#' ? fmt++, true : false; - switch (*fmt++) + // read flags + const bool plus_sign = *fmt == '+' ? fmt++, true : false; + const bool minus_sign = *fmt == '-' ? fmt++, true : false; + const bool space_sign = *fmt == ' ' ? fmt++, true : false; + const bool number_sign = *fmt == '#' ? fmt++, true : false; + const bool zero_padding = *fmt == '0' ? fmt++, true : false; + + // read width + const u32 width = [&]() -> u32 + { + u32 width = 0; + + if (*fmt == '*') + { + fmt++; + return context.get_next_gpr_arg(g_count, f_count, v_count); + } + + while (*fmt - '0' < 10) + { + width = width * 10 + (*fmt++ - '0'); + } + + return width; + }(); + + // read precision + const u32 prec = [&]() -> u32 + { + u32 prec = 0; + + if (*fmt != '.') + { + return 0; + } + + if (*++fmt == '*') + { + fmt++; + return context.get_next_gpr_arg(g_count, f_count, v_count); + } + + while (*fmt - '0' < 10) + { + prec = prec * 10 + (*fmt++ - '0'); + } + + return prec; + }(); + + switch (char cf = *fmt++) { case '%': { + if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break; + result += '%'; continue; } @@ -39,20 +90,38 @@ std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g // signed decimal const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count); + if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break; + result += fmt::to_sdec(value); continue; } case 'x': + case 'X': { // hexadecimal const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count); + if (plus_sign || minus_sign || space_sign || prec) break; + if (number_sign && value) { - result += "0x"; + result += cf == 'x' ? "0x" : "0X"; } - result += fmt::to_hex(value); + const std::string& hex = cf == 'x' ? fmt::to_hex(value) : fmt::toupper(fmt::to_hex(value)); + + if (hex.length() >= width) + { + result += hex; + } + else if (zero_padding) + { + result += std::string(width - hex.length(), '0') + hex; + } + else + { + result += hex + std::string(width - hex.length(), ' '); + } continue; } case 's': @@ -60,14 +129,14 @@ std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g // string auto string = vm::psv::ptr::make(context.get_next_gpr_arg(g_count, f_count, v_count)); + if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break; + result += string.get_ptr(); continue; } - default: - { - throw fmt::Format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr()); - } } + + throw fmt::format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr()); } } @@ -127,21 +196,21 @@ namespace sce_libc_func void printf(ARMv7Context& context, vm::psv::ptr fmt) // va_args... { sceLibc.Warning("printf(fmt=0x%x)", fmt); + sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr()); - sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr()); + const std::string& result = armv7_fmt(context, fmt, 1, 0, 0); + sceLibc.Log("*** -> '%s'", result); - LOG_NOTICE(TTY, armv7_fmt(context, fmt, 1, 0, 0)); + LOG_NOTICE(TTY, result); } void sprintf(ARMv7Context& context, vm::psv::ptr str, vm::psv::ptr fmt) // va_args... { sceLibc.Warning("sprintf(str=0x%x, fmt=0x%x)", str, fmt); - - sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr()); + sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr()); const std::string& result = armv7_fmt(context, fmt, 2, 0, 0); - - sceLibc.Notice("*** res -> '%s'", result); + sceLibc.Log("*** -> '%s'", result); ::memcpy(str.get_ptr(), result.c_str(), result.size() + 1); } From 819c955cca888368546f195d11aff3d4c2c5d026 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 5 Feb 2015 02:52:47 +0300 Subject: [PATCH 05/15] ARMv7: partial disasm functionality, bugfix --- Utilities/Log.cpp | 6 +- Utilities/StrFmt.cpp | 4 +- rpcs3/Emu/ARMv7/ARMv7Context.h | 28 +- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 2 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 671 ++++++++++++++++++++++++--- rpcs3/Emu/ARMv7/ARMv7Interpreter.h | 3 +- rpcs3/Emu/ARMv7/PSVFuncList.cpp | 21 +- rpcs3/Emu/ARMv7/PSVFuncList.h | 6 +- rpcs3/Emu/System.cpp | 10 + 9 files changed, 651 insertions(+), 100 deletions(-) diff --git a/Utilities/Log.cpp b/Utilities/Log.cpp index 0b49521e09..5aaf98579d 100644 --- a/Utilities/Log.cpp +++ b/Utilities/Log.cpp @@ -112,7 +112,11 @@ struct FileListener : LogListener if (msg.mType == Log::TTY) { - text = fmt::escape(text) + "\n"; + text = fmt::escape(text); + if (text[text.length() - 1] != '\n') + { + text += '\n'; + } } } mFile.Write(text); diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index a4a43b8624..f3f74a327d 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -355,7 +355,7 @@ std::string fmt::escape(std::string source) { "\a", "\\a" }, { "\b", "\\b" }, { "\f", "\\f" }, - { "\n", "\\n" }, + { "\n", "\\n\n" }, { "\r", "\\r" }, { "\t", "\\t" }, { "\v", "\\v" }, @@ -365,7 +365,7 @@ std::string fmt::escape(std::string source) for (char c = 0; c < 32; c++) { - source = fmt::replace_all(source, std::string(1, c), fmt::Format("\\x%02X", c)); + if (c != '\n') source = fmt::replace_all(source, std::string(1, c), fmt::Format("\\x%02X", c)); } return source; diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 5ca662939f..78c0ab0e43 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -10,17 +10,15 @@ enum ARMv7InstructionSet ThumbEE }; +enum armv7_debug_flags : u32 +{ + DF_DISASM = 1 << 0, + DF_PRINT = 1 << 1, + DF_NO_EXE = 1 << 2, +}; + struct ARMv7Context { - ARMv7Thread& thread; - - ARMv7Context(ARMv7Thread& thread) : thread(thread) {} - - void write_pc(u32 value); - u32 read_pc(); - u32 get_stack_arg(u32 pos); - void fast_call(u32 addr); - union { u32 GPR[15]; @@ -127,6 +125,18 @@ struct ARMv7Context std::array counters; + ARMv7Thread& thread; + + u32 debug; // debug flags + std::string debug_str; + + ARMv7Context(ARMv7Thread& thread) : thread(thread), debug(DF_DISASM | DF_PRINT) {} + + void write_pc(u32 value); + u32 read_pc(); + u32 get_stack_arg(u32 pos); + void fast_call(u32 addr); + void write_gpr(u32 n, u32 value) { assert(n < 16); diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index cbc6a5d553..4ae428e985 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -35,7 +35,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM, nullptr), ARMv7_OP4(0x0fe0, 0x0000, 0x02a0, 0x0000, A1, ADC_IMM), - ARMv7_OP2(0xffc0, 0x4040, T1, ADC_REG, nullptr), + ARMv7_OP2(0xffc0, 0x4140, T1, ADC_REG, nullptr), ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG, nullptr), ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR), diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index aede0d0488..1d1add9481 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include #include "Utilities/Log.h" #include "Emu/System.h" #include "Emu/Memory/Memory.h" @@ -10,6 +11,8 @@ #define reject(cond, info) { if (cond) Error(__FUNCTION__, code, type, #cond, info); } +std::map g_armv7_dump; + namespace ARMv7_instrs { template @@ -63,7 +66,7 @@ namespace ARMv7_instrs SRType DecodeImmShift(u32 type, u32 imm5, u32* shift_n) { - SRType shift_t = SRType_None; + SRType shift_t; switch (type) { @@ -80,25 +83,28 @@ namespace ARMv7_instrs shift_t = SRType_ROR; if (shift_n) *shift_n = imm5; } break; + + default: throw __FUNCTION__; } return shift_t; } - SRType DecodeRegShift(u8 type) - { - SRType shift_t = SRType_None; + //SRType DecodeRegShift(u8 type) + //{ + // SRType shift_t; - switch (type) - { - case 0: shift_t = SRType_LSL; break; - case 1: shift_t = SRType_LSR; break; - case 2: shift_t = SRType_ASR; break; - case 3: shift_t = SRType_ROR; break; - } + // switch (type) + // { + // case 0: shift_t = SRType_LSL; break; + // case 1: shift_t = SRType_LSR; break; + // case 2: shift_t = SRType_ASR; break; + // case 3: shift_t = SRType_ROR; break; + // default: throw __FUNCTION__; + // } - return shift_t; - } + // return shift_t; + //} u32 LSL_C(u32 x, s32 shift, bool& carry_out) { @@ -129,7 +135,7 @@ namespace ARMv7_instrs s32 ASR_C(s32 x, s32 shift, bool& carry_out) { assert(shift > 0); - carry_out = shift <= 32 ? x & (1 << (shift - 1)) : false; + carry_out = shift <= 32 ? x & (1 << (shift - 1)) : x < 0; return shift < 32 ? x >> shift : x >> 31; } @@ -142,8 +148,9 @@ namespace ARMv7_instrs u32 ROR_C(u32 x, s32 shift, bool& carry_out) { assert(shift); - carry_out = x & (1 << (shift - 1)); - return x >> shift | x << (32 - shift); + const u32 result = x >> shift | x << (32 - shift); + carry_out = result >> 31; + return result; } u32 ROR_(u32 x, s32 shift) @@ -230,7 +237,7 @@ namespace ARMv7_instrs u32 ThumbExpandImm(u32 imm12) { - bool carry; + bool carry = false; return ThumbExpandImm_C(imm12, carry, carry); } @@ -240,13 +247,13 @@ namespace ARMv7_instrs switch (cond >> 1) { - case 0: result = context.APSR.Z == 1; break; - case 1: result = context.APSR.C == 1; break; - case 2: result = context.APSR.N == 1; break; - case 3: result = context.APSR.V == 1; break; - case 4: result = context.APSR.C == 1 && context.APSR.Z == 0; break; - case 5: result = context.APSR.N == context.APSR.V; break; - case 6: result = context.APSR.N == context.APSR.V && context.APSR.Z == 0; break; + case 0: result = (context.APSR.Z == 1); break; + case 1: result = (context.APSR.C == 1); break; + case 2: result = (context.APSR.N == 1); break; + case 3: result = (context.APSR.V == 1); break; + case 4: result = (context.APSR.C == 1) && (context.APSR.Z == 0); break; + case 5: result = (context.APSR.N == context.APSR.V); break; + case 6: result = (context.APSR.N == context.APSR.V) && (context.APSR.Z == 0); break; case 7: return true; } @@ -276,6 +283,137 @@ namespace ARMv7_instrs throw fmt::format("%s(%s) error: %s (%s)", func, format_encoding(type), info, cond); } + + bool process_debug(ARMv7Context& context) + { + if (context.debug & DF_PRINT) + { + auto pos = context.debug_str.find(' '); + if (pos != std::string::npos && pos < 8) + { + context.debug_str.insert(pos, 8 - pos, ' '); + } + + context.debug_str = fmt::format("0x%08x: %s", context.thread.PC, context.debug_str); + + LV2_LOCK(0); + + auto found = g_armv7_dump.find(context.thread.PC); + if (found != g_armv7_dump.end()) + { + if (found->second != context.debug_str) + { + throw context.debug_str; + } + } + else + { + g_armv7_dump[context.thread.PC] = context.debug_str; + } + } + + if (context.debug & DF_NO_EXE) + { + return true; + } + + return false; + } + + const char* fmt_cond(u32 cond) + { + switch (cond) + { + case 0: return "eq"; + case 1: return "ne"; + case 2: return "cs"; + case 3: return "cc"; + case 4: return "mi"; + case 5: return "pl"; + case 6: return "vs"; + case 7: return "vc"; + case 8: return "hi"; + case 9: return "ls"; + case 10: return "ge"; + case 11: return "lt"; + case 12: return "gt"; + case 13: return "le"; + case 14: return ""; + default: return "???"; + } + } + + const char* fmt_it(u32 state) + { + switch (state & ~0x10) + { + case 0x8: return ""; + + case 0x4: return state & 0x10 ? "e" : "t"; + case 0xc: return state & 0x10 ? "t" : "e"; + + case 0x2: return state & 0x10 ? "ee" : "tt"; + case 0x6: return state & 0x10 ? "et" : "te"; + case 0xa: return state & 0x10 ? "te" : "et"; + case 0xe: return state & 0x10 ? "tt" : "ee"; + + case 0x1: return state & 0x10 ? "eee" : "ttt"; + case 0x3: return state & 0x10 ? "eet" : "tte"; + case 0x5: return state & 0x10 ? "ete" : "tet"; + case 0x7: return state & 0x10 ? "ett" : "tee"; + case 0x9: return state & 0x10 ? "tee" : "ett"; + case 0xb: return state & 0x10 ? "tet" : "ete"; + case 0xd: return state & 0x10 ? "tte" : "eet"; + case 0xf: return state & 0x10 ? "ttt" : "eee"; + + default: return "???"; + } + } + + const char* fmt_reg(u32 reg) + { + switch (reg) + { + case 0: return "r0"; + case 1: return "r1"; + case 2: return "r2"; + case 3: return "r3"; + case 4: return "r4"; + case 5: return "r5"; + case 6: return "r6"; + case 7: return "r7"; + case 8: return "r8"; + case 9: return "r9"; + case 10: return "r10"; + case 11: return "r11"; + case 12: return "r12"; + case 13: return "sp"; + case 14: return "lr"; + case 15: return "pc"; + default: return "???"; + } + } + + std::string fmt_shift(u32 type, u32 amount) + { + assert(type != SRType_RRX || amount == 1); + assert(amount <= 32); + + if (amount) + { + switch (type) + { + case SRType_LSL: return ",lsl #" + fmt::to_udec(amount); + case SRType_LSR: return ",lsr #" + fmt::to_udec(amount); + case SRType_ASR: return ",asr #" + fmt::to_udec(amount); + case SRType_ROR: return ",ror #" + fmt::to_udec(amount); + case SRType_RRX: return ",rrx"; + default: return ",?????"; + } + } + + return{}; + } } void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code) @@ -311,6 +449,12 @@ void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("hack%s %s", fmt_cond(cond), get_psv_func_by_index(func)->name); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { execute_psv_func_by_index(context, func); @@ -341,6 +485,12 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mrc%s p%d,%d,r%d,c%d,c%d,%d", fmt_cond(cond), cp, opc1, t, cn, cm, opc2); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { // APSR flags are written if t = 15 @@ -358,7 +508,7 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 return; } - throw fmt::format("Bad instruction: mrc p%d,%d,r%d,c%d,c%d,%d", cp, opc1, t, cn, cm, opc2); + throw fmt::format("Bad instruction: mrc%s p%d,%d,r%d,c%d,c%d,%d", fmt_cond(cond), cp, opc1, t, cn, cm, opc2); } } @@ -384,6 +534,12 @@ void ARMv7_instrs::ADC_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adc%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -432,6 +588,12 @@ void ARMv7_instrs::ADC_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adc%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -511,6 +673,12 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -576,6 +744,12 @@ void ARMv7_instrs::ADD_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -650,6 +824,12 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s (spi)", set_flags ? "s" : "", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -710,6 +890,12 @@ void ARMv7_instrs::ADD_SPR(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s (spr)", set_flags ? "s" : "", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -767,10 +953,17 @@ void ARMv7_instrs::ADR(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + const u32 base = context.read_pc() & ~3; + const u32 result = add ? base + imm32 : base - imm32; + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adr%s r%d, 0x%08x", fmt_cond(cond), d, result); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { - const u32 base = context.read_pc() & ~3; - const u32 result = add ? base + imm32 : base - imm32; context.write_gpr(d, result); } } @@ -799,6 +992,12 @@ void ARMv7_instrs::AND_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("and%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(n) & imm32; @@ -846,6 +1045,12 @@ void ARMv7_instrs::AND_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("and%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -951,6 +1156,12 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("b%s 0x%08x", fmt_cond(cond), context.read_pc() + imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.thread.SetBranch(context.read_pc() + imm32); @@ -999,6 +1210,12 @@ void ARMv7_instrs::BIC_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bic%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(n) & ~imm32; @@ -1045,6 +1262,12 @@ void ARMv7_instrs::BIC_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bic%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -1109,18 +1332,19 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e default: throw __FUNCTION__; } + const u32 lr = context.ISET == ARM ? context.read_pc() - 4 : context.read_pc() | 1; + const u32 pc = context.ISET == ARM ? (context.read_pc() & ~3) + imm32 : context.read_pc() + imm32; + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bl%s 0x%08x", fmt_cond(cond), pc); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { - if (context.ISET == ARM) - { - context.LR = context.read_pc() - 4; - context.thread.SetBranch((context.read_pc() & ~3) + imm32); - } - else - { - context.LR = context.read_pc() | 1; - context.thread.SetBranch(context.read_pc() + imm32); - } + context.LR = lr; + context.thread.SetBranch(pc); } } @@ -1174,6 +1398,21 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) + { + context.debug_str = fmt::format("blx%s ", fmt_cond(cond)); + switch (type) + { + case T1: context.debug_str += fmt_reg((code.data >> 3) & 0xf); break; + case T2: context.debug_str += fmt::format("0x%08x", target); break; + default: context.debug_str += "???"; + } + } + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.LR = newLR; @@ -1183,14 +1422,14 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ void ARMv7_instrs::BX(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { - u32 cond, target; + u32 cond, m; switch (type) { case T1: { cond = context.ITSTATE.advance(); - target = context.read_gpr((code.data >> 3) & 0xf); + m = (code.data >> 3) & 0xf; reject(context.ITSTATE, "UNPREDICTABLE"); break; @@ -1198,15 +1437,21 @@ void ARMv7_instrs::BX(ARMv7Context& context, const ARMv7Code code, const ARMv7_e case A1: { cond = code.data >> 28; - target = context.read_gpr(code.data & 0xf); + m = (code.data & 0xf); break; } default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bx%s %s", fmt_cond(cond), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { - context.write_pc(target); + context.write_pc(context.read_gpr(m)); } } @@ -1230,6 +1475,12 @@ void ARMv7_instrs::CB_Z(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cb%sz 0x%08x", nonzero ? "n" : "", context.read_pc() + imm32); + if (process_debug(context)) return; + } + if ((context.read_gpr(n) == 0) ^ nonzero) { context.thread.SetBranch(context.read_pc() + imm32); @@ -1257,6 +1508,12 @@ void ARMv7_instrs::CLZ(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("clz%s %s,%s", fmt_cond(cond), fmt_reg(d), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.write_gpr(d, cntlz32(context.read_gpr(m))); @@ -1318,13 +1575,19 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cmp%s %s,#0x%x", fmt_cond(cond), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; const u32 n_value = context.read_gpr(n); - const u32 res = AddWithCarry(n_value, ~imm32, true, carry, overflow); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + const u32 result = AddWithCarry(n_value, ~imm32, true, carry, overflow); + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; @@ -1373,15 +1636,21 @@ void ARMv7_instrs::CMP_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cmp%s %s,%s%s", fmt_cond(cond), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { + bool carry, overflow; const u32 m_value = context.read_gpr(m); const u32 n_value = context.read_gpr(n); - bool carry, overflow; const u32 shifted = Shift(m_value, shift_t, shift_n, true); - const u32 res = AddWithCarry(n_value, ~shifted, true, carry, overflow); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + const u32 result = AddWithCarry(n_value, ~shifted, true, carry, overflow); + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; @@ -1469,6 +1738,12 @@ void ARMv7_instrs::EOR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("eor%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -1501,19 +1776,25 @@ void ARMv7_instrs::IT(ARMv7Context& context, const ARMv7Code code, const ARMv7_e { case T1: { - const u32 mask = code.data & 0xf; + const u32 mask = (code.data & 0xf); const u32 first = (code.data & 0xf0) >> 4; reject(mask == 0, "Related encodings"); reject(first == 15, "UNPREDICTABLE"); reject(first == 14 && BitCount(mask) != 1, "UNPREDICTABLE"); reject(context.ITSTATE, "UNPREDICTABLE"); + + context.ITSTATE.IT = code.data & 0xff; break; } default: throw __FUNCTION__; } - context.ITSTATE.IT = code.data & 0xff; + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("IT%s %s", fmt_it(context.ITSTATE.shift_state), fmt_cond(context.ITSTATE.condition)); + if (process_debug(context)) return; + } } @@ -1618,11 +1899,16 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - context.write_gpr(t, vm::psv::read32(addr)); if (wback) @@ -1661,6 +1947,12 @@ void ARMv7_instrs::LDR_LIT(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (lit)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 base = context.read_pc() & ~3; @@ -1711,19 +2003,23 @@ void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; const u32 addr = index ? offset_addr : context.read_gpr(n); - const u32 data = vm::psv::read32(addr); + context.write_gpr(t, vm::psv::read32(addr)); if (wback) { context.write_gpr(n, offset_addr); } - - context.write_gpr(t, data); } } @@ -1782,6 +2078,12 @@ void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; @@ -1845,6 +2147,12 @@ void ARMv7_instrs::LDRB_REG(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); @@ -1888,6 +2196,12 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; @@ -1926,6 +2240,12 @@ void ARMv7_instrs::LDRD_LIT(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s (lit)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 base = context.read_pc() & ~3; @@ -2000,11 +2320,16 @@ void ARMv7_instrs::LDRH_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrh%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - context.write_gpr(t, vm::psv::read16(addr)); if (wback) @@ -2076,6 +2401,12 @@ void ARMv7_instrs::LDRSB_IMM(ARMv7Context& context, const ARMv7Code code, const default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrsb%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; @@ -2158,14 +2489,19 @@ void ARMv7_instrs::LDREX(ARMv7Context& context, const ARMv7Code code, const ARMv default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrex%s ()", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 addr = context.read_gpr(n) + imm32; const u32 value = vm::psv::read32(addr); - + context.write_gpr(t, value); context.R_ADDR = addr; context.R_DATA = value; - context.write_gpr(t, value); } } @@ -2230,16 +2566,22 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("lsl%s%s %s,%s,#%d", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), shift_n); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; - const u32 res = Shift_C(context.read_gpr(m), SRType_LSL, shift_n, context.APSR.C, carry); - context.write_gpr(d, res); + const u32 result = Shift_C(context.read_gpr(m), SRType_LSL, shift_n, context.APSR.C, carry); + context.write_gpr(d, result); if (set_flags) { - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; } } @@ -2274,16 +2616,22 @@ void ARMv7_instrs::LSL_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("lsl%s%s %s,%s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; - const u32 res = Shift_C(context.read_gpr(n), SRType_LSL, (context.read_gpr(m) & 0xff), context.APSR.C, carry); - context.write_gpr(d, res); + const u32 result = Shift_C(context.read_gpr(n), SRType_LSL, (context.read_gpr(m) & 0xff), context.APSR.C, carry); + context.write_gpr(d, result); if (set_flags) { - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; } } @@ -2320,6 +2668,12 @@ void ARMv7_instrs::LSR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("lsr%s%s %s,%s,#%d", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), shift_n); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -2382,7 +2736,7 @@ void ARMv7_instrs::MOV_IMM(ARMv7Context& context, const ARMv7Code code, const AR case T2: { cond = context.ITSTATE.advance(); - set_flags = code.data & 0x100000; + set_flags = (code.data & 0x100000); d = (code.data >> 8) & 0xf; imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); @@ -2402,14 +2756,21 @@ void ARMv7_instrs::MOV_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mov%s%s %s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { - context.write_gpr(d, imm32); + const u32 result = imm32; + context.write_gpr(d, result); if (set_flags) { - context.APSR.N = imm32 >> 31; - context.APSR.Z = imm32 == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; } } @@ -2457,6 +2818,12 @@ void ARMv7_instrs::MOV_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mov%s%s %s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(m); @@ -2466,7 +2833,7 @@ void ARMv7_instrs::MOV_REG(ARMv7Context& context, const ARMv7Code code, const AR { context.APSR.N = result >> 31; context.APSR.Z = result == 0; - //context.APSR.C = ? + //context.APSR.C = carry; } } } @@ -2490,6 +2857,12 @@ void ARMv7_instrs::MOVT(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("movt%s %s,#0x%x", fmt_cond(cond), fmt_reg(d), imm16); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.write_gpr(d, (context.read_gpr(d) & 0xffff) | (imm16 << 16)); @@ -2556,6 +2929,12 @@ void ARMv7_instrs::MUL(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mul%s%s %s,%s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 op1 = context.read_gpr(n); @@ -2593,6 +2972,12 @@ void ARMv7_instrs::MVN_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mvn%s%s %s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = ~imm32; @@ -2638,6 +3023,12 @@ void ARMv7_instrs::MVN_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mvn%s%s %s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -2688,6 +3079,12 @@ void ARMv7_instrs::NOP(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("nop%s", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { } @@ -2736,6 +3133,12 @@ void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("orr%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(n) | imm32; @@ -2783,6 +3186,12 @@ void ARMv7_instrs::ORR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("orr%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -2870,6 +3279,12 @@ void ARMv7_instrs::POP(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("pop%s ()", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { u32 written = 0; @@ -2935,6 +3350,12 @@ void ARMv7_instrs::PUSH(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("push%s ()", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { u32 read = 0; @@ -3103,6 +3524,12 @@ void ARMv7_instrs::ROR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ror%s%s %s,%s,#%d", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), shift_n); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -3134,6 +3561,7 @@ void ARMv7_instrs::ROR_REG(ARMv7Context& context, const ARMv7Code code, const AR } case T2: { + cond = context.ITSTATE.advance(); d = (code.data & 0xf00) >> 8; n = (code.data & 0xf0000) >> 16; m = (code.data & 0xf); @@ -3146,6 +3574,12 @@ void ARMv7_instrs::ROR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ror%s%s %s,%s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -3203,6 +3637,12 @@ void ARMv7_instrs::RSB_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("rsb%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -3698,11 +4138,16 @@ void ARMv7_instrs::STR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write32(addr, context.read_gpr(t)); if (wback) @@ -3752,12 +4197,17 @@ void ARMv7_instrs::STR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write32(addr, context.read_gpr(t)); if (wback) @@ -3819,11 +4269,16 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write8(addr, (u8)context.read_gpr(t)); if (wback) @@ -3873,12 +4328,17 @@ void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write8(addr, (u8)context.read_gpr(t)); if (wback) @@ -3916,12 +4376,18 @@ void ARMv7_instrs::STRD_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strd%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 n_value = context.read_gpr(n); const u32 offset = add ? n_value + imm32 : n_value - imm32; const u32 addr = index ? offset : n_value; - vm::psv::write64(addr, (u64)context.read_gpr(t2) << 32 | context.read_gpr(t)); + vm::psv::write64(addr, (u64)context.read_gpr(t2) << 32 | (u64)context.read_gpr(t)); if (wback) { @@ -3991,11 +4457,16 @@ void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write16(addr, (u16)context.read_gpr(t)); if (wback) @@ -4045,6 +4516,12 @@ void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); @@ -4083,6 +4560,12 @@ void ARMv7_instrs::STREX(ARMv7Context& context, const ARMv7Code code, const ARMv default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strex%s ()", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 addr = context.read_gpr(n) + imm32; @@ -4174,6 +4657,12 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -4225,6 +4714,12 @@ void ARMv7_instrs::SUB_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s (reg)", set_flags ? "s" : "", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -4291,6 +4786,12 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s (spi)", set_flags ? "s" : "", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -4440,6 +4941,12 @@ void ARMv7_instrs::TST_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("tst%s %s,#0x%x", fmt_cond(cond), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(n) & imm32; @@ -4609,6 +5116,12 @@ void ARMv7_instrs::UMULL(ARMv7Context& context, const ARMv7Code code, const ARMv default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("umull%s%s %s,%s,%s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d0), fmt_reg(d1), fmt_reg(n), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u64 result = (u64)context.read_gpr(n) * (u64)context.read_gpr(m); @@ -4795,6 +5308,12 @@ void ARMv7_instrs::UXTB(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("uxtb%s %s,%s%s", fmt_cond(cond), fmt_reg(d), fmt_reg(m), fmt_shift(SRType_ROR, rot)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.write_gpr(d, (context.read_gpr(m) >> rot) & 0xff); diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index 01521ce9d5..e759f5e40b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -18,12 +18,11 @@ enum ARMv7_encoding enum SRType : u32 { - SRType_None, SRType_LSL, SRType_LSR, SRType_ASR, SRType_ROR, - SRType_RRX + SRType_RRX, }; namespace ARMv7_instrs diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index 29990a3208..21d9c6488e 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -10,7 +10,7 @@ void add_psv_func(psv_func& data) g_psv_func_list.push_back(data); } -psv_func* get_psv_func_by_nid(u32 nid) +const psv_func* get_psv_func_by_nid(u32 nid) { for (auto& f : g_psv_func_list) { @@ -23,7 +23,7 @@ psv_func* get_psv_func_by_nid(u32 nid) return nullptr; } -u32 get_psv_func_index(psv_func* func) +u32 get_psv_func_index(const psv_func* func) { auto res = func - g_psv_func_list.data(); @@ -32,14 +32,21 @@ u32 get_psv_func_index(psv_func* func) return (u32)res; } -void execute_psv_func_by_index(ARMv7Context& context, u32 index) +const psv_func* get_psv_func_by_index(u32 index) { assert(index < g_psv_func_list.size()); + + return &g_psv_func_list[index]; +} + +void execute_psv_func_by_index(ARMv7Context& context, u32 index) +{ + auto func = get_psv_func_by_index(index); auto old_last_syscall = context.thread.m_last_syscall; - context.thread.m_last_syscall = g_psv_func_list[index].nid; + context.thread.m_last_syscall = func->nid; - (*g_psv_func_list[index].func)(context); + (*func->func)(context); context.thread.m_last_syscall = old_last_syscall; } @@ -174,7 +181,7 @@ void initialize_psv_modules() // setup special functions (without NIDs) psv_func unimplemented; unimplemented.nid = 0; - unimplemented.name = "Special function (unimplemented stub)"; + unimplemented.name = "UNIMPLEMENTED"; unimplemented.func.reset(new psv_func_detail::func_binder([](ARMv7Context& context) { context.thread.m_last_syscall = vm::psv::read32(context.thread.PC + 4); @@ -184,7 +191,7 @@ void initialize_psv_modules() psv_func hle_return; hle_return.nid = 1; - hle_return.name = "Special function (return from HLE)"; + hle_return.name = "HLE_RETURN"; hle_return.func.reset(new psv_func_detail::func_binder([](ARMv7Context& context) { context.thread.FastStop(); diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.h b/rpcs3/Emu/ARMv7/PSVFuncList.h index a1948dcbec..8ddb45ab75 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.h +++ b/rpcs3/Emu/ARMv7/PSVFuncList.h @@ -492,9 +492,11 @@ template void reg_psv_func(u32 nid, psv_log_base* mo add_psv_func(f); } // Find registered HLE function by its ID -psv_func* get_psv_func_by_nid(u32 nid); +const psv_func* get_psv_func_by_nid(u32 nid); // Get index of registered HLE function -u32 get_psv_func_index(psv_func* func); +u32 get_psv_func_index(const psv_func* func); +// Find registered HLE function by its index +const psv_func* get_psv_func_by_index(u32 index); // Execute registered HLE function by its index void execute_psv_func_by_index(ARMv7Context& context, u32 index); // Register all HLE functions diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 8324e0e54f..db61eac0ea 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -349,6 +349,8 @@ void Emulator::Resume() GetCallbackManager().RunPauseCallbacks(false); } +extern std::map g_armv7_dump; + void Emulator::Stop() { if(IsStopped()) return; @@ -365,6 +367,14 @@ void Emulator::Stop() finalize_psv_modules(); clear_all_psv_objects(); + + for (auto& v : g_armv7_dump) + { + LOG_NOTICE(ARMv7, v.second); + } + + g_armv7_dump.clear(); + m_rsx_callback = 0; // TODO: check finalization order From e93aaf395770eec4ecb09efb932f764dda1700f2 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 5 Feb 2015 15:18:10 +0300 Subject: [PATCH 06/15] ARMv7: bugfix, some disasm subroutines --- Utilities/StrFmt.h | 44 ++++++- rpcs3/Emu/ARMv7/ARMv7Context.h | 2 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 183 +++++++++++++++++++-------- 3 files changed, 176 insertions(+), 53 deletions(-) diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 4015d5077b..bdc99a83af 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -177,6 +177,8 @@ namespace fmt std::string to_udec(u64 value); std::string to_sdec(s64 value); + std::string toupper(std::string source); + namespace detail { size_t get_fmt_start(const char* fmt, size_t len); @@ -198,6 +200,10 @@ namespace fmt { return to_hex(arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u') { return to_udec(arg); @@ -218,6 +224,10 @@ namespace fmt { return to_hex(arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u') { return to_udec(arg); @@ -238,6 +248,10 @@ namespace fmt { return to_hex(arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u') { return to_udec(arg); @@ -258,6 +272,10 @@ namespace fmt { return to_hex(arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u') { return to_udec(arg); @@ -278,6 +296,10 @@ namespace fmt { return to_hex((u8)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u8)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd') { return to_sdec(arg); @@ -298,6 +320,10 @@ namespace fmt { return to_hex((u16)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u16)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd') { return to_sdec(arg); @@ -318,6 +344,10 @@ namespace fmt { return to_hex((u32)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u32)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd') { return to_sdec(arg); @@ -338,6 +368,10 @@ namespace fmt { return to_hex((u64)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u64)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd') { return to_sdec(arg); @@ -358,6 +392,10 @@ namespace fmt { return to_hex((u32&)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u32&)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'f') { return std::to_string(arg); @@ -378,6 +416,10 @@ namespace fmt { return to_hex((u64&)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u64&)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'f') { return std::to_string(arg); @@ -394,7 +436,7 @@ namespace fmt { static std::string text(const char* fmt, size_t len, bool arg) { - if (fmt[len - 1] == 'x') + if (fmt[len - 1] == 'x' || fmt[len - 1] == 'X') { return to_hex(arg, get_fmt_precision(fmt, len)); } diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 78c0ab0e43..f8ad2c8212 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -130,7 +130,7 @@ struct ARMv7Context u32 debug; // debug flags std::string debug_str; - ARMv7Context(ARMv7Thread& thread) : thread(thread), debug(DF_DISASM | DF_PRINT) {} + ARMv7Context(ARMv7Thread& thread) : thread(thread), debug(/*DF_DISASM | DF_PRINT*/ 0) {} void write_pc(u32 value); u32 read_pc(); diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 1d1add9481..836fd7ef33 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -390,7 +390,7 @@ namespace ARMv7_instrs case 13: return "sp"; case 14: return "lr"; case 15: return "pc"; - default: return "???"; + default: return "r???"; } } @@ -414,17 +414,90 @@ namespace ARMv7_instrs return{}; } + + std::string fmt_reg_list(u32 reg_list) + { + std::vector> lines; + + for (u32 i = 0; i < 13; i++) + { + if (reg_list & (1 << i)) + { + if (lines.size() && lines.rbegin()->second == i - 1) + { + lines.rbegin()->second = i; + } + else + { + lines.push_back({ i, i }); + } + } + } + + if (reg_list & 0x2000) lines.push_back({ 13, 13 }); // sp + if (reg_list & 0x4000) lines.push_back({ 14, 14 }); // lr + if (reg_list & 0x8000) lines.push_back({ 15, 15 }); // pc + + std::string result; + + if (reg_list >> 16) result = "???"; // invalid bits + + for (auto& line : lines) + { + if (!result.empty()) + { + result += ","; + } + + if (line.first == line.second) + { + result += fmt_reg(line.first); + } + else + { + result += fmt_reg(line.first); + result += '-'; + result += fmt_reg(line.second); + } + } + + return result; + } + + std::string fmt_mem_imm(u32 reg, u32 imm, bool index, bool add, bool wback) + { + if (index) + { + return fmt::format("[%s,#%s0x%X]%s", fmt_reg(reg), add ? "" : "-", imm, wback ? "!" : ""); + } + else + { + return fmt::format("[%s],#%s0x%X%s", fmt_reg(reg), add ? "" : "-", imm, wback ? "" : "???"); + } + } + + std::string fmt_mem_reg(u32 n, u32 m, bool index, bool add, bool wback, u32 shift_t = SRType_LSL, u32 shift_n = 0) + { + if (index) + { + return fmt::format("[%s,%s%s%s]%s", fmt_reg(n), add ? "" : "-", fmt_reg(m), fmt_shift(shift_t, shift_n), wback ? "!" : ""); + } + else + { + return fmt::format("[%s],%s%s%s%s", fmt_reg(n), add ? "" : "-", fmt_reg(m), fmt_shift(shift_t, shift_n), wback ? "" : "???"); + } + } } void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code) { if (context.ISET == Thumb) { - throw fmt::format("Unknown/illegal opcode: 0x%04x 0x%04x", code.code1, code.code0); + throw fmt::format("Unknown/illegal opcode: 0x%04X 0x%04X", code.code1, code.code0); } else { - throw fmt::format("Unknown/illegal opcode: 0x%08x", code.data); + throw fmt::format("Unknown/illegal opcode: 0x%08X", code.data); } } @@ -536,7 +609,7 @@ void ARMv7_instrs::ADC_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("adc%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adc%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -675,7 +748,7 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -826,7 +899,7 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s (spi)", set_flags ? "s" : "", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,sp,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); if (process_debug(context)) return; } @@ -892,7 +965,7 @@ void ARMv7_instrs::ADD_SPR(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s (spr)", set_flags ? "s" : "", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,sp,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), fmt_shift(shift_t, shift_n)); if (process_debug(context)) return; } @@ -958,7 +1031,7 @@ void ARMv7_instrs::ADR(ARMv7Context& context, const ARMv7Code code, const ARMv7_ if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("adr%s r%d, 0x%08x", fmt_cond(cond), d, result); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adr%s r%d, 0x%08X", fmt_cond(cond), d, result); if (process_debug(context)) return; } @@ -994,7 +1067,7 @@ void ARMv7_instrs::AND_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("and%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("and%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -1158,7 +1231,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("b%s 0x%08x", fmt_cond(cond), context.read_pc() + imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("b%s 0x%08X", fmt_cond(cond), context.read_pc() + imm32); if (process_debug(context)) return; } @@ -1212,7 +1285,7 @@ void ARMv7_instrs::BIC_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("bic%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bic%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -1337,7 +1410,7 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("bl%s 0x%08x", fmt_cond(cond), pc); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bl%s 0x%08X", fmt_cond(cond), pc); if (process_debug(context)) return; } @@ -1406,7 +1479,8 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ switch (type) { case T1: context.debug_str += fmt_reg((code.data >> 3) & 0xf); break; - case T2: context.debug_str += fmt::format("0x%08x", target); break; + case T2: context.debug_str += fmt::format("0x%08X", target); break; + case A1: context.debug_str += fmt_reg(code.data & 0xf); break; default: context.debug_str += "???"; } } @@ -1477,7 +1551,7 @@ void ARMv7_instrs::CB_Z(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("cb%sz 0x%08x", nonzero ? "n" : "", context.read_pc() + imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cb%sz 0x%08X", nonzero ? "n" : "", context.read_pc() + imm32); if (process_debug(context)) return; } @@ -1577,7 +1651,7 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("cmp%s %s,#0x%x", fmt_cond(cond), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cmp%s %s,#0x%X", fmt_cond(cond), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -1901,7 +1975,7 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -1947,16 +2021,17 @@ void ARMv7_instrs::LDR_LIT(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + const u32 base = context.read_pc() & ~3; + const u32 addr = add ? base + imm32 : base - imm32; + if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (lit)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s %s,0x%08X", fmt_cond(cond), fmt_reg(t), addr); if (process_debug(context)) return; } if (ConditionPassed(context, cond)) { - const u32 base = context.read_pc() & ~3; - const u32 addr = add ? base + imm32 : base - imm32; const u32 data = vm::psv::read32(addr); context.write_gpr(t, data); } @@ -2005,7 +2080,7 @@ void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -2080,7 +2155,7 @@ void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -2149,7 +2224,7 @@ void ARMv7_instrs::LDRB_REG(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -2198,7 +2273,7 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s %s,%s,%s", fmt_cond(cond), fmt_reg(t), fmt_reg(t2), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -2240,16 +2315,17 @@ void ARMv7_instrs::LDRD_LIT(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + const u32 base = context.read_pc() & ~3; + const u32 addr = add ? base + imm32 : base - imm32; + if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s (lit)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s %s,%s,0x%08X", fmt_cond(cond), fmt_reg(t), fmt_reg(t2), addr); if (process_debug(context)) return; } if (ConditionPassed(context, cond)) { - const u32 base = context.read_pc() & ~3; - const u32 addr = add ? base + imm32 : base - imm32; const u64 value = vm::psv::read64(addr); context.write_gpr(t, (u32)(value)); context.write_gpr(t2, (u32)(value >> 32)); @@ -2322,7 +2398,7 @@ void ARMv7_instrs::LDRH_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrh%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrh%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -2403,7 +2479,7 @@ void ARMv7_instrs::LDRSB_IMM(ARMv7Context& context, const ARMv7Code code, const if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrsb%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrsb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -2412,7 +2488,6 @@ void ARMv7_instrs::LDRSB_IMM(ARMv7Context& context, const ARMv7Code code, const const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); const s8 value = vm::psv::read8(addr); - context.write_gpr(t, value); // sign-extend if (wback) @@ -2491,7 +2566,7 @@ void ARMv7_instrs::LDREX(ARMv7Context& context, const ARMv7Code code, const ARMv if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrex%s ()", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrex%s %s,[%s,#0x%X]", fmt_cond(cond), fmt_reg(t), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -2758,7 +2833,14 @@ void ARMv7_instrs::MOV_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("mov%s%s %s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + if (context.debug & DF_DISASM) + { + switch (type) + { + case T3: case A2: context.debug_str = fmt::format("movw%s%s %s,#0x%04X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); break; + default: context.debug_str = fmt::format("mov%s%s %s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + } + } if (process_debug(context)) return; } @@ -2848,7 +2930,7 @@ void ARMv7_instrs::MOVT(ARMv7Context& context, const ARMv7Code code, const ARMv7 { cond = context.ITSTATE.advance(); d = (code.data & 0xf00) >> 8; - imm16 = (code.data & 0xf0000) >> 4 | (code.data & 0x4000000) >> 14 | (code.data & 0x7000) >> 4 | (code.data & 0xff); + imm16 = (code.data & 0xf0000) >> 4 | (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff); reject(d == 13 || d == 15, "UNPREDICTABLE"); break; @@ -2859,7 +2941,7 @@ void ARMv7_instrs::MOVT(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("movt%s %s,#0x%x", fmt_cond(cond), fmt_reg(d), imm16); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("movt%s %s,#0x%04X", fmt_cond(cond), fmt_reg(d), imm16); if (process_debug(context)) return; } @@ -2974,7 +3056,7 @@ void ARMv7_instrs::MVN_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("mvn%s%s %s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mvn%s%s %s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); if (process_debug(context)) return; } @@ -3135,7 +3217,7 @@ void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("orr%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("orr%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -3281,7 +3363,7 @@ void ARMv7_instrs::POP(ARMv7Context& context, const ARMv7Code code, const ARMv7_ if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("pop%s ()", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("pop%s {%s}", fmt_cond(cond), fmt_reg_list(reg_list)); if (process_debug(context)) return; } @@ -3352,7 +3434,7 @@ void ARMv7_instrs::PUSH(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("push%s ()", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("push%s {%s}", fmt_cond(cond), fmt_reg_list(reg_list)); if (process_debug(context)) return; } @@ -3639,7 +3721,7 @@ void ARMv7_instrs::RSB_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("rsb%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("rsb%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -4140,7 +4222,7 @@ void ARMv7_instrs::STR_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -4199,7 +4281,7 @@ void ARMv7_instrs::STR_REG(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -4271,7 +4353,7 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -4330,7 +4412,7 @@ void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -4378,7 +4460,7 @@ void ARMv7_instrs::STRD_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strd%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strd%s %s,%s,%s", fmt_cond(cond), fmt_reg(t), fmt_reg(t2), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -4459,7 +4541,7 @@ void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -4518,7 +4600,7 @@ void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -4527,7 +4609,6 @@ void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const A const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write16(addr, (u16)context.read_gpr(t)); if (wback) @@ -4562,7 +4643,7 @@ void ARMv7_instrs::STREX(ARMv7Context& context, const ARMv7Code code, const ARMv if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strex%s ()", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strex%s %s,%s,[%s,#0x%x]", fmt_cond(cond), fmt_reg(d), fmt_reg(t), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -4659,7 +4740,7 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -4716,7 +4797,7 @@ void ARMv7_instrs::SUB_REG(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s (reg)", set_flags ? "s" : "", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); if (process_debug(context)) return; } @@ -4788,7 +4869,7 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s (spi)", set_flags ? "s" : "", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,sp,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); if (process_debug(context)) return; } @@ -4943,7 +5024,7 @@ void ARMv7_instrs::TST_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("tst%s %s,#0x%x", fmt_cond(cond), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("tst%s %s,#0x%X", fmt_cond(cond), fmt_reg(n), imm32); if (process_debug(context)) return; } From 5983813d12d3630344ba24f9170989fcdf1fa051 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 5 Feb 2015 21:13:27 +0300 Subject: [PATCH 07/15] ARMv7: new instructions EOR_IMM, LDM, REV, STM --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 2 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 190 +++++++++++++++++++++++++-- 2 files changed, 177 insertions(+), 15 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 4ae428e985..70ccd9f240 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1281,7 +1281,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); - const u32 instr = vm::psv::read32(target); + const u32 instr = Memory.IsGoodAddr(target, 4) ? vm::psv::read32(target) : 0; // possibly a call to imported function: if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 836fd7ef33..dbe994c42b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -1574,7 +1574,7 @@ void ARMv7_instrs::CLZ(ARMv7Context& context, const ARMv7Code code, const ARMv7_ d = (code.data & 0xf00) >> 8; m = (code.data & 0xf); - reject((code.data & 0xf0000) >> 16 != m, "UNPREDICTABLE"); + reject(m != (code.data & 0xf0000) >> 16, "UNPREDICTABLE"); reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); break; } @@ -1772,11 +1772,45 @@ void ARMv7_instrs::DSB(ARMv7Context& context, const ARMv7Code code, const ARMv7_ void ARMv7_instrs::EOR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags, carry = context.APSR.C; + u32 cond, d, n, imm32; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(d == 15 && set_flags, "TEQ (immediate)"); + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("eor%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) ^ imm32; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::EOR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1855,7 +1889,7 @@ void ARMv7_instrs::IT(ARMv7Context& context, const ARMv7Code code, const ARMv7_e reject(mask == 0, "Related encodings"); reject(first == 15, "UNPREDICTABLE"); - reject(first == 14 && BitCount(mask) != 1, "UNPREDICTABLE"); + reject(first == 14 && BitCount(mask, 4) != 1, "UNPREDICTABLE"); reject(context.ITSTATE, "UNPREDICTABLE"); context.ITSTATE.IT = code.data & 0xff; @@ -1874,11 +1908,61 @@ void ARMv7_instrs::IT(ARMv7Context& context, const ARMv7Code code, const ARMv7_e void ARMv7_instrs::LDM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, n, reg_list; + bool wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0x700) >> 8; + reg_list = (code.data & 0xff); + wback = !(reg_list & (1 << n)); + + reject(reg_list == 0, "UNPREDICTABLE"); + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0xf0000) >> 16; + reg_list = (code.data & 0xdfff); + wback = (code.data & 0x200000); + + reject(wback && n == 13, "POP"); + reject(n == 15 || BitCount(reg_list, 16) < 2 || reg_list >= 0xc000, "UNPREDICTABLE"); + reject(reg_list & 0x8000 && context.ITSTATE, "UNPREDICTABLE"); + reject(wback && reg_list & (1 << n), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldm%s %s%s,{%s}", fmt_cond(cond), fmt_reg(n), wback ? "!" : "", fmt_reg_list(reg_list)); + if (process_debug(context)) return; + } + + if (ConditionPassed(context, cond)) + { + auto memory = vm::psv::ptr::make(context.read_gpr(n)); + + for (u32 i = 0; i < 16; i++) + { + if (reg_list & (1 << i)) + { + context.write_gpr(i, *memory++); + } + } + + if (wback) + { + context.write_gpr(n, memory.addr()); + } + } } void ARMv7_instrs::LDMDA(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3369,17 +3453,17 @@ void ARMv7_instrs::POP(ARMv7Context& context, const ARMv7Code code, const ARMv7_ if (ConditionPassed(context, cond)) { - u32 written = 0; - for (u16 mask = 1, i = 0; mask; mask <<= 1, i++) + auto stack = vm::psv::ptr::make(context.SP); + + for (u32 i = 0; i < 16; i++) { - if (reg_list & mask) + if (reg_list & (1 << i)) { - context.write_gpr(i, vm::psv::read32(context.SP + written)); - written += 4; + context.write_gpr(i, *stack++); } } - context.SP += written; + context.SP = stack.addr(); } } @@ -3440,17 +3524,17 @@ void ARMv7_instrs::PUSH(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (ConditionPassed(context, cond)) { - u32 read = 0; - for (u16 mask = 1 << 15, i = 15; mask; mask >>= 1, i--) + auto memory = vm::psv::ptr::make(context.SP); + + for (u32 i = 15; ~i; i--) { - if (reg_list & mask) + if (reg_list & (1 << i)) { - read += 4; - vm::psv::write32(context.SP - read, context.read_gpr(i)); + *--memory = context.read_gpr(i); } } - context.SP -= read; + context.SP = memory.addr(); } } @@ -3557,11 +3641,41 @@ void ARMv7_instrs::RBIT(ARMv7Context& context, const ARMv7Code code, const ARMv7 void ARMv7_instrs::REV(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, m; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + m = (code.data & 0xf); + + reject(m != (code.data & 0xf0000) >> 16, "UNPREDICTABLE"); + reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("rev%s %s,%s", fmt_cond(cond), fmt_reg(d), fmt_reg(m)); + if (process_debug(context)) return; + } + + if (ConditionPassed(context, cond)) + { + context.write_gpr(d, re32(context.read_gpr(m))); + } } void ARMv7_instrs::REV16(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -4122,11 +4236,59 @@ void ARMv7_instrs::SSUB8(ARMv7Context& context, const ARMv7Code code, const ARMv void ARMv7_instrs::STM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, n, reg_list; + bool wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0x700) >> 8; + reg_list = (code.data & 0xff); + wback = true; + + reject(reg_list == 0, "UNPREDICTABLE"); + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0xf0000) >> 16; + reg_list = (code.data & 0x5fff); + wback = (code.data & 0x200000); + + reject(n == 15 || BitCount(reg_list, 16) < 2, "UNPREDICTABLE"); + reject(wback && reg_list & (1 << n), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("stm%s %s%s,{%s}", fmt_cond(cond), fmt_reg(n), wback ? "!" : "", fmt_reg_list(reg_list)); + if (process_debug(context)) return; + } + + if (ConditionPassed(context, cond)) + { + auto memory = vm::psv::ptr::make(context.read_gpr(n)); + + for (u32 i = 0; i < 16; i++) + { + if (reg_list & (1 << i)) + { + *memory++ = context.read_gpr(i); + } + } + + if (wback) + { + context.write_gpr(n, memory.addr()); + } + } } void ARMv7_instrs::STMDA(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) From c1c586a072a0180430949d6c16a052f80e8a53d5 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 6 Feb 2015 03:23:37 +0300 Subject: [PATCH 08/15] Some drafts --- rpcs3/Emu/ARMv7/Modules/psv_cond.cpp | 13 +++++++++++++ rpcs3/Emu/ARMv7/Modules/psv_cond.h | 24 ++++++++++++++++++++++++ rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp | 13 +++++++++++++ rpcs3/Emu/ARMv7/Modules/psv_mutex.h | 24 ++++++++++++++++++++++++ rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 18 ++++++++++++++++-- rpcs3/Emu/ARMv7/Modules/scePerf.cpp | 5 +++++ rpcs3/Emu/ARMv7/PSVObjectList.cpp | 6 ++++++ rpcs3/emucore.vcxproj | 4 ++++ rpcs3/emucore.vcxproj.filters | 24 ++++++++++++++++++------ 9 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_cond.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_cond.h create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_mutex.h diff --git a/rpcs3/Emu/ARMv7/Modules/psv_cond.cpp b/rpcs3/Emu/ARMv7/Modules/psv_cond.cpp new file mode 100644 index 0000000000..c89511b19d --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_cond.cpp @@ -0,0 +1,13 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" +#include "sceLibKernel.h" +#include "psv_cond.h" + +psv_cond_t::psv_cond_t(const char* name, u32 attr, s32 mutexId) + : attr(attr) + , mutexId(mutexId) +{ + strcpy_trunc(this->name, name); +} diff --git a/rpcs3/Emu/ARMv7/Modules/psv_cond.h b/rpcs3/Emu/ARMv7/Modules/psv_cond.h new file mode 100644 index 0000000000..cd8c518615 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_cond.h @@ -0,0 +1,24 @@ +#pragma once + +struct psv_cond_t +{ + char name[32]; + u32 attr; + s32 mutexId; + +private: + psv_cond_t() = delete; + psv_cond_t(const psv_cond_t&) = delete; + psv_cond_t(psv_cond_t&&) = delete; + + psv_cond_t& operator =(const psv_cond_t&) = delete; + psv_cond_t& operator =(psv_cond_t&&) = delete; + +public: + psv_cond_t(const char* name, u32 attr, s32 mutexId); + void on_init(s32 id) {} + void on_stop() {} + +}; + +extern psv_object_list_t g_psv_cond_list; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp b/rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp new file mode 100644 index 0000000000..7733ad54ea --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp @@ -0,0 +1,13 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" +#include "sceLibKernel.h" +#include "psv_mutex.h" + +psv_mutex_t::psv_mutex_t(const char* name, u32 attr, s32 count) + : attr(attr) + , count(count) +{ + strcpy_trunc(this->name, name); +} diff --git a/rpcs3/Emu/ARMv7/Modules/psv_mutex.h b/rpcs3/Emu/ARMv7/Modules/psv_mutex.h new file mode 100644 index 0000000000..5da6ad4590 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_mutex.h @@ -0,0 +1,24 @@ +#pragma once + +struct psv_mutex_t +{ + char name[32]; + u32 attr; + s32 count; + +private: + psv_mutex_t() = delete; + psv_mutex_t(const psv_mutex_t&) = delete; + psv_mutex_t(psv_mutex_t&&) = delete; + + psv_mutex_t& operator =(const psv_mutex_t&) = delete; + psv_mutex_t& operator =(psv_mutex_t&&) = delete; + +public: + psv_mutex_t(const char* name, u32 attr, s32 count); + void on_init(s32 id) {} + void on_stop() {} + +}; + +extern psv_object_list_t g_psv_mutex_list; diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index d7bd58c79a..016917d6de 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -10,6 +10,8 @@ #include "sceLibKernel.h" #include "psv_sema.h" #include "psv_event_flag.h" +#include "psv_mutex.h" +#include "psv_cond.h" #define RETURN_ERROR(code) { Emu.Pause(); sceLibKernel.Error("%s() failed: %s", __FUNCTION__, #code); return code; } @@ -522,7 +524,13 @@ s32 sceKernelGetSemaInfo(s32 semaId, vm::psv::ptr pInfo) s32 sceKernelCreateMutex(vm::psv::ptr pName, u32 attr, s32 initCount, vm::psv::ptr pOptParam) { - throw __FUNCTION__; + sceLibKernel.Error("sceKernelCreateMutex(pName=0x%x, attr=0x%x, initCount=%d, pOptParam=0x%x)", pName, attr, initCount, pOptParam); + + std::shared_ptr mutex(new psv_mutex_t(pName.get_ptr(), attr, initCount)); + + const s32 id = g_psv_mutex_list.add(mutex); + + return id; } s32 sceKernelDeleteMutex(s32 mutexId) @@ -616,7 +624,13 @@ s32 sceKernelGetLwMutexInfoById(s32 lwMutexId, vm::psv::ptr pName, u32 attr, s32 mutexId, vm::psv::ptr pOptParam) { - throw __FUNCTION__; + sceLibKernel.Error("sceKernelCreateCond(pName=0x%x, attr=0x%x, mutexId=0x%x, pOptParam=0x%x)", pName, attr, mutexId, pOptParam); + + std::shared_ptr cond(new psv_cond_t(pName.get_ptr(), attr, mutexId)); + + const s32 id = g_psv_cond_list.add(cond); + + return id; } s32 sceKernelDeleteCond(s32 condId) diff --git a/rpcs3/Emu/ARMv7/Modules/scePerf.cpp b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp index e7939506bc..fabf63691a 100644 --- a/rpcs3/Emu/ARMv7/Modules/scePerf.cpp +++ b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp @@ -134,6 +134,11 @@ s32 scePerfArmPmonSelectEvent(ARMv7Context& context, s32 threadId, u32 counter, case SCE_PERF_ARM_PMON_BRANCH_MISPREDICT: case SCE_PERF_ARM_PMON_DCACHE_MISS: + case SCE_PERF_ARM_PMON_DCACHE_STALL: + case SCE_PERF_ARM_PMON_ICACHE_STALL: + case SCE_PERF_ARM_PMON_DATA_EVICTION: + case SCE_PERF_ARM_PMON_WRITE_STALL: + case SCE_PERF_ARM_PMON_MAINTLB_STALL: case SCE_PERF_ARM_PMON_UNALIGNED: { value = 1; // these events will probably never be implemented diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.cpp b/rpcs3/Emu/ARMv7/PSVObjectList.cpp index cc8e97a1c0..5e89e15c73 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.cpp +++ b/rpcs3/Emu/ARMv7/PSVObjectList.cpp @@ -5,12 +5,18 @@ #include "Modules/sceLibKernel.h" #include "Modules/psv_sema.h" #include "Modules/psv_event_flag.h" +#include "Modules/psv_mutex.h" +#include "Modules/psv_cond.h" psv_object_list_t g_psv_sema_list; psv_object_list_t g_psv_ef_list; +psv_object_list_t g_psv_mutex_list; +psv_object_list_t g_psv_cond_list; void clear_all_psv_objects() { g_psv_sema_list.clear(); g_psv_ef_list.clear(); + g_psv_mutex_list.clear(); + g_psv_cond_list.clear(); } diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index daed4a06ea..5327e220e3 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -56,7 +56,9 @@ + + @@ -334,7 +336,9 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 0720c265c4..ea11ba34b9 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -583,7 +583,7 @@ Emu\GPU\RSX - + Emu\GPU\RSX @@ -670,7 +670,7 @@ Emu\CPU\ARMv7 - + Emu\CPU\ARMv7 @@ -696,7 +696,7 @@ Emu\CPU\ARMv7\Modules - Emu\CPU\ARMv7\Modules + Emu\CPU\ARMv7\Modules Emu\CPU\ARMv7\Modules @@ -848,6 +848,12 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Objects + + + Emu\CPU\ARMv7\Objects + @@ -1350,7 +1356,7 @@ Emu\GPU\RSX - + Emu\GPU\RSX @@ -1479,7 +1485,7 @@ Emu\CPU\ARMv7\Modules - + Emu\CPU\ARMv7 @@ -1490,7 +1496,7 @@ Emu\CPU\ARMv7\Objects - Emu\CPU\ARMv7\Modules + Emu\CPU\ARMv7\Modules Emu\CPU\ARMv7\Modules @@ -1510,5 +1516,11 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Objects + + + Emu\CPU\ARMv7\Objects + \ No newline at end of file From 1af4848324fa887ba4e58ea56cbaad3eddbfcb7c Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 02:39:51 +0300 Subject: [PATCH 09/15] New reservations (not finished) --- Utilities/Thread.cpp | 32 ++++- rpcs3/Emu/ARMv7/ARMv7Context.h | 3 - rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 14 +- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 2 +- rpcs3/Emu/Cell/PPUInterpreter.h | 66 +++------ rpcs3/Emu/Cell/PPUThread.h | 5 - rpcs3/Emu/Cell/SPUThread.cpp | 103 ++------------ rpcs3/Emu/Cell/SPUThread.h | 3 - rpcs3/Emu/Memory/Memory.cpp | 13 +- rpcs3/Emu/Memory/vm.cpp | 192 +++++++++++++++++++++++++-- rpcs3/Emu/Memory/vm.h | 24 ++++ 11 files changed, 279 insertions(+), 178 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 2539c791cd..b85b96691a 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -215,7 +215,8 @@ static const reg_table_t reg_table[17] = bool handle_access_violation(const u32 addr, x64_context* context) { - if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) // RawSPU MMIO registers + // check if address is RawSPU MMIO register + if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) { // one x64 instruction is manually decoded and interpreted x64_op_t op; @@ -277,6 +278,12 @@ bool handle_access_violation(const u32 addr, x64_context* context) return true; } + // check if fault is caused by reservation + if (vm::reservation_query(addr)) + { + return true; + } + // TODO: allow recovering from a page fault as a feature of PS3 virtual memory return false; } @@ -303,6 +310,24 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) // else some fatal error (should crash) } +extern LPTOP_LEVEL_EXCEPTION_FILTER filter_set; + +LONG __stdcall exception_filter(_EXCEPTION_POINTERS* pExp) +{ + _se_translator(pExp->ExceptionRecord->ExceptionCode, pExp); + + if (filter_set) + { + return filter_set(pExp); + } + else + { + return EXCEPTION_CONTINUE_SEARCH; + } +} + +LPTOP_LEVEL_EXCEPTION_FILTER filter_set = SetUnhandledExceptionFilter(exception_filter); + #else void signal_handler(int sig, siginfo_t* info, void* uct) @@ -352,6 +377,11 @@ void SetCurrentNamedThread(NamedThreadBase* value) return; } + if (old_value) + { + vm::reservation_free(); + } + if (value && value->m_tls_assigned.exchange(true)) { LOG_ERROR(GENERAL, "Thread '%s' was already assigned to g_tls_this_thread of another thread", value->GetThreadName()); diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index f8ad2c8212..9200cd5752 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -114,9 +114,6 @@ struct ARMv7Context u32 TLS; - u32 R_ADDR; - u64 R_DATA; - struct perf_counter { u32 event; diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index dbe994c42b..e07bbaa00b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -2657,10 +2657,11 @@ void ARMv7_instrs::LDREX(ARMv7Context& context, const ARMv7Code code, const ARMv if (ConditionPassed(context, cond)) { const u32 addr = context.read_gpr(n) + imm32; - const u32 value = vm::psv::read32(addr); - context.write_gpr(t, value); - context.R_ADDR = addr; - context.R_DATA = value; + + u32 value; + vm::reservation_acquire(&value, addr, sizeof(value)); + + context.write_gpr(t, value); } } @@ -4813,10 +4814,7 @@ void ARMv7_instrs::STREX(ARMv7Context& context, const ARMv7Code code, const ARMv { const u32 addr = context.read_gpr(n) + imm32; const u32 value = context.read_gpr(t); - - auto& sync_obj = vm::get_ref>(addr); - context.write_gpr(d, addr != context.R_ADDR || sync_obj.compare_and_swap((u32)context.R_DATA, value) != context.R_DATA); - context.R_ADDR = 0; + context.write_gpr(d, !vm::reservation_update(addr, &value, sizeof(value))); } } diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 12b7c7b0b3..0a57e4abcf 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -118,7 +118,7 @@ void ARMv7Thread::InitRegs() context.ITSTATE.IT = 0; context.SP = m_stack_addr + m_stack_size; context.TLS = armv7_get_tls(GetId()); - context.R_ADDR = 0; + context.debug |= DF_DISASM | DF_PRINT; } void ARMv7Thread::InitStack() diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 201385e827..be1611bf78 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2500,39 +2500,16 @@ private: } void MFOCRF(u32 a, u32 rd, u32 crm) { - /* - if(a) - { - u32 n = 0, count = 0; - for(u32 i = 0; i < 8; ++i) - { - if(crm & (1 << i)) - { - n = i; - count++; - } - } - - if(count == 1) - { - //RD[32+4*n : 32+4*n+3] = CR[4*n : 4*n+3]; - u8 offset = n * 4; - CPU.GPR[rd] = (CPU.GPR[rd] & ~(0xf << offset)) | ((u32)CPU.GetCR(7 - n) << offset); - } - else - CPU.GPR[rd] = 0; - } - else - { - */ CPU.GPR[rd] = CPU.CR.CR; - //} } void LWARX(u32 rd, u32 ra, u32 rb) { - CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.R_VALUE = vm::get_ref(vm::cast(CPU.R_ADDR)); - CPU.GPR[rd] = re32((u32)CPU.R_VALUE); + const u32 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + + be_t value; + vm::reservation_acquire(&value, vm::cast(addr), sizeof(value)); + + CPU.GPR[rd] = value; } void LDX(u32 rd, u32 ra, u32 rb) { @@ -2682,9 +2659,12 @@ private: } void LDARX(u32 rd, u32 ra, u32 rb) { - CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.R_VALUE = vm::get_ref(vm::cast(CPU.R_ADDR)); - CPU.GPR[rd] = re64(CPU.R_VALUE); + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + + be_t value; + vm::reservation_acquire(&value, vm::cast(addr), sizeof(value)); + + CPU.GPR[rd] = value; } void DCBF(u32 ra, u32 rb) { @@ -2800,15 +2780,8 @@ private: { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - if (CPU.R_ADDR == addr) - { - CPU.SetCR_EQ(0, InterlockedCompareExchange(vm::get_ptr(vm::cast(CPU.R_ADDR)), re32((u32)CPU.GPR[rs]), (u32)CPU.R_VALUE) == (u32)CPU.R_VALUE); - } - else - { - CPU.SetCR_EQ(0, false); - } - CPU.R_ADDR = 0; + const be_t value = be_t::make((u32)CPU.GPR[rs]); + CPU.SetCR_EQ(0, vm::reservation_update(vm::cast(addr), &value, sizeof(value))); } void STWX(u32 rs, u32 ra, u32 rb) { @@ -2859,15 +2832,8 @@ private: { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - if (CPU.R_ADDR == addr) - { - CPU.SetCR_EQ(0, InterlockedCompareExchange(vm::get_ptr(vm::cast(CPU.R_ADDR)), re64(CPU.GPR[rs]), CPU.R_VALUE) == CPU.R_VALUE); - } - else - { - CPU.SetCR_EQ(0, false); - } - CPU.R_ADDR = 0; + const be_t value = be_t::make(CPU.GPR[rs]); + CPU.SetCR_EQ(0, vm::reservation_update(vm::cast(addr), &value, sizeof(value))); } void STBX(u32 rs, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 820b244c2b..834200b1ae 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -536,11 +536,6 @@ public: //TBR : Time-Base Registers u64 TB; //TBR 0x10C - 0x10D - u64 cycle; - - u64 R_ADDR; // reservation address - u64 R_VALUE; // reservation value (BE) - u32 owned_mutexes; std::function custom_task; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index f5faf9fff1..71033cbd9d 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -99,8 +99,6 @@ void SPUThread::InitRegs() m_event_mask = 0; m_events = 0; - - R_ADDR = 0; } void SPUThread::InitStack() @@ -437,103 +435,37 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) if (op == MFC_GETLLAR_CMD) // get reservation { - if (R_ADDR) - { - m_events |= SPU_EVENT_LR; - } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - R_ADDR = ea; - for (u32 i = 0; i < 16; i++) + vm::reservation_acquire(vm::get_ptr(ls_offset + lsa), ea, 128, [this]() { - R_DATA[i] = vm::get_ptr((u32)R_ADDR)[i]; - vm::get_ptr(ls_offset + lsa)[i] = R_DATA[i]; - } + m_events |= SPU_EVENT_LR; // TODO: atomic op + Notify(); + }); + MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); } else if (op == MFC_PUTLLC_CMD) // store conditional { - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); - - if (R_ADDR == ea) + if (vm::reservation_update(ea, vm::get_ptr(ls_offset + lsa), 128)) { - u32 changed = 0, mask = 0; - u64 buf[16]; - for (u32 i = 0; i < 16; i++) - { - buf[i] = vm::get_ptr(ls_offset + lsa)[i]; - if (buf[i] != R_DATA[i]) - { - changed++; - mask |= (0x3 << (i * 2)); - if (vm::get_ptr((u32)R_ADDR)[i] != R_DATA[i]) - { - m_events |= SPU_EVENT_LR; - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - R_ADDR = 0; - return; - } - } - } - - for (u32 i = 0; i < 16; i++) - { - if (buf[i] != R_DATA[i]) - { - if (InterlockedCompareExchange(&vm::get_ptr((u32)R_ADDR)[i], buf[i], R_DATA[i]) != R_DATA[i]) - { - m_events |= SPU_EVENT_LR; - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - - if (changed > 1) - { - LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: Memory corrupted (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", - changed, mask, op, cmd, lsa, ea, tag, size); - Emu.Pause(); - } - - break; - } - } - } - - if (changed > 1) - { - LOG_WARNING(Log::SPU, "MFC_PUTLLC_CMD: Reservation impossibru (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", - changed, mask, op, cmd, lsa, ea, tag, size); - - SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); - for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4) - { - dis_asm.dump_pc = i; - dis_asm.offset = vm::get_ptr(ls_offset); - const u32 opcode = vm::read32(i + ls_offset); - (*SPU_instr::rrr_list)(&dis_asm, opcode); - if (i >= 0 && i < 0x40000) - { - LOG_NOTICE(Log::SPU, "*** %s", dis_asm.last_opcode.c_str()); - } - } - } + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); } else { MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); } - R_ADDR = 0; } - else // store unconditional + else // store unconditional (may be wrong) { - if (R_ADDR) // may be wrong - { - m_events |= SPU_EVENT_LR; - } + vm::reservation_break(ea); ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); + if (op == MFC_PUTLLUC_CMD) { MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS); } - R_ADDR = 0; } break; } @@ -548,19 +480,6 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) bool SPUThread::CheckEvents() { // checks events: - // SPU_EVENT_LR: - if (R_ADDR) - { - for (u32 i = 0; i < 16; i++) - { - if (vm::get_ptr((u32)R_ADDR)[i] != R_DATA[i]) - { - m_events |= SPU_EVENT_LR; - R_ADDR = 0; - break; - } - } - } return (m_events & m_event_mask) != 0; } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index c2e2cc2f03..bab5f1aa2d 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -277,9 +277,6 @@ public: u32 SRR0; SPU_SNRConfig_hdr cfg; // Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2) - u64 R_ADDR; // reservation address - u64 R_DATA[16]; // lock line data (BE) - std::shared_ptr SPUPs[64]; // SPU Thread Event Ports EventManager SPUQs; // SPU Queue Mapping std::shared_ptr group; // associated SPU Thread Group (null for raw spu) diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 502694ff93..b892bff2b8 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -231,9 +231,11 @@ bool MemoryBase::Unmap(const u64 addr) MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) : MemInfo(_addr, PAGE_4K(_size)) { - void* real_addr = (void*)((u64)Memory.GetBaseAddr() + _addr); + void* real_addr = vm::get_ptr(vm::cast(_addr)); #ifdef _WIN32 - mem = VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE); + void* priv_addr = vm::get_priv_ptr(vm::cast(_addr)); + void* priv_mem = VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE); + mem = priv_mem == priv_addr ? VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE) : priv_mem; #else if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE)) { @@ -262,7 +264,10 @@ void MemBlockInfo::Free() { Memory.UnregisterPages(addr, size); #ifdef _WIN32 - if (!VirtualFree(mem, size, MEM_DECOMMIT)) + DWORD old; + + if (!VirtualProtect(mem, size, PAGE_NOACCESS, &old) || !VirtualProtect(vm::get_priv_ptr(vm::cast(addr)), size, PAGE_NOACCESS, &old)) + //if (!VirtualFree(mem, size, MEM_DECOMMIT)) #else if (::mprotect(mem, size, PROT_NONE)) #endif @@ -715,4 +720,4 @@ bool VirtualMemoryBlock::Unreserve(u32 size) u32 VirtualMemoryBlock::GetReservedAmount() { return m_reserve_size; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 9a5f9eec9e..a32d176b2e 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -1,24 +1,194 @@ #include "stdafx.h" +#include "Utilities/Log.h" #include "Memory.h" +#include "Emu/System.h" #include "Emu/CPU/CPUThread.h" #include "Emu/Cell/PPUThread.h" #include "Emu/ARMv7/ARMv7Thread.h" +#include "Emu/SysCalls/lv2/sys_time.h" + +#ifdef _WIN32 +#include +#else +#include + +/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif +#endif + namespace vm { - #ifdef _WIN32 - #include - void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); - #else - #include +#ifdef _WIN32 + HANDLE g_memory_handle; +#endif - /* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ - #ifndef MAP_ANONYMOUS - #define MAP_ANONYMOUS MAP_ANON - #endif + void* g_priv_addr; - void* const g_base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); - #endif + void* initialize() + { +#ifdef _WIN32 + g_memory_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0x1, 0x0, NULL); + + void* base_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // main memory + g_priv_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // memory mirror for privileged access + + return base_addr; + //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); +#else + return mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +#endif + } + + void finalize() + { +#ifdef _WIN32 + UnmapViewOfFile(g_base_addr); + UnmapViewOfFile(g_priv_addr); + CloseHandle(g_memory_handle); +#else + munmap(g_base_addr, 0x100000000); +#endif + } + + void* const g_base_addr = (atexit(finalize), initialize()); + + void* g_reservation_owner = nullptr; + u32 g_reservation_addr = 0; + + std::function g_reservation_cb = nullptr; + + // break the reservation, return true if it was successfully broken + bool reservation_break(u32 addr) + { + LV2_LOCK(0); + + if (g_reservation_addr >> 12 == addr >> 12) + { + const auto stamp0 = get_time(); + +#ifdef _WIN32 + if (!VirtualAlloc(vm::get_ptr(addr & ~0xfff), 4096, MEM_COMMIT, PAGE_READWRITE)) +#else + +#endif + { + throw fmt::format("vm::reservation_break() failed (addr=0x%x)", addr); + } + + //LOG_NOTICE(MEMORY, "VirtualAlloc: %f us", (get_time() - stamp0) / 80.f); + + if (g_reservation_cb) + { + g_reservation_cb(); + g_reservation_cb = nullptr; + } + + g_reservation_owner = nullptr; + g_reservation_addr = 0; + + return true; + } + + return false; + } + + // read memory and reserve it for further atomic update, return true if the previous reservation was broken + bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback) + { + const auto stamp0 = get_time(); + + bool broken = false; + + assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); + assert((addr + size & ~0xfff) == (addr & ~0xfff)); + + { + LV2_LOCK(0); + + // break previous reservation + if (g_reservation_addr) + { + broken = reservation_break(g_reservation_addr); + } + + // change memory protection to read-only +#ifdef _WIN32 + DWORD old; + if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) +#else + +#endif + { + throw fmt::format("vm::reservation_acquire() failed (addr=0x%x, size=%d)", addr, size); + } + + //LOG_NOTICE(MEMORY, "VirtualProtect: %f us", (get_time() - stamp0) / 80.f); + + // set the new reservation + g_reservation_addr = addr; + g_reservation_owner = GetCurrentNamedThread(); + g_reservation_cb = callback; + + // copy data + memcpy(data, vm::get_ptr(addr), size); + } + + return broken; + } + + // attempt to atomically update reserved memory + bool reservation_update(u32 addr, const void* data, u32 size) + { + assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); + assert((addr + size & ~0xfff) == (addr & ~0xfff)); + + LV2_LOCK(0); + + if (g_reservation_addr != addr || g_reservation_owner != GetCurrentNamedThread()) + { + // atomic update failed + return false; + } + + // update memory using privileged access + memcpy(vm::get_priv_ptr(addr), data, size); + + // free the reservation and restore memory protection + reservation_break(addr); + + // atomic update succeeded + return true; + } + + // for internal use + bool reservation_query(u32 addr) + { + LV2_LOCK(0); + + if (!Memory.IsGoodAddr(addr)) + { + return false; + } + + // break the reservation + reservation_break(addr); + + return true; + } + + // for internal use + void reservation_free() + { + LV2_LOCK(0); + + if (g_reservation_owner == GetCurrentNamedThread()) + { + reservation_break(g_reservation_addr); + } + } bool check_addr(u32 addr) { diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 7cc958c3ba..32bcf17859 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -21,7 +21,19 @@ namespace vm static void set_stack_size(u32 size) {} static void initialize_stack() {} +#ifdef _WIN32 + extern HANDLE g_memory_handle; +#endif + + extern void* g_priv_addr; extern void* const g_base_addr; + + bool reservation_break(u32 addr); + bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback = nullptr); + bool reservation_update(u32 addr, const void* data, u32 size); + bool reservation_query(u32 addr); + void reservation_free(); + bool map(u32 addr, u32 size, u32 flags); bool unmap(u32 addr, u32 size = 0, u32 flags = 0); u32 alloc(u32 size, memory_location location = user_space); @@ -40,6 +52,18 @@ namespace vm return *get_ptr(addr); } + template + T* const get_priv_ptr(u32 addr) + { + return reinterpret_cast(static_cast(g_priv_addr) + addr); + } + + template + T& get_priv_ref(u32 addr) + { + return *get_priv_ptr(addr); + } + u32 get_addr(const void* real_pointer); __noinline void error(const u64 addr, const char* func); From 39db6bb4615d03a704aa283c9077d69da0639a6d Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 16:46:42 +0300 Subject: [PATCH 10/15] Reservations improved --- rpcs3/Emu/Cell/PPULLVMRecompiler.cpp | 204 ++++++++++--------- rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp | 15 -- rpcs3/Emu/Cell/SPUThread.cpp | 12 +- rpcs3/Emu/Memory/Memory.cpp | 22 +- rpcs3/Emu/Memory/vm.cpp | 190 +++++++++++++---- rpcs3/Emu/Memory/vm.h | 7 +- rpcs3/Emu/Memory/vm_ptr.h | 15 ++ rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp | 11 +- rpcs3/Emu/SysCalls/lv2/cellFs.cpp | 2 +- 9 files changed, 308 insertions(+), 170 deletions(-) diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 5678d5f9d9..99203e1864 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -2463,25 +2463,27 @@ void Compiler::MFOCRF(u32 a, u32 rd, u32 crm) { } void Compiler::LWARX(u32 rd, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; + + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); - auto resv_val_i32 = ReadMemory(addr_i64, 32, 4, false, false); - auto resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); + //auto resv_val_i32 = ReadMemory(addr_i64, 32, 4, false, false); + //auto resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); - resv_val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), resv_val_i32); - resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); - SetGpr(rd, resv_val_i64); + //resv_val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), resv_val_i32); + //resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); + //SetGpr(rd, resv_val_i64); } void Compiler::LDX(u32 rd, u32 ra, u32 rb) { @@ -2739,23 +2741,25 @@ void Compiler::MULHW(u32 rd, u32 ra, u32 rb, bool rc) { } void Compiler::LDARX(u32 rd, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); - resv_val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), resv_val_i64); - SetGpr(rd, resv_val_i64); + //auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); + + //resv_val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), resv_val_i64); + //SetGpr(rd, resv_val_i64); } void Compiler::DCBF(u32 ra, u32 rb) { @@ -2919,45 +2923,47 @@ void Compiler::STDX(u32 rs, u32 ra, u32 rb) { } void Compiler::STWCX_(u32 rs, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); - auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); - auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); - auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); - m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); + //auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); - m_ir_builder->SetInsertPoint(then_bb); - auto rs_i32 = GetGpr(rs, 32); - rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32); - resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); - auto resv_addr_val_i32_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt32Ty()->getPointerTo()); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i32_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); - auto resv_val_i32 = m_ir_builder->CreateAlignedLoad(resv_val_i32_ptr, 8); + //auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); + //auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); + //auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); + //m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); - auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); - auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); - auto cr_i32 = GetCr(); - cr_i32 = SetBit(cr_i32, 2, success_i1); - SetCr(cr_i32); - m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); - m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(then_bb); + //auto rs_i32 = GetGpr(rs, 32); + //rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32); + //resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + //auto resv_addr_val_i32_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt32Ty()->getPointerTo()); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i32_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); + //auto resv_val_i32 = m_ir_builder->CreateAlignedLoad(resv_val_i32_ptr, 8); - m_ir_builder->SetInsertPoint(else_bb); - cr_i32 = GetCr(); - cr_i32 = ClrBit(cr_i32, 2); - SetCr(cr_i32); - m_ir_builder->CreateBr(merge_bb); - m_ir_builder->SetInsertPoint(merge_bb); + //auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); + //auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); + //auto cr_i32 = GetCr(); + //cr_i32 = SetBit(cr_i32, 2, success_i1); + //SetCr(cr_i32); + //m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); + //m_ir_builder->CreateBr(merge_bb); + + //m_ir_builder->SetInsertPoint(else_bb); + //cr_i32 = GetCr(); + //cr_i32 = ClrBit(cr_i32, 2); + //SetCr(cr_i32); + //m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(merge_bb); } void Compiler::STWX(u32 rs, u32 ra, u32 rb) { @@ -3060,45 +3066,47 @@ void Compiler::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) { } void Compiler::STDCX_(u32 rs, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); - auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); - auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); - auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); - m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); + //auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); - m_ir_builder->SetInsertPoint(then_bb); - auto rs_i64 = GetGpr(rs, 64); - rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64); - resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); - auto resv_addr_val_i64_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_val_i64 = m_ir_builder->CreateAlignedLoad(resv_val_i64_ptr, 8); + //auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); + //auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); + //auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); + //m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); - auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); - auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); - auto cr_i32 = GetCr(); - cr_i32 = SetBit(cr_i32, 2, success_i1); - SetCr(cr_i32); - m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); - m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(then_bb); + //auto rs_i64 = GetGpr(rs, 64); + //rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64); + //resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + //auto resv_addr_val_i64_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_val_i64 = m_ir_builder->CreateAlignedLoad(resv_val_i64_ptr, 8); - m_ir_builder->SetInsertPoint(else_bb); - cr_i32 = GetCr(); - cr_i32 = ClrBit(cr_i32, 2); - SetCr(cr_i32); - m_ir_builder->CreateBr(merge_bb); - m_ir_builder->SetInsertPoint(merge_bb); + //auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); + //auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); + //auto cr_i32 = GetCr(); + //cr_i32 = SetBit(cr_i32, 2, success_i1); + //SetCr(cr_i32); + //m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); + //m_ir_builder->CreateBr(merge_bb); + + //m_ir_builder->SetInsertPoint(else_bb); + //cr_i32 = GetCr(); + //cr_i32 = ClrBit(cr_i32, 2); + //SetCr(cr_i32); + //m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(merge_bb); } void Compiler::STBX(u32 rs, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp index f30a713c09..e1054ecc89 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp @@ -59,10 +59,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp /// Time base register u64 TB; - /// Reservations - u64 R_ADDR; - u64 R_VALUE; - /// Memory block u32 address; u64 mem_block[64]; @@ -86,9 +82,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp CTR = ppu.CTR; TB = ppu.TB; - R_ADDR = ppu.R_ADDR; - R_VALUE = ppu.R_VALUE; - address = addr; for (int i = 0; i < (sizeof(mem_block) / 8); i++) { mem_block[i] = vm::read64(address + (i * 8)); @@ -114,9 +107,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp ppu.CTR = CTR; ppu.TB = TB; - ppu.R_ADDR = R_ADDR; - ppu.R_VALUE = R_VALUE; - for (int i = 0; i < (sizeof(mem_block) / 8); i++) { vm::write64(address + (i * 8), mem_block[i]); } @@ -151,8 +141,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp LR = rng(); CTR = rng(); TB = rng(); - R_ADDR = rng(); - R_VALUE = rng(); address = addr; for (int i = 0; i < (sizeof(mem_block) / 8); i++) { @@ -187,7 +175,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp // fmt::by_value(FPSCR.VXZDZ), fmt::by_value(FPSCR.VXIDI), fmt::by_value(FPSCR.VXISI), fmt::by_value(FPSCR.VXSNAN), // fmt::by_value(FPSCR.XX), fmt::by_value(FPSCR.ZX), fmt::by_value(FPSCR.UX), fmt::by_value(FPSCR.OX), fmt::by_value(FPSCR.VX), fmt::by_value(FPSCR.FEX), fmt::by_value(FPSCR.FX)); //ret += fmt::Format("VSCR = 0x%08x [NJ=%d | SAT=%d]\n", VSCR.VSCR, fmt::by_value(VSCR.NJ), fmt::by_value(VSCR.SAT)); // TODO: Uncomment after implementing VSCR.SAT - ret += fmt::Format("R_ADDR = 0x%016llx R_VALUE = 0x%016llx\n", R_ADDR, R_VALUE); for (int i = 0; i < (sizeof(mem_block) / 8); i += 2) { ret += fmt::Format("mem_block[%d] = 0x%016llx mem_block[%d] = 0x%016llx\n", i, mem_block[i], i + 1, mem_block[i + 1]); @@ -724,8 +711,6 @@ void Compiler::RunAllTests() { input.GPR[14] = 10; input.GPR[21] = 15; input.GPR[23] = 0x10000; - input.R_ADDR = 0x10000; - input.R_VALUE = 0x1122334455667788; input.mem_block[0] = 0x8877665544332211; VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 0, input, 5, 0, 0x10000); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 71033cbd9d..2bd0e0f629 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -435,10 +435,20 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) if (op == MFC_GETLLAR_CMD) // get reservation { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + //std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack vm::reservation_acquire(vm::get_ptr(ls_offset + lsa), ea, 128, [this]() { + //std::shared_ptr t = Emu.GetCPU().GetThread(tid); + + //if (t && (t->GetType() == CPU_THREAD_SPU || t->GetType() == CPU_THREAD_RAW_SPU)) + //{ + // SPUThread& spu = static_cast(*t); + + // spu.m_events |= SPU_EVENT_LR; // TODO: atomic op + // spu.Notify(); + //} + m_events |= SPU_EVENT_LR; // TODO: atomic op Notify(); }); diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index b892bff2b8..ecd4961d82 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -232,21 +232,13 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) : MemInfo(_addr, PAGE_4K(_size)) { void* real_addr = vm::get_ptr(vm::cast(_addr)); -#ifdef _WIN32 void* priv_addr = vm::get_priv_ptr(vm::cast(_addr)); - void* priv_mem = VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE); - mem = priv_mem == priv_addr ? VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE) : priv_mem; + +#ifdef _WIN32 + if (!VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE) || !VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE)) #else - if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE)) - { - mem = nullptr; - } - else - { - mem = real_addr; - } + if (!::mprotect(real_addr, size, PROT_READ | PROT_WRITE) || !::mprotect(priv_addr, size, PROT_READ | PROT_WRITE)) #endif - if (mem != real_addr) { LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%x)", addr, size); Emu.Pause(); @@ -254,7 +246,9 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) else { Memory.RegisterPages(_addr, PAGE_4K(_size)); - memset(mem, 0, size); + + mem = real_addr; + memset(mem, 0, size); // ??? } } @@ -269,7 +263,7 @@ void MemBlockInfo::Free() if (!VirtualProtect(mem, size, PAGE_NOACCESS, &old) || !VirtualProtect(vm::get_priv_ptr(vm::cast(addr)), size, PAGE_NOACCESS, &old)) //if (!VirtualFree(mem, size, MEM_DECOMMIT)) #else - if (::mprotect(mem, size, PROT_NONE)) + if (::mprotect(mem, size, PROT_NONE) || !::mprotect(vm::get_priv_ptr(vm::cast(addr)), size, PROT_NONE)) #endif { LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%llx, size=0x%x)", addr, size); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index a32d176b2e..55564a371f 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -23,6 +23,8 @@ namespace vm { #ifdef _WIN32 HANDLE g_memory_handle; +#else + int g_memory_handle; #endif void* g_priv_addr; @@ -36,9 +38,17 @@ namespace vm g_priv_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // memory mirror for privileged access return base_addr; + //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); #else - return mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + g_memory_handle = shm_open("/rpcs3_vm", O_RDWR, 0); + + void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); + g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); + + return base_addr; + + //return mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); #endif } @@ -50,32 +60,112 @@ namespace vm CloseHandle(g_memory_handle); #else munmap(g_base_addr, 0x100000000); + munmap(g_priv_addr, 0x100000000); + + shm_unlink("/rpcs3_vm"); #endif } void* const g_base_addr = (atexit(finalize), initialize()); - void* g_reservation_owner = nullptr; - u32 g_reservation_addr = 0; + class reservation_mutex_t + { + std::atomic m_owner; + std::condition_variable m_cv; + std::atomic test; + std::mutex m_cv_mutex; + + public: + reservation_mutex_t() + : m_owner(nullptr) + , test(0) + { + } + + bool do_notify; + + __noinline void lock() + { + NamedThreadBase* owner = GetCurrentNamedThread(); + NamedThreadBase* old = nullptr; + + while (!m_owner.compare_exchange_strong(old, owner)) + { + std::unique_lock cv_lock(m_cv_mutex); + + m_cv.wait_for(cv_lock, std::chrono::milliseconds(1)); + + if (old == owner) + { + throw __FUNCTION__; + } + + old = nullptr; + } + + do_notify = true; + + test++; + assert(test == 1); + } + + __noinline void unlock() + { + assert(test == 1); + test--; + + NamedThreadBase* owner = GetCurrentNamedThread(); + + if (!m_owner.compare_exchange_strong(owner, nullptr)) + { + throw __FUNCTION__; + } + + if (do_notify) + { + m_cv.notify_one(); + } + } + + }; std::function g_reservation_cb = nullptr; + NamedThreadBase* g_reservation_owner = nullptr; - // break the reservation, return true if it was successfully broken - bool reservation_break(u32 addr) + u32 g_reservation_addr = 0; + + reservation_mutex_t g_reservation_mutex; + + void _reservation_set(u32 addr) { - LV2_LOCK(0); + //const auto stamp0 = get_time(); +#ifdef _WIN32 + DWORD old; + if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) +#else + if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ)) +#endif + { + throw fmt::format("vm::_reservation_set() failed (addr=0x%x)", addr); + } + + //LOG_NOTICE(MEMORY, "VirtualProtect: %f us", (get_time() - stamp0) / 80.f); + } + + bool _reservation_break(u32 addr) + { if (g_reservation_addr >> 12 == addr >> 12) { - const auto stamp0 = get_time(); + //const auto stamp0 = get_time(); #ifdef _WIN32 if (!VirtualAlloc(vm::get_ptr(addr & ~0xfff), 4096, MEM_COMMIT, PAGE_READWRITE)) #else - + if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ | PROT_WRITE)) #endif { - throw fmt::format("vm::reservation_break() failed (addr=0x%x)", addr); + throw fmt::format("vm::_reservation_break() failed (addr=0x%x)", addr); } //LOG_NOTICE(MEMORY, "VirtualAlloc: %f us", (get_time() - stamp0) / 80.f); @@ -95,8 +185,14 @@ namespace vm return false; } - // read memory and reserve it for further atomic update, return true if the previous reservation was broken - bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback) + bool reservation_break(u32 addr) + { + std::lock_guard lock(g_reservation_mutex); + + return _reservation_break(addr); + } + + bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback) { const auto stamp0 = get_time(); @@ -106,28 +202,21 @@ namespace vm assert((addr + size & ~0xfff) == (addr & ~0xfff)); { - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); + + // silent unlocking to prevent priority boost for threads going to break reservation + g_reservation_mutex.do_notify = false; // break previous reservation if (g_reservation_addr) { - broken = reservation_break(g_reservation_addr); + broken = _reservation_break(g_reservation_addr); } // change memory protection to read-only -#ifdef _WIN32 - DWORD old; - if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) -#else + _reservation_set(addr); -#endif - { - throw fmt::format("vm::reservation_acquire() failed (addr=0x%x, size=%d)", addr, size); - } - - //LOG_NOTICE(MEMORY, "VirtualProtect: %f us", (get_time() - stamp0) / 80.f); - - // set the new reservation + // set additional information g_reservation_addr = addr; g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = callback; @@ -139,13 +228,12 @@ namespace vm return broken; } - // attempt to atomically update reserved memory bool reservation_update(u32 addr, const void* data, u32 size) { assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); assert((addr + size & ~0xfff) == (addr & ~0xfff)); - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); if (g_reservation_addr != addr || g_reservation_owner != GetCurrentNamedThread()) { @@ -157,39 +245,69 @@ namespace vm memcpy(vm::get_priv_ptr(addr), data, size); // free the reservation and restore memory protection - reservation_break(addr); + _reservation_break(addr); // atomic update succeeded return true; } - // for internal use bool reservation_query(u32 addr) { - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); - if (!Memory.IsGoodAddr(addr)) { - return false; + LV2_LOCK(0); + + if (!Memory.IsGoodAddr(addr)) + { + return false; + } } // break the reservation - reservation_break(addr); + _reservation_break(addr); return true; } - // for internal use void reservation_free() { - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); if (g_reservation_owner == GetCurrentNamedThread()) { - reservation_break(g_reservation_addr); + _reservation_break(g_reservation_addr); } } + void reservation_op(u32 addr, u32 size, std::function proc) + { + assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); + assert((addr + size & ~0xfff) == (addr & ~0xfff)); + + std::lock_guard lock(g_reservation_mutex); + + // break previous reservation + if (g_reservation_addr) + { + _reservation_break(g_reservation_addr); + } + + // change memory protection to read-only + _reservation_set(addr); + + // set additional information + g_reservation_addr = addr; + g_reservation_owner = GetCurrentNamedThread(); + g_reservation_cb = nullptr; + + // do the operation + proc(); + + // remove the reservation + _reservation_break(addr); + } + bool check_addr(u32 addr) { // Checking address before using it is unsafe. diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 32bcf17859..559ccb15e6 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -28,11 +28,16 @@ namespace vm extern void* g_priv_addr; extern void* const g_base_addr; + // break the reservation, return true if it was successfully broken bool reservation_break(u32 addr); - bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback = nullptr); + // read memory and reserve it for further atomic update, return true if the previous reservation was broken + bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback = nullptr); + // attempt to atomically update reserved memory bool reservation_update(u32 addr, const void* data, u32 size); bool reservation_query(u32 addr); void reservation_free(); + // perform complete operation + void reservation_op(u32 addr, u32 size, std::function proc); bool map(u32 addr, u32 size, u32 flags); bool unmap(u32 addr, u32 size = 0, u32 flags = 0); diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 0c588cd7ee..68d940ea6b 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -213,6 +213,11 @@ namespace vm { return vm::get_ptr(vm::cast(m_addr)); } + + T* get_priv_ptr() const + { + return vm::get_priv_ptr(vm::cast(m_addr)); + } static const _ptr_base make(const AT& addr) { @@ -243,6 +248,11 @@ namespace vm return vm::get_ptr(vm::cast(m_addr)); } + void* get_priv_ptr() const + { + return vm::get_priv_ptr(vm::cast(m_addr)); + } + explicit operator void*() const { return get_ptr(); @@ -301,6 +311,11 @@ namespace vm return vm::get_ptr(vm::cast(m_addr)); } + const void* get_priv_ptr() const + { + return vm::get_priv_ptr(vm::cast(m_addr)); + } + explicit operator const void*() const { return get_ptr(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp index 69445ccb17..28828c9d38 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp @@ -136,7 +136,7 @@ const char *getModuleName(int id) { } } - return 0; + return "UNKNOWN MODULE"; } int cellSysmoduleInitialize() @@ -159,11 +159,12 @@ int cellSysmoduleSetMemcontainer(u32 ct_id) int cellSysmoduleLoadModule(u16 id) { + cellSysmodule->Warning("cellSysmoduleLoadModule(id=0x%04x: %s)", id, getModuleName(id)); + if (id == 0xf054) { cellSysmodule->Todo("cellSysmoduleLoadModule: CELL_SYSMODULE_LIBATRAC3MULTI"); } - cellSysmodule->Warning("cellSysmoduleLoadModule(%s)", getModuleName(id)); if (Module* m = Emu.GetModuleManager().GetModuleById(id)) { @@ -180,7 +181,8 @@ int cellSysmoduleLoadModule(u16 id) int cellSysmoduleUnloadModule(u16 id) { - cellSysmodule->Warning("cellSysmoduleUnloadModule(%s)", getModuleName(id)); + cellSysmodule->Warning("cellSysmoduleUnloadModule(id=0x%04x: %s)", id, getModuleName(id)); + Module* m = Emu.GetModuleManager().GetModuleById(id); if(!m) @@ -199,7 +201,8 @@ int cellSysmoduleUnloadModule(u16 id) int cellSysmoduleIsLoaded(u16 id) { - cellSysmodule->Warning("cellSysmoduleIsLoaded(%s)", getModuleName(id)); + cellSysmodule->Warning("cellSysmoduleIsLoaded(id=0x%04x: %s)", id, getModuleName(id)); + Module* m = Emu.GetModuleManager().GetModuleById(id); if(!m) diff --git a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp index 38ea4fc729..ca72b045ac 100644 --- a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp @@ -395,7 +395,7 @@ s32 cellFsFsync(u32 fd) s32 cellFsRmdir(vm::ptr path) { - sys_fs->Warning("cellFsRmdir(path=0x%x)", path.get_ptr()); + sys_fs->Warning("cellFsRmdir(path=0x%x)", path); std::string _path = path.get_ptr(); From c71c5eb422d3ae4ac24e49e39da6e080bc615086 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 16:59:10 +0300 Subject: [PATCH 11/15] Compilation fix --- rpcs3/Emu/Memory/vm.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 55564a371f..1f03c77434 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -12,6 +12,8 @@ #include #else #include +#include +#include /* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ #ifndef MAP_ANONYMOUS From c9f994d92d9ba4253231dbaed0f8411b6bde4884 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 17:12:39 +0300 Subject: [PATCH 12/15] Fix 1 --- rpcs3/Emu/Memory/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 1f03c77434..98761f8dd4 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -43,7 +43,7 @@ namespace vm //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); #else - g_memory_handle = shm_open("/rpcs3_vm", O_RDWR, 0); + g_memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREATE | O_EXCL, 0); void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); From 6aef58318c18ce660ff6429584d04b2b0518f39f Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 17:13:32 +0300 Subject: [PATCH 13/15] Fix 2 --- rpcs3/Emu/Memory/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 98761f8dd4..691d992b1e 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -43,7 +43,7 @@ namespace vm //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); #else - g_memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREATE | O_EXCL, 0); + g_memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREAT | O_EXCL, 0); void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); From e70875ad5cc1b9ffa69a44ce23f562c981447284 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 18:35:54 +0300 Subject: [PATCH 14/15] Linux fix --- rpcs3/Emu/Memory/Memory.cpp | 20 ++++++++------------ rpcs3/Emu/Memory/vm.cpp | 36 +++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index ecd4961d82..7f87615796 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -102,20 +102,17 @@ void MemoryBase::Init(MemoryType type) memset(m_pages, 0, sizeof(m_pages)); memset(RawSPUMem, 0, sizeof(RawSPUMem)); + LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx, priv_addr = 0x%llx", (u64)vm::g_base_addr, (u64)vm::g_priv_addr); + #ifdef _WIN32 - if (!vm::g_base_addr) + if (!vm::g_base_addr || !vm::g_priv_addr) #else - if ((s64)vm::g_base_addr == (s64)-1) + if ((s64)vm::g_base_addr == (s64)-1 || (s64)vm::g_priv_addr == (s64)-1) #endif { LOG_ERROR(MEMORY, "Initializing memory failed"); - assert(0); return; } - else - { - LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx", (u64)vm::g_base_addr); - } switch (type) { @@ -207,7 +204,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size) } MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size)); - + LOG_WARNING(MEMORY, "Memory mapped at 0x%llx: size=0x%x", addr, size); return true; } @@ -237,7 +234,7 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) #ifdef _WIN32 if (!VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE) || !VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE)) #else - if (!::mprotect(real_addr, size, PROT_READ | PROT_WRITE) || !::mprotect(priv_addr, size, PROT_READ | PROT_WRITE)) + if (mprotect(real_addr, size, PROT_READ | PROT_WRITE) || mprotect(priv_addr, size, PROT_READ | PROT_WRITE)) #endif { LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%x)", addr, size); @@ -261,9 +258,8 @@ void MemBlockInfo::Free() DWORD old; if (!VirtualProtect(mem, size, PAGE_NOACCESS, &old) || !VirtualProtect(vm::get_priv_ptr(vm::cast(addr)), size, PAGE_NOACCESS, &old)) - //if (!VirtualFree(mem, size, MEM_DECOMMIT)) #else - if (::mprotect(mem, size, PROT_NONE) || !::mprotect(vm::get_priv_ptr(vm::cast(addr)), size, PROT_NONE)) + if (mprotect(mem, size, PROT_NONE) || mprotect(vm::get_priv_ptr(vm::cast(addr)), size, PROT_NONE)) #endif { LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%llx, size=0x%x)", addr, size); @@ -436,7 +432,7 @@ u64 DynamicMemoryBlockBase::AllocAlign(u32 size, u32 align) LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocAlign(size=0x%x, align=0x%x): memory block not initialized", size, align); return 0; } - + size = PAGE_4K(size); u32 exsize; diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 691d992b1e..894e3aff70 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include /* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ #ifndef MAP_ANONYMOUS @@ -25,8 +27,6 @@ namespace vm { #ifdef _WIN32 HANDLE g_memory_handle; -#else - int g_memory_handle; #endif void* g_priv_addr; @@ -43,10 +43,22 @@ namespace vm //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); #else - g_memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREAT | O_EXCL, 0); + //shm_unlink("/rpcs3_vm"); - void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); - g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); + int memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREAT | O_EXCL, 0); + + if (memory_handle == -1) + { + printf("shm_open() failed\n"); + return (void*)-1; + } + + ftruncate(memory_handle, 0x100000000); + + void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_SHARED, memory_handle, 0); + g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_SHARED, memory_handle, 0); + + shm_unlink("/rpcs3_vm"); return base_addr; @@ -63,8 +75,6 @@ namespace vm #else munmap(g_base_addr, 0x100000000); munmap(g_priv_addr, 0x100000000); - - shm_unlink("/rpcs3_vm"); #endif } @@ -94,7 +104,7 @@ namespace vm while (!m_owner.compare_exchange_strong(old, owner)) { std::unique_lock cv_lock(m_cv_mutex); - + m_cv.wait_for(cv_lock, std::chrono::milliseconds(1)); if (old == owner) @@ -146,7 +156,7 @@ namespace vm DWORD old; if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) #else - if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ)) + if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ)) #endif { throw fmt::format("vm::_reservation_set() failed (addr=0x%x)", addr); @@ -164,7 +174,7 @@ namespace vm #ifdef _WIN32 if (!VirtualAlloc(vm::get_ptr(addr & ~0xfff), 4096, MEM_COMMIT, PAGE_READWRITE)) #else - if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ | PROT_WRITE)) + if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ | PROT_WRITE)) #endif { throw fmt::format("vm::_reservation_break() failed (addr=0x%x)", addr); @@ -297,7 +307,7 @@ namespace vm // change memory protection to read-only _reservation_set(addr); - + // set additional information g_reservation_addr = addr; g_reservation_owner = GetCurrentNamedThread(); @@ -352,7 +362,7 @@ namespace vm { return res; } - + if (real_pointer) { throw fmt::format("vm::get_addr(0x%016llx) failed: not a part of virtual memory", (u64)real_pointer); @@ -557,4 +567,4 @@ namespace vm } } } -} \ No newline at end of file +} From 90c021fc310ecd4d6290eaacd20e6ebc27cabcef Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 23:06:35 +0300 Subject: [PATCH 15/15] Small fix --- rpcs3/Emu/Memory/vm.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 894e3aff70..2e3aaae4ae 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -84,13 +84,11 @@ namespace vm { std::atomic m_owner; std::condition_variable m_cv; - std::atomic test; std::mutex m_cv_mutex; public: reservation_mutex_t() : m_owner(nullptr) - , test(0) { } @@ -116,16 +114,10 @@ namespace vm } do_notify = true; - - test++; - assert(test == 1); } __noinline void unlock() { - assert(test == 1); - test--; - NamedThreadBase* owner = GetCurrentNamedThread(); if (!m_owner.compare_exchange_strong(owner, nullptr)) @@ -206,7 +198,7 @@ namespace vm bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback) { - const auto stamp0 = get_time(); + //const auto stamp0 = get_time(); bool broken = false; @@ -217,7 +209,7 @@ namespace vm std::lock_guard lock(g_reservation_mutex); // silent unlocking to prevent priority boost for threads going to break reservation - g_reservation_mutex.do_notify = false; + //g_reservation_mutex.do_notify = false; // break previous reservation if (g_reservation_addr) @@ -228,6 +220,9 @@ namespace vm // change memory protection to read-only _reservation_set(addr); + // may not be necessary, just for sure: + _mm_mfence(); + // set additional information g_reservation_addr = addr; g_reservation_owner = GetCurrentNamedThread(); @@ -313,6 +308,9 @@ namespace vm g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = nullptr; + // may not be necessary, just for sure: + _mm_mfence(); + // do the operation proc();