mirror of https://github.com/RPCS3/rpcs3.git
ARMv7 decoder reworked (needs more testing / fixes / optimisations). TODO: implement new ARMv7 disassembler (currently ARMv7DisAsm fully disabled), add 0x0 opcodes group.
This commit is contained in:
parent
b736b8616b
commit
c3696f7897
|
@ -1,35 +1,48 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Emu/CPU/CPUDecoder.h"
|
|
||||||
#include "ARMv7Opcodes.h"
|
|
||||||
|
|
||||||
|
#include "Emu/CPU/CPUDecoder.h"
|
||||||
|
#include "ARMv7Thread.h"
|
||||||
|
#include "ARMv7Interpreter.h"
|
||||||
|
#include "ARMv7Opcodes.h"
|
||||||
|
#include "Utilities/Log.h"
|
||||||
|
|
||||||
class ARMv7Decoder : public CPUDecoder
|
class ARMv7Decoder : public CPUDecoder
|
||||||
{
|
{
|
||||||
ARMv7Opcodes& m_op;
|
ARMv7Thread& m_thr;
|
||||||
u8 m_last_instr_size;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ARMv7Decoder(ARMv7Opcodes& op) : m_op(op)
|
ARMv7Decoder(ARMv7Thread& thr) : m_thr(thr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual u8 DecodeMemory(const u32 address)
|
virtual u8 DecodeMemory(const u32 address)
|
||||||
{
|
{
|
||||||
const u32 code0 = vm::psv::read16(address & ~1);
|
m_thr.update_code(address & ~1);
|
||||||
const u32 code1 = vm::psv::read16(address + 2 & ~1);
|
|
||||||
const u32 data = code0 << 16 | code1;
|
|
||||||
const u32 arg = address & 1 ? code1 << 16 | code0 : data;
|
|
||||||
|
|
||||||
|
// LOG_NOTICE(GENERAL, "code0 = 0x%04x, code1 = 0x%04x, data = 0x%08x", m_thr.code.code0, m_thr.code.code1, m_thr.code.data);
|
||||||
|
// LOG_NOTICE(GENERAL, "arg = 0x%08x", m_thr.m_arg);
|
||||||
|
// Emu.Pause();
|
||||||
|
|
||||||
|
// old decoding algorithm
|
||||||
|
/*
|
||||||
for (auto& opcode : ARMv7_opcode_table)
|
for (auto& opcode : ARMv7_opcode_table)
|
||||||
{
|
{
|
||||||
if ((opcode.type < A1) == ((address & 1) == 0) && (arg & opcode.mask) == opcode.code)
|
if ((opcode.type < A1) == ((address & 0x1) == 0) && (m_thr.m_arg & opcode.mask) == opcode.code)
|
||||||
{
|
{
|
||||||
(m_op.*opcode.func)(opcode.length == 2 ? code0 : arg, opcode.type);
|
m_thr.code.data = opcode.length == 2 ? m_thr.code.code0 : m_thr.m_arg;
|
||||||
|
(*opcode.func)(&m_thr, opcode.type);
|
||||||
|
// LOG_NOTICE(GENERAL, "%s, %d \n\n", opcode.name, opcode.length);
|
||||||
return opcode.length;
|
return opcode.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_op.UNK(data);
|
ARMv7_instrs::UNK(&m_thr);
|
||||||
return address & 1 ? 4 : 2;
|
return address & 0x1 ? 4 : 2;
|
||||||
|
*/
|
||||||
|
|
||||||
|
execute_main_group(&m_thr);
|
||||||
|
LOG_NOTICE(GENERAL, "%s, %d \n\n", m_thr.m_last_instr_name, m_thr.m_last_instr_size);
|
||||||
|
m_thr.m_last_instr_name = "Unknown";
|
||||||
|
return m_thr.m_last_instr_size;
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -12,10 +12,9 @@ static const char* g_arm_cond_name[16] =
|
||||||
|
|
||||||
class ARMv7DisAsm
|
class ARMv7DisAsm
|
||||||
: public CPUDisAsm
|
: public CPUDisAsm
|
||||||
, public ARMv7Opcodes
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ARMv7DisAsm(CPUDisAsmMode mode) : CPUDisAsm(mode)
|
ARMv7DisAsm() : CPUDisAsm(CPUDisAsm_InterpreterMode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,11 @@
|
||||||
#include "ARMv7DisAsm.h"
|
#include "ARMv7DisAsm.h"
|
||||||
#include "ARMv7Interpreter.h"
|
#include "ARMv7Interpreter.h"
|
||||||
|
|
||||||
ARMv7Thread::ARMv7Thread() : CPUThread(CPU_THREAD_ARMv7)
|
ARMv7Thread::ARMv7Thread()
|
||||||
|
: CPUThread(CPU_THREAD_ARMv7)
|
||||||
|
, m_arg(0)
|
||||||
|
, m_last_instr_size(0)
|
||||||
|
, m_last_instr_name("UNK")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +85,7 @@ void ARMv7Thread::DoRun()
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
m_dec = new ARMv7Decoder(*new ARMv7Interpreter(*this));
|
m_dec = new ARMv7Decoder(*this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Emu/CPU/CPUThread.h"
|
#include "Emu/CPU/CPUThread.h"
|
||||||
|
#include "Emu/Memory/Memory.h"
|
||||||
|
|
||||||
enum ARMv7InstructionSet
|
enum ARMv7InstructionSet
|
||||||
{
|
{
|
||||||
ARM,
|
ARM,
|
||||||
Thumb,
|
Thumb,
|
||||||
Jazelle,
|
Jazelle,
|
||||||
ThumbEE,
|
ThumbEE
|
||||||
};
|
};
|
||||||
|
|
||||||
class ARMv7Thread : public CPUThread
|
class ARMv7Thread : public CPUThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
u32 m_arg;
|
||||||
|
u8 m_last_instr_size;
|
||||||
|
const char* m_last_instr_name;
|
||||||
|
|
||||||
ARMv7Thread();
|
ARMv7Thread();
|
||||||
|
|
||||||
union
|
union
|
||||||
|
@ -61,6 +67,18 @@ public:
|
||||||
|
|
||||||
} IPSR;
|
} IPSR;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 code1 : 16;
|
||||||
|
u32 code0 : 16;
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 data;
|
||||||
|
|
||||||
|
} code;
|
||||||
|
|
||||||
ARMv7InstructionSet ISET;
|
ARMv7InstructionSet ISET;
|
||||||
|
|
||||||
union
|
union
|
||||||
|
@ -119,6 +137,13 @@ public:
|
||||||
return PC;
|
return PC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_code(const u32 address)
|
||||||
|
{
|
||||||
|
code.code0 = vm::psv::read16(address & ~1);
|
||||||
|
code.code1 = vm::psv::read16(address + 2 & ~1);
|
||||||
|
m_arg = address & 0x1 ? code.code1 << 16 | code.code0 : code.data;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void InitRegs();
|
virtual void InitRegs();
|
||||||
virtual void InitStack();
|
virtual void InitStack();
|
||||||
|
|
|
@ -112,7 +112,8 @@ void InterpreterDisAsmFrame::UpdateUnitList()
|
||||||
|
|
||||||
for(uint i=0; i<thrs.size(); ++i)
|
for(uint i=0; i<thrs.size(); ++i)
|
||||||
{
|
{
|
||||||
m_choice_units->Append(thrs[i]->GetFName(), thrs[i]);
|
if (thrs[i]->GetType() != CPU_THREAD_ARMv7)
|
||||||
|
m_choice_units->Append(thrs[i]->GetFName(), thrs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_choice_units->Thaw();
|
m_choice_units->Thaw();
|
||||||
|
@ -150,9 +151,9 @@ void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
|
||||||
|
|
||||||
case CPU_THREAD_ARMv7:
|
case CPU_THREAD_ARMv7:
|
||||||
{
|
{
|
||||||
ARMv7DisAsm& dis_asm = *new ARMv7DisAsm(CPUDisAsm_InterpreterMode);
|
//ARMv7DisAsm& dis_asm = *new ARMv7DisAsm(CPUDisAsm_InterpreterMode);
|
||||||
decoder = new ARMv7Decoder(dis_asm);
|
//decoder = new ARMv7Decoder(dis_asm);
|
||||||
disasm = &dis_asm;
|
//disasm = &dis_asm;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,14 +10,19 @@ namespace loader
|
||||||
{
|
{
|
||||||
for (auto i : m_handlers)
|
for (auto i : m_handlers)
|
||||||
{
|
{
|
||||||
if (i->init(stream) == handler::ok)
|
i->set_status(i->init(stream));
|
||||||
|
if (i->get_status() == handler::ok)
|
||||||
{
|
{
|
||||||
if (i->load() == handler::ok)
|
i->set_status(i->load());
|
||||||
|
if (i->get_status() == handler::ok)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_ERROR(LOADER, "loader::load() failed: %s", i->get_error_code().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_ERROR(LOADER, "loader::init() failed: %s", i->get_error_code().c_str());
|
||||||
stream.Seek(i->get_stream_offset());
|
stream.Seek(i->get_stream_offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ enum Elf_Machine
|
||||||
MACHINE_MIPS = 0x08,
|
MACHINE_MIPS = 0x08,
|
||||||
MACHINE_PPC64 = 0x15,
|
MACHINE_PPC64 = 0x15,
|
||||||
MACHINE_SPU = 0x17,
|
MACHINE_SPU = 0x17,
|
||||||
MACHINE_ARM = 0x28,
|
MACHINE_ARM = 0x28
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ShdrType
|
enum ShdrType
|
||||||
|
@ -31,7 +31,7 @@ enum ShdrType
|
||||||
SHT_NOBITS,
|
SHT_NOBITS,
|
||||||
SHT_REL,
|
SHT_REL,
|
||||||
SHT_SHLIB,
|
SHT_SHLIB,
|
||||||
SHT_DYNSYM,
|
SHT_DYNSYM
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ShdrFlag
|
enum ShdrFlag
|
||||||
|
@ -39,7 +39,7 @@ enum ShdrFlag
|
||||||
SHF_WRITE = 0x1,
|
SHF_WRITE = 0x1,
|
||||||
SHF_ALLOC = 0x2,
|
SHF_ALLOC = 0x2,
|
||||||
SHF_EXECINSTR = 0x4,
|
SHF_EXECINSTR = 0x4,
|
||||||
SHF_MASKPROC = 0xf0000000,
|
SHF_MASKPROC = 0xf0000000
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::string Ehdr_DataToString(const u8 data);
|
const std::string Ehdr_DataToString(const u8 data);
|
||||||
|
@ -117,7 +117,7 @@ namespace loader
|
||||||
broken_file = -3,
|
broken_file = -3,
|
||||||
loading_error = -4,
|
loading_error = -4,
|
||||||
bad_relocation_type = -5,
|
bad_relocation_type = -5,
|
||||||
ok = 0,
|
ok = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~handler() = default;
|
virtual ~handler() = default;
|
||||||
|
@ -128,6 +128,34 @@ namespace loader
|
||||||
{
|
{
|
||||||
return m_stream_offset;
|
return m_stream_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_status(const error_code& code)
|
||||||
|
{
|
||||||
|
m_status = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code get_status() const
|
||||||
|
{
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string get_error_code() const
|
||||||
|
{
|
||||||
|
switch (m_status)
|
||||||
|
{
|
||||||
|
case bad_version: return "Bad version";
|
||||||
|
case bad_file: return "Bad file";
|
||||||
|
case broken_file: return "Broken file";
|
||||||
|
case loading_error: return "Loading error";
|
||||||
|
case bad_relocation_type: return "Bad relocation type";
|
||||||
|
case ok: return "Ok";
|
||||||
|
|
||||||
|
default: return "Unknown error code";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
error_code m_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
class loader
|
class loader
|
||||||
|
|
Loading…
Reference in New Issue