1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 04:02:42 +01:00

ARMv7: CMP_REG, LDR_IMM, LDR_LIT, STR_REG, SUB_REG

sceLibc: exit and printf drafts
This actually allows to display hello world.
This commit is contained in:
Nekotekina 2014-11-02 18:50:20 +03:00
parent 31c71b4a48
commit df72f5e37c
6 changed files with 268 additions and 28 deletions

View File

@ -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<LogTypeName, 8> gTypeNameTable = { {
static const std::array<LogTypeName, 9> 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)

View File

@ -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)

View File

@ -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<typename T> T Shift(T value, SRType type, uint amount, bool carry_in)
template<typename T> 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;

View File

@ -103,7 +103,7 @@ public:
}
else
{
SetBranch(value);
SetBranch(value & ~1);
}
}

View File

@ -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<const char> 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()");
}
}

View File

@ -6,7 +6,7 @@
#include "Emu/ARMv7/PSVFuncList.h"
#include "ELF32.h"
#define LOADER_DEBUG
//#define LOADER_DEBUG
void Elf32_Ehdr::Show()
{