Refactor mmu code

This commit is contained in:
rkx1209 2018-03-05 22:20:48 +09:00
parent a5d8832222
commit a60f814e0c
9 changed files with 68 additions and 79 deletions

View file

@ -8,6 +8,8 @@ ARMv8State arm_state;
void Init() {
Interpreter::create ();
cpu_engine = Interpreter::get_instance ();
PC = 0x0;
SP = 0x30000;
}
void RunLoop() {

View file

@ -150,14 +150,14 @@ static void ArithmeticLogic(unsigned int rd_idx, uint64_t arg1, uint64_t arg2, b
void IntprCallback::MoviI64(unsigned int reg_idx, uint64_t imm, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("MOV: %c[%u] = 0x%016lx\n", regc, reg_idx, imm);
debug_print ("MOV: %c[%u] = 0x%lx\n", regc, reg_idx, imm);
if (bit64) X(reg_idx) = imm;
else W(reg_idx) = imm;
}
void IntprCallback::DepositiI64(unsigned int reg_idx, unsigned int pos, uint64_t imm, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("MOVK: %c[%u] = 0x%016lx\n", regc, reg_idx, imm << pos);
debug_print ("MOVK: %c[%u] = 0x%lx\n", regc, reg_idx, imm << pos);
uint32_t mask = (1 << 16) - 1; //XXX: hard coded bit size: 16
if (bit64) {
X(reg_idx) = (X(reg_idx) & ~(mask << pos)) | (imm << pos);
@ -193,7 +193,7 @@ void IntprCallback::CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned
/* Add/Sub with Immediate value */
void IntprCallback::AddI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("Add: %c[%u] = %c[%u] + 0x%016lx (flag: %s)\n", regc, rd_idx, regc, rn_idx, imm, setflags? "update": "no");
debug_print ("Add: %c[%u] = %c[%u] + 0x%lx (flag: %s)\n", regc, rd_idx, regc, rn_idx, imm, setflags? "update": "no");
if (bit64)
ArithmeticLogic (rd_idx, X(rn_idx), imm, setflags, bit64, AL_TYPE_ADD);
else
@ -201,7 +201,7 @@ void IntprCallback::AddI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t im
}
void IntprCallback::SubI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("Sub: %c[%u] = %c[%u] - 0x%016lx (flag: %s)\n", regc, rd_idx, regc, rn_idx, imm, setflags? "update": "no");
debug_print ("Sub: %c[%u] = %c[%u] - 0x%lx (flag: %s)\n", regc, rd_idx, regc, rn_idx, imm, setflags? "update": "no");
if (bit64)
ArithmeticLogic (rd_idx, X(rn_idx), imm, setflags, bit64, AL_TYPE_SUB);
else
@ -268,7 +268,7 @@ void IntprCallback::SubcReg(unsigned int rd_idx, unsigned int rn_idx, unsigned i
/* AND/OR/EOR... with Immediate value */
void IntprCallback::AndI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool setflags, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("And: %c[%u] = %c[%u] & 0x%016lx (flag: %s)\n", regc, rd_idx, regc, rn_idx, wmask, setflags? "update": "no");
debug_print ("And: %c[%u] = %c[%u] & 0x%lx (flag: %s)\n", regc, rd_idx, regc, rn_idx, wmask, setflags? "update": "no");
if (bit64)
ArithmeticLogic (rd_idx, X(rn_idx), wmask, setflags, bit64, AL_TYPE_AND);
else
@ -277,7 +277,7 @@ void IntprCallback::AndI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wm
}
void IntprCallback::OrrI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("Or: %c[%u] = %c[%u] | 0x%016lx \n", regc, rd_idx, regc, rn_idx, wmask);
debug_print ("Or: %c[%u] = %c[%u] | 0x%lx \n", regc, rd_idx, regc, rn_idx, wmask);
if (bit64)
ArithmeticLogic (rd_idx, X(rn_idx), wmask, false, bit64, AL_TYPE_OR);
else
@ -285,7 +285,7 @@ void IntprCallback::OrrI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wm
}
void IntprCallback::EorI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("Eor: %c[%u] = %c[%u] ^ 0x%016lx \n", regc, rd_idx, regc, rn_idx, wmask);
debug_print ("Eor: %c[%u] = %c[%u] ^ 0x%lx \n", regc, rd_idx, regc, rn_idx, wmask);
if (bit64)
ArithmeticLogic (rd_idx, X(rn_idx), wmask, false, bit64, AL_TYPE_EOR);
else
@ -293,7 +293,7 @@ void IntprCallback::EorI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wm
}
void IntprCallback::ShiftI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int shift_type, unsigned int shift_amount, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("Shift: %c[%u] = %c[%u] %s 0x%016lx \n", regc, rd_idx, regc, rn_idx, OpStrs[shift_type], shift_amount);
debug_print ("Shift: %c[%u] = %c[%u] %s 0x%lx \n", regc, rd_idx, regc, rn_idx, OpStrs[shift_type], shift_amount);
if (bit64)
ArithmeticLogic (rd_idx, X(rn_idx), shift_amount, false, bit64, (OpType)shift_type);
else
@ -404,7 +404,7 @@ void IntprCallback::LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned
void IntprCallback::LoadRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size,
bool extend, bool post, bool writeback, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("Load(%d): %c[%u] <= [%c[%u], 0x%16lx]\n", size, regc, rd_idx, regc, base_idx, offset);
debug_print ("Load(%d): %c[%u] <= [%c[%u], 0x%lx]\n", size, regc, rd_idx, regc, base_idx, offset);
uint64_t addr;
if (bit64) {
if (post)
@ -450,7 +450,7 @@ void IntprCallback::StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigne
void IntprCallback::StoreRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size,
bool extend, bool post, bool writeback, bool bit64) {
char regc = bit64? 'X': 'W';
debug_print ("Store(%d): %c[%u] => [%c[%u], 0x%16lx]\n", size, regc, rd_idx, regc, base_idx, offset);
debug_print ("Store(%d): %c[%u] => [%c[%u], 0x%lx]\n", size, regc, rd_idx, regc, base_idx, offset);
uint64_t addr;
if (bit64) {
if (post)
@ -583,7 +583,7 @@ void IntprCallback::CondCmpReg(unsigned int rn_idx, unsigned int rm_idx, unsigne
/* Go to Immediate address */
void IntprCallback::BranchI64(uint64_t imm) {
debug_print ("Goto: 0x%016lx\n", imm + 4);
debug_print ("Goto: 0x%lx\n", imm + 4);
PC = imm;
}

View file

@ -2,7 +2,7 @@
#include <sys/mman.h>
#include "Nsemu.hpp"
AddressSpace::AddressSpace (std::string _name, uint64_t addr, size_t _length, int _perm, uint8_t **out_pointer) {
RAMBlock::RAMBlock (std::string _name, uint64_t _addr, size_t _length, int _perm) {
int page = getpagesize ();
name = _name;
length = _length;
@ -10,38 +10,37 @@ AddressSpace::AddressSpace (std::string _name, uint64_t addr, size_t _length, in
if (addr & (page - 1)) {
addr = addr & ~(page - 1);
}
if ((data = mmap ((void *) addr, length, perm, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) {
ns_abort ("Failed to mmap %s\n", name.c_str ());
}
debug_print ("mmap %s: %p\n", name.c_str (), data);
addr = (uint64_t) data;
if (out_pointer) {
*out_pointer = (uint8_t *) data;
}
addr = _addr;
}
namespace Memory
{
uint8_t *pRAM; // XXX: Replace raw pointer to View wrapper.
static AddressSpace mem_map[] =
static RAMBlock mem_map[] =
{
AddressSpace (".text", (uint64_t) nullptr, 0x100000, PROT_READ | PROT_WRITE | PROT_EXEC, &pRAM),
AddressSpace (".rdata", (uint64_t) nullptr, 0x100000, PROT_READ | PROT_WRITE, NULL),
AddressSpace (".data", (uint64_t) nullptr, 0x100000, PROT_READ | PROT_WRITE, NULL),
RAMBlock (".text", 0x0, 0x10000, PROT_READ | PROT_WRITE | PROT_EXEC),
RAMBlock (".rdata", 0x10000, 0x10000, PROT_READ | PROT_WRITE),
RAMBlock (".data", 0x20000, 0x10000, PROT_READ | PROT_WRITE),
RAMBlock ("[stack]", 0x30000, 0x10000, PROT_READ | PROT_WRITE),
};
void InitMemmap(Nsemu *nsemu) {
int num = sizeof(mem_map) / sizeof(AddressSpace);
void *data;
if ((data = mmap (nullptr, 0x100000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) {
ns_abort ("Failed to allocate host memory\n");
}
pRAM = (uint8_t *) data;
int num = sizeof(mem_map) / sizeof(RAMBlock);
for (int n = 0; n < num; n++) {
std::string sec_name = mem_map[n].name;
nsemu->as[sec_name] = mem_map[n];
nsemu->rams[sec_name] = mem_map[n];
}
}
AddressSpace *FindAddressSpace(Nsemu *nsemu, uint64_t addr, size_t len) {
AddressSpace *as;
std::map<std::string, AddressSpace>::iterator it = nsemu->as.begin ();
for (; it != nsemu->as.end (); it++) {
RAMBlock *FindRAMBlock(Nsemu *nsemu, uint64_t addr, size_t len) {
RAMBlock *as;
std::map<std::string, RAMBlock>::iterator it = nsemu->rams.begin ();
for (; it != nsemu->rams.end (); it++) {
as = &it->second;
if (as->addr <= addr && addr + len <= as->addr + as->length) {
return as;
@ -50,9 +49,8 @@ AddressSpace *FindAddressSpace(Nsemu *nsemu, uint64_t addr, size_t len) {
return nullptr;
}
static bool _CopyMemEmu(AddressSpace *as, void *data, uint64_t hva, size_t len, bool load) {
uint64_t off = hva - as->addr;
void *emu_mem = (uint8_t *) as->data + off;
static bool _CopyMemEmu(void *data, uint64_t gpa, size_t len, bool load) {
void *emu_mem = (void *)&pRAM[gpa];
if (load) {
memcpy (emu_mem, data, len);
} else {
@ -61,42 +59,34 @@ static bool _CopyMemEmu(AddressSpace *as, void *data, uint64_t hva, size_t len,
return true;
}
bool CopytoEmu(Nsemu *nsemu, void *data, uint64_t hva, size_t len) {
AddressSpace *as;
if (!(as = FindAddressSpace (nsemu, hva, len))) {
return false;
}
return _CopyMemEmu (as, data, hva, len, true);
bool CopytoEmu(Nsemu *nsemu, void *data, uint64_t gpa, size_t len) {
return _CopyMemEmu (data, gpa, len, true);
}
bool CopytoEmuByName(Nsemu *nsemu, void *data, std::string name, size_t len) {
if (nsemu->as.find (name) == nsemu->as.end ()) {
if (nsemu->rams.find (name) == nsemu->rams.end ()) {
return false;
}
AddressSpace *as = &nsemu->as[name];
RAMBlock *as = &nsemu->rams[name];
if (len > as->length) {
return false;
}
return _CopyMemEmu (as, data, as->addr, len, true);
return _CopyMemEmu (data, as->addr, len, true);
}
bool CopyfromEmu(Nsemu *nsemu, void *data, uint64_t hva, size_t len) {
AddressSpace *as;
if (!(as = FindAddressSpace (nsemu, hva, len))) {
return false;
}
return _CopyMemEmu (as, data, hva, len, false);
bool CopyfromEmu(Nsemu *nsemu, void *data, uint64_t gpa, size_t len) {
return _CopyMemEmu (data, gpa, len, false);
}
bool CopyfromEmuByName(Nsemu *nsemu, void *data, std::string name, size_t len) {
if (nsemu->as.find (name) == nsemu->as.end ()) {
if (nsemu->rams.find (name) == nsemu->rams.end ()) {
return false;
}
AddressSpace *as = &nsemu->as[name];
RAMBlock *as = &nsemu->rams[name];
if (len > as->length) {
return false;
}
return _CopyMemEmu (as, data, as->addr, len, false);
return _CopyMemEmu (data, as->addr, len, false);
}
}

View file

@ -24,7 +24,7 @@ char *decompress(ifstream &fp, uint32_t offset, uint32_t csize, uint32_t usize)
return obuf;
}
int Nso::load(Nsemu *nsemu, uint64_t base) {
int Nso::load(Nsemu *nsemu) {
NsoHeader hdr;
fp.read ((char *) &hdr, sizeof(NsoHeader));
if (hdr.magic != byte_swap32_str ("NSO0")) {
@ -64,6 +64,6 @@ int Nso::load(Nsemu *nsemu, uint64_t base) {
return size;
}
int Nro::load(Nsemu *nsemu, uint64_t base) {
int Nro::load(Nsemu *nsemu) {
return 0;
}

View file

@ -5,9 +5,9 @@
Nsemu *Nsemu::inst = nullptr;
static std::thread cpu_thread;
static void load_nso(Nsemu *nsemu, string path, uint64_t addr) {
static void LoadNso(Nsemu *nsemu, string path) {
Nso nso (path);
nso.load (nsemu, addr);
nso.load (nsemu);
}
static void CpuThread() {
@ -19,7 +19,7 @@ static void CpuThread() {
bool Nsemu::BootUp(const std::string& path) {
debug_print ("Booting... %s\n", path.c_str ());
Memory::InitMemmap (this);
load_nso (this, path, 0x1000);
LoadNso (this, path);
cpu_thread = std::thread (CpuThread);
/* Run cpu */
cpu_thread.join ();

View file

@ -21,23 +21,24 @@ extern ARMv8State arm_state;
#define GPR_LR 30
#define GPR_SP 31
#define GPR_ZERO 31
#define PC_IDX 32
#define PC_IDX 32 // XXX: bit tricky
#define GPR_DUMMY 33
#define LR ARMv8::arm_state.gpr[GPR_LR]
#define SP ARMv8::arm_state.gpr[GPR_SP]
#define ZERO ARMv8::arm_state.gpr[GPR_ZERO]
#define PC ARMv8::arm_state.gpr[PC_IDX].x // XXX: bit tricky
#define GPR(r) ARMv8::arm_state.gpr[r]
#define X(r) GPR(r).x
#define W(r) GPR(r).w[1]
#define LR X(GPR_LR)
#define SP X(GPR_SP)
#define ZERO X(GPR_ZERO)
#define PC X(PC_IDX)
#define NZCV ARMv8::arm_state.nzcv
#define N_MASK 0x80000000
#define Z_MASK 0x40000000
#define C_MASK 0x20000000
#define V_MASK 0x10000000
#define GPR(r) ARMv8::arm_state.gpr[r]
#define X(r) GPR(r).x
#define W(r) GPR(r).w[1]
void Init();
void RunLoop();

View file

@ -6,21 +6,17 @@
#include <string>
#include <sys/types.h>
class AddressSpace {
class RAMBlock {
public:
std::string name;
size_t length;
int perm;
void *data;
uint64_t addr;
AddressSpace() {}
AddressSpace(std::string _name, uint64_t addr, size_t _length, int _perm, uint8_t **out_pointer);
bool operator<(const AddressSpace &as) {
uint64_t addr; //gpa (guest physical address)
RAMBlock() {}
RAMBlock(std::string _name, uint64_t _addr, size_t _length, int _perm);
bool operator<(const RAMBlock &as) {
return name < as.name;
}
void *GetPointer() {
return data;
}
};
class Nsemu;
@ -28,7 +24,7 @@ namespace Memory
{
extern uint8_t *pRAM; // XXX: Replace raw pointer to View wrapper.
void InitMemmap(Nsemu *nsemu);
AddressSpace *FindAddressSpace(Nsemu *nsemu, uint64_t addr, size_t len);
RAMBlock *FindRAMBlock(Nsemu *nsemu, uint64_t addr, size_t len);
bool CopytoEmu(Nsemu *nsemu, void *data, uint64_t addr, size_t len);
bool CopytoEmuByName(Nsemu *nsemu, void *data, std::string name, size_t len);
bool CopyfromEmu(Nsemu *nsemu, void *data, uint64_t addr, size_t len);

View file

@ -6,7 +6,7 @@ class NintendoObject {
public:
NintendoObject(std::string path);
~NintendoObject();
virtual int load(Nsemu *nsemu, uint64_t base) = 0;
virtual int load(Nsemu *nsemu) = 0;
protected:
std::ifstream fp;
uint32_t length;
@ -15,7 +15,7 @@ uint32_t length;
class Nso : NintendoObject {
public:
Nso(std::string path) : NintendoObject (path) {}
int load(Nsemu *nsemu, uint64_t base);
int load(Nsemu *nsemu);
};
typedef struct {
@ -29,7 +29,7 @@ typedef struct {
class Nro : NintendoObject {
public:
Nro(std::string path) : NintendoObject (path) {}
int load(Nsemu *nsemu, uint64_t base);
int load(Nsemu *nsemu);
};
#endif

View file

@ -31,7 +31,7 @@ Nsemu() = default;
static Nsemu *inst;
public:
std::map<std::string, AddressSpace> as;
std::map<std::string, RAMBlock> rams;
public:
Nsemu(const Nsemu&) = delete;
Nsemu& operator=(const Nsemu&) = delete;