mirror of
https://github.com/RKX1209/nsemu.git
synced 2024-06-23 06:32:39 -04:00
Refactor mmu code
This commit is contained in:
parent
a5d8832222
commit
a60f814e0c
|
@ -8,6 +8,8 @@ ARMv8State arm_state;
|
|||
void Init() {
|
||||
Interpreter::create ();
|
||||
cpu_engine = Interpreter::get_instance ();
|
||||
PC = 0x0;
|
||||
SP = 0x30000;
|
||||
}
|
||||
|
||||
void RunLoop() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
70
Memory.cpp
70
Memory.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue