From df72f5e37cd199729343765ef0db5b54b52f6335 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 2 Nov 2014 18:50:20 +0300 Subject: [PATCH] ARMv7: CMP_REG, LDR_IMM, LDR_LIT, STR_REG, SUB_REG sceLibc: exit and printf drafts This actually allows to display hello world. --- Utilities/Log.h | 5 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 240 +++++++++++++++++++++++++-- rpcs3/Emu/ARMv7/ARMv7Interpreter.h | 29 +++- rpcs3/Emu/ARMv7/ARMv7Thread.h | 2 +- rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 18 +- rpcs3/Loader/ELF32.cpp | 2 +- 6 files changed, 268 insertions(+), 28 deletions(-) diff --git a/Utilities/Log.h b/Utilities/Log.h index 8dbeb71e07..46fc604f5a 100644 --- a/Utilities/Log.h +++ b/Utilities/Log.h @@ -24,6 +24,7 @@ namespace Log HLE, PPU, SPU, + ARMv7, TTY, }; @@ -35,7 +36,7 @@ namespace Log }; //well I'd love make_array() but alas manually counting is not the end of the world - static const std::array gTypeNameTable = { { + static const std::array gTypeNameTable = { { { GENERAL, "G: " }, { LOADER, "LDR: " }, { MEMORY, "MEM: " }, @@ -43,6 +44,7 @@ namespace Log { HLE, "HLE: " }, { PPU, "PPU: " }, { SPU, "SPU: " }, + { ARMv7, "ARM: " }, { TTY, "TTY: " } } }; @@ -121,6 +123,7 @@ static struct { inline operator Log::LogType() { return Log::LogType::RSX; } } R static struct { inline operator Log::LogType() { return Log::LogType::HLE; } } HLE; static struct { inline operator Log::LogType() { return Log::LogType::PPU; } } PPU; static struct { inline operator Log::LogType() { return Log::LogType::SPU; } } SPU; +static struct { inline operator Log::LogType() { return Log::LogType::ARMv7; } } ARMv7; static struct { inline operator Log::LogType() { return Log::LogType::TTY; } } TTY; inline void log_message(Log::LogType type, Log::LogSeverity sev, const char* text) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 0ecf629c45..62a4838c27 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -210,7 +210,7 @@ void ARMv7Interpreter::ASR_REG(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::B(const u32 data, const ARMv7_encoding type) { u32 cond = CPU.ITSTATE.advance(); - u32 jump = 0; // jump = instr_size + imm32 + u32 jump = 0; // jump = instr_size + imm32 ??? switch (type) { @@ -222,12 +222,12 @@ void ARMv7Interpreter::B(const u32 data, const ARMv7_encoding type) throw "SVC"; } - jump = 2 + sign<9, u32>((data & 0xff) << 1); + jump = 4 + sign<9, u32>((data & 0xff) << 1); break; } case T2: { - jump = 2 + sign<12, u32>((data & 0x7ff) << 1); + jump = 4 + sign<12, u32>((data & 0x7ff) << 1); break; } case T3: @@ -235,7 +235,7 @@ void ARMv7Interpreter::B(const u32 data, const ARMv7_encoding type) cond = (data >> 6) & 0xf; if (cond >= 0xe) { - throw "Related encodings"; + throw "B_T3: Related encodings"; } u32 s = (data >> 26) & 0x1; @@ -254,7 +254,7 @@ void ARMv7Interpreter::B(const u32 data, const ARMv7_encoding type) } case A1: { - cond = (data >> 28) & 0xf; + cond = data >> 28; jump = 1 + 4 + sign<26, u32>((data & 0xffffff) << 2); break; } @@ -457,7 +457,7 @@ void ARMv7Interpreter::CB_Z(const u32 data, const ARMv7_encoding type) default: throw __FUNCTION__; } - if ((CPU.read_gpr(data & 0x7) == 0) ^ (data & 0x800)) + if ((CPU.read_gpr(data & 0x7) == 0) ^ ((data & 0x800) != 0)) { CPU.SetBranch(CPU.PC + 2 + ((data & 0xf8) >> 2) + ((data & 0x200) >> 3)); } @@ -513,11 +513,47 @@ void ARMv7Interpreter::CMP_IMM(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::CMP_REG(const u32 data, const ARMv7_encoding type) { + u32 cond = CPU.ITSTATE.advance(); + u32 n = 0; + u32 m = 0; + auto shift_t = SRType_LSL; + u32 shift_n = 0; + switch (type) { + case T1: + { + n = (data & 0x7); + m = (data & 0x38) >> 3; + break; + } + case T2: + { + n = (data & 0x80) >> 4 | (data & 0x7); + m = (data & 0x78) >> 3; + break; + } + case T3: + { + n = (data & 0xf0000) >> 16; + m = (data & 0xf); + shift_t = DecodeImmShift((data & 0x30) >> 4, (data & 0x7000) >> 10 | (data & 0xc0) >> 6, &shift_n); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + bool carry, overflow; + const u32 shifted = Shift(CPU.read_gpr(m), shift_t, shift_n, true); + const u32 res = AddWithCarry(CPU.read_gpr(n), ~shifted, true, carry, overflow); + CPU.APSR.N = res >> 31; + CPU.APSR.Z = res == 0; + CPU.APSR.C = carry; + CPU.APSR.V = overflow; + } } void ARMv7Interpreter::CMP_RSR(const u32 data, const ARMv7_encoding type) @@ -566,7 +602,7 @@ void ARMv7Interpreter::IT(const u32 data, const ARMv7_encoding type) { if ((data & 0xf) == 0) { - throw "Related encodings"; + throw "IT_T1: Related encodings"; } CPU.ITSTATE.IT = data & 0xff; @@ -616,11 +652,83 @@ void ARMv7Interpreter::LDMIB(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::LDR_IMM(const u32 data, const ARMv7_encoding type) { + u32 cond = CPU.ITSTATE.advance(); + u32 t = 0; + u32 n = 13; + u32 imm32 = 0; + bool index = true; + bool add = true; + bool wback = false; + switch (type) { - case A1: throw __FUNCTION__; + case T1: + { + t = (data & 0x7); + n = (data & 0x38) >> 3; + imm32 = (data & 0x7c0) >> 4; + break; + } + case T2: + { + t = (data & 0x700) >> 8; + imm32 = (data & 0xff) << 2; + break; + } + case T3: + { + t = (data & 0xf000) >> 12; + n = (data & 0xf0000) >> 16; + imm32 = (data & 0xfff); + + if (n == 15) + { + throw "LDR (literal)"; + } + break; + } + case T4: + { + t = (data & 0xf000) >> 12; + n = (data & 0xf0000) >> 16; + imm32 = (data & 0xff); + index = (data & 0x400); + add = (data & 0x200); + wback = (data & 0x100); + + if (n == 15) + { + throw "LDR (literal)"; + } + if (index && add && !wback) + { + throw "LDRT"; + } + if (n == 13 && !index && add && wback && imm32 == 4) + { + throw "POP"; + } + if (!index && !wback) + { + throw "LDR_IMM_T4: undefined"; + } + break; + } default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + const u32 offset_addr = add ? CPU.read_gpr(n) + imm32 : CPU.read_gpr(n) - imm32; + const u32 addr = index ? offset_addr : CPU.read_gpr(n); + + if (wback) + { + CPU.write_gpr(n, offset_addr); + } + + CPU.write_gpr(t, vm::psv::read32(addr)); + } } void ARMv7Interpreter::LDR_LIT(const u32 data, const ARMv7_encoding type) @@ -855,13 +963,13 @@ void ARMv7Interpreter::MOV_IMM(const u32 data, const ARMv7_encoding type) imm32 = sign<8, u32>(data & 0xff); break; } - //case T2: - //{ - // set_flags = data & 0x100000; - // d = (data >> 8) & 0xf; - // imm32 = ThumbExpandImm_C((data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff), carry); - // break; - //} + case T2: + { + set_flags = data & 0x100000; + d = (data >> 8) & 0xf; + imm32 = ThumbExpandImm_C((data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff), carry, carry); + break; + } case T3: { set_flags = false; @@ -1115,7 +1223,7 @@ void ARMv7Interpreter::POP(const u32 data, const ARMv7_encoding type) { case T1: { - reg_list = ((data & 0x100) << 6) | (data & 0xff); + reg_list = ((data & 0x100) << 7) | (data & 0xff); break; } case T2: @@ -1830,7 +1938,7 @@ void ARMv7Interpreter::STR_IMM(const u32 data, const ARMv7_encoding type) if (n == 0xf) { - throw "STR_IMM_T3 UNDEFINED"; + throw "STR_IMM_T3: undefined"; } break; } @@ -1853,7 +1961,7 @@ void ARMv7Interpreter::STR_IMM(const u32 data, const ARMv7_encoding type) } if (n == 15 || (!index && !wback)) { - throw "STR_IMM_T4 UNDEFINED"; + throw "STR_IMM_T4: undefined"; } break; } @@ -1877,11 +1985,55 @@ void ARMv7Interpreter::STR_IMM(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::STR_REG(const u32 data, const ARMv7_encoding type) { + u32 cond = CPU.ITSTATE.advance(); + u32 t = 0; + u32 n = 0; + u32 m = 0; + bool index = true; + bool add = true; + bool wback = false; + auto shift_t = SRType_LSL; + u32 shift_n = 0; + switch (type) { + case T1: + { + t = (data & 0x7); + n = (data & 0x38) >> 3; + m = (data & 0x1c0) >> 6; + break; + } + case T2: + { + t = (data & 0xf000) >> 12; + n = (data & 0xf0000) >> 16; + m = (data & 0xf); + shift_n = (data & 0x30) >> 4; + + if (n == 15) + { + throw "STR_REG_T2: undefined"; + } + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + const u32 offset = Shift(CPU.read_gpr(m), shift_t, shift_n, CPU.APSR.C); + const u32 offset_addr = add ? CPU.read_gpr(n) + offset : CPU.read_gpr(n) - offset; + const u32 addr = index ? offset_addr : CPU.read_gpr(n); + + vm::psv::write32(addr, CPU.read_gpr(t)); + + if (wback) + { + CPU.write_gpr(n, offset_addr); + } + } } @@ -1953,11 +2105,63 @@ void ARMv7Interpreter::SUB_IMM(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::SUB_REG(const u32 data, const ARMv7_encoding type) { + bool set_flags = !CPU.ITSTATE; + u32 cond = CPU.ITSTATE.advance(); + u32 d = 0; + u32 n = 0; + u32 m = 0; + auto shift_t = SRType_LSL; + u32 shift_n = 0; + switch (type) { + case T1: + { + d = (data & 0x7); + n = (data & 0x38) >> 3; + m = (data & 0x1c0) >> 6; + break; + } + case T2: + { + d = (data & 0xf00) >> 8; + n = (data & 0xf0000) >> 16; + m = (data & 0xf); + set_flags = (data & 0x100000); + shift_t = DecodeImmShift((data & 0x30) >> 4, (data & 0x7000) >> 10 | (data & 0xc0) >> 6, &shift_n); + + if (d == 15 && set_flags) + { + throw "CMP (register)"; + } + if (n == 13) + { + throw "SUB (SP minus register)"; + } + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + u32 shifted = Shift(CPU.read_gpr(m), shift_t, shift_n, CPU.APSR.C); + if (set_flags) + { + bool carry, overflow; + u32 res = AddWithCarry(CPU.read_gpr(n), ~shifted, true, carry, overflow); + CPU.write_gpr(d, res); + CPU.APSR.N = res >> 31; + CPU.APSR.Z = res == 0; + CPU.APSR.C = carry; + CPU.APSR.V = overflow; + } + else + { + CPU.write_gpr(d, CPU.read_gpr(n) - shifted); + } + } } void ARMv7Interpreter::SUB_RSR(const u32 data, const ARMv7_encoding type) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index bfe7539967..da1b437c61 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -10,7 +10,7 @@ public: { } - enum SRType + enum SRType : u32 { SRType_None, SRType_LSL, @@ -93,7 +93,7 @@ public: return len - 1 - HighestSetBit(x, len); } - SRType DecodeImmShift(u8 type, u8 imm5, uint* shift_n) + SRType DecodeImmShift(u32 type, u32 imm5, u32* shift_n) { SRType shift_t = SRType_None; @@ -217,7 +217,7 @@ public: return value; } - template T Shift(T value, SRType type, uint amount, bool carry_in) + template T Shift(T value, SRType type, u32 amount, bool carry_in) { bool carry_out; return Shift_C(value, type, amount, carry_in, carry_out); @@ -239,6 +239,29 @@ public: return result; } + u32 ThumbExpandImm_C(u32 imm12, bool carry_in, bool& carry_out) + { + if ((imm12 & 0xc00) >> 10) + { + u32 unrotated_value = (imm12 & 0x7f) | 0x80; + + return ROR_C(unrotated_value, (imm12 & 0xf80) >> 7, carry_out); + } + else + { + carry_out = carry_in; + + u32 imm8 = imm12 & 0xff; + switch ((imm12 & 0x300) >> 8) + { + case 0: return imm8; + case 1: return imm8 << 16 | imm8; + case 2: return imm8 << 24 | imm8 << 8; + default: return imm8 << 24 | imm8 << 16 | imm8 << 8 | imm8; + } + } + } + bool ConditionPassed(u32 cond) const { bool result = false; diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index 0ef26562ff..4e1dd7d20b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -103,7 +103,7 @@ public: } else { - SetBranch(value); + SetBranch(value & ~1); } } diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index c02a2b5f1f..ac702a3e58 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -1,4 +1,6 @@ #include "stdafx.h" +#include "Emu/System.h" +#include "Emu/Memory/Memory.h" #include "Emu/ARMv7/PSVFuncList.h" extern psv_log_base& sceLibc; @@ -12,17 +14,25 @@ namespace sce_libc_func void exit() { - sceLibc.Todo(__FUNCTION__); + sceLibc.Error("exit()"); + Emu.Pause(); + sceLibc.Success("Process finished"); + CallAfter([]() + { + Emu.Stop(); + }); } - void printf() + void printf(vm::psv::ptr fmt) { - sceLibc.Todo(__FUNCTION__); + sceLibc.Error("printf(fmt_addr=0x%x)", fmt.addr()); + + LOG_NOTICE(TTY, "%s", fmt.get_ptr()); } void __cxa_set_dso_handle_main() { - sceLibc.Todo(__FUNCTION__); + sceLibc.Error("__cxa_set_dso_handle_main()"); } } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index d7765e5e32..b4c7d110cf 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -6,7 +6,7 @@ #include "Emu/ARMv7/PSVFuncList.h" #include "ELF32.h" -#define LOADER_DEBUG +//#define LOADER_DEBUG void Elf32_Ehdr::Show() {