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:
Oil
2014-12-01 23:20:27 +04:00
parent b736b8616b
commit c3696f7897
10 changed files with 3628 additions and 1805 deletions
+27 -14
View File
@@ -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;
} }
}; };
+1 -2
View File
@@ -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
+6 -2
View File
@@ -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;
} }
} }
+26 -1
View File
@@ -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();
+5 -4
View File
@@ -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;
} }
+7 -2
View File
@@ -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());
} }
+32 -4
View File
@@ -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