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

View File

@ -1,35 +1,48 @@
#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
{
ARMv7Opcodes& m_op;
u8 m_last_instr_size;
ARMv7Thread& m_thr;
public:
ARMv7Decoder(ARMv7Opcodes& op) : m_op(op)
ARMv7Decoder(ARMv7Thread& thr) : m_thr(thr)
{
}
virtual u8 DecodeMemory(const u32 address)
{
const u32 code0 = vm::psv::read16(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;
m_thr.update_code(address & ~1);
// 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)
{
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;
}
}
m_op.UNK(data);
return address & 1 ? 4 : 2;
ARMv7_instrs::UNK(&m_thr);
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;
}
};
};

View File

@ -12,10 +12,9 @@ static const char* g_arm_cond_name[16] =
class ARMv7DisAsm
: public CPUDisAsm
, public ARMv7Opcodes
{
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

View File

@ -10,7 +10,11 @@
#include "ARMv7DisAsm.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 2:
m_dec = new ARMv7Decoder(*new ARMv7Interpreter(*this));
m_dec = new ARMv7Decoder(*this);
break;
}
}

View File

@ -1,17 +1,23 @@
#pragma once
#include "Emu/CPU/CPUThread.h"
#include "Emu/Memory/Memory.h"
enum ARMv7InstructionSet
{
ARM,
Thumb,
Jazelle,
ThumbEE,
ThumbEE
};
class ARMv7Thread : public CPUThread
{
public:
u32 m_arg;
u8 m_last_instr_size;
const char* m_last_instr_name;
ARMv7Thread();
union
@ -61,6 +67,18 @@ public:
} IPSR;
union
{
struct
{
u32 code1 : 16;
u32 code0 : 16;
};
u32 data;
} code;
ARMv7InstructionSet ISET;
union
@ -119,6 +137,13 @@ public:
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:
virtual void InitRegs();
virtual void InitStack();

View File

@ -112,7 +112,8 @@ void InterpreterDisAsmFrame::UpdateUnitList()
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();
@ -150,9 +151,9 @@ void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
case CPU_THREAD_ARMv7:
{
ARMv7DisAsm& dis_asm = *new ARMv7DisAsm(CPUDisAsm_InterpreterMode);
decoder = new ARMv7Decoder(dis_asm);
disasm = &dis_asm;
//ARMv7DisAsm& dis_asm = *new ARMv7DisAsm(CPUDisAsm_InterpreterMode);
//decoder = new ARMv7Decoder(dis_asm);
//disasm = &dis_asm;
}
break;
}

View File

@ -10,14 +10,19 @@ namespace loader
{
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;
}
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());
}

View File

@ -15,7 +15,7 @@ enum Elf_Machine
MACHINE_MIPS = 0x08,
MACHINE_PPC64 = 0x15,
MACHINE_SPU = 0x17,
MACHINE_ARM = 0x28,
MACHINE_ARM = 0x28
};
enum ShdrType
@ -31,7 +31,7 @@ enum ShdrType
SHT_NOBITS,
SHT_REL,
SHT_SHLIB,
SHT_DYNSYM,
SHT_DYNSYM
};
enum ShdrFlag
@ -39,7 +39,7 @@ enum ShdrFlag
SHF_WRITE = 0x1,
SHF_ALLOC = 0x2,
SHF_EXECINSTR = 0x4,
SHF_MASKPROC = 0xf0000000,
SHF_MASKPROC = 0xf0000000
};
const std::string Ehdr_DataToString(const u8 data);
@ -117,7 +117,7 @@ namespace loader
broken_file = -3,
loading_error = -4,
bad_relocation_type = -5,
ok = 0,
ok = 0
};
virtual ~handler() = default;
@ -128,6 +128,34 @@ namespace loader
{
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