mirror of
https://github.com/RKX1209/nsemu.git
synced 2024-06-23 14:43:16 -04:00
Fixed some bugs of CPU emulation
This commit is contained in:
parent
7907d0dd1a
commit
99a9efa369
|
@ -40,10 +40,7 @@ void DumpJson(FILE *fp) {
|
|||
file_print (fp, "%lu : {\n", counter++);
|
||||
int r;
|
||||
for (r = 0; r < GPR_DUMMY; r++) {
|
||||
if (r == GPR_LR && X(r))
|
||||
file_print (fp, "\"X%d\" : \"0x%016lx\",\n", r, X(r) + 4);
|
||||
else
|
||||
file_print (fp, "\"X%d\" : \"0x%016lx\",\n", r, X(r));
|
||||
file_print (fp, "\"X%d\" : \"0x%016lx\",\n", r, X(r));
|
||||
}
|
||||
file_print (fp, "\"X%d\" : \"0x%016x\"\n", r, NZCV);
|
||||
file_print (fp, "},\n");
|
||||
|
|
|
@ -188,16 +188,19 @@ static void DisasBitfield(uint32_t insn, DisasCallback *cb) {
|
|||
}
|
||||
|
||||
/* Recognize simple(r) extractions. */
|
||||
cb->MovReg (GPR_DUMMY, rn, true);
|
||||
if (si >= ri) {
|
||||
/* Xd<0:r> = Xn<(s-r+1):s> */
|
||||
len = (si - ri) + 1;
|
||||
if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
|
||||
cb->SExtractI64(rd, rn, ri, len, is_64bit);
|
||||
cb->SExtractI64(rd, GPR_DUMMY, ri, len, is_64bit);
|
||||
return;
|
||||
} else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */
|
||||
cb->UExtractI64(rd, rn, ri, len, is_64bit);
|
||||
cb->UExtractI64(rd, GPR_DUMMY, ri, len, is_64bit);
|
||||
return;
|
||||
}
|
||||
/* opc == 1, BXFIL fall through to deposit */
|
||||
cb->UExtractI64(GPR_DUMMY, GPR_DUMMY, ri, len, is_64bit);
|
||||
pos = 0;
|
||||
} else {
|
||||
/* Handle the ri > si case with a deposit
|
||||
|
@ -211,17 +214,17 @@ static void DisasBitfield(uint32_t insn, DisasCallback *cb) {
|
|||
/* SBFM: sign extend the destination field from len to fill
|
||||
the balance of the word. Let the deposit below insert all
|
||||
of those sign bits. */
|
||||
cb->SExtractI64(rd, rn, 0, len, is_64bit);
|
||||
cb->SExtractI64(GPR_DUMMY, GPR_DUMMY, 0, len, is_64bit);
|
||||
len = ri;
|
||||
}
|
||||
|
||||
if (opc == 1) { /* BFM, BXFIL */
|
||||
cb->DepositReg (rd, rd, pos, len, is_64bit);
|
||||
cb->DepositReg (rd, GPR_DUMMY, pos, len, is_64bit);
|
||||
} else {
|
||||
/* SBFM or UBFM: We start with zero, and we haven't modified
|
||||
any bits outside bitsize, therefore the zero-extension
|
||||
below is unneeded. */
|
||||
cb->DepositZeroReg (rd, rd, pos, len, is_64bit);
|
||||
cb->DepositZeroReg (rd, GPR_DUMMY, pos, len, is_64bit);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -280,14 +283,14 @@ static void DisasDataProcImm(uint32_t insn, DisasCallback *cb) {
|
|||
}
|
||||
|
||||
static void DisasUncondBrImm(uint32_t insn, DisasCallback *cb) {
|
||||
uint64_t addr = PC + sextract32(insn, 0, 26) * 4 - 4;
|
||||
cb->AddI64(GPR_DUMMY, PC_IDX, sextract32(insn, 0, 26) * 4, false, true);
|
||||
if (insn & (1U << 31)) {
|
||||
/* BL Branch with link */
|
||||
cb->MoviI64(GPR_LR, PC, true);
|
||||
cb->AddI64(GPR_LR, PC_IDX, 4, false, true);
|
||||
}
|
||||
|
||||
/* B Branch / BL Branch with link */
|
||||
cb->BranchI64(addr);
|
||||
cb->SetPCReg(GPR_DUMMY);
|
||||
}
|
||||
|
||||
static void DisasCompBrImm(uint32_t insn, DisasCallback *cb) {
|
||||
|
@ -337,7 +340,7 @@ static void DisasUncondBrReg(uint32_t insn, DisasCallback *cb) {
|
|||
|
||||
switch (opc) {
|
||||
case 1: /* BLR */
|
||||
cb->MovReg(GPR_LR, PC_IDX, true);
|
||||
cb->AddI64(GPR_LR, PC_IDX, 4, false, true);
|
||||
case 0: /* BR */
|
||||
case 2: /* RET */
|
||||
cb->SetPCReg (rn);
|
||||
|
@ -450,38 +453,41 @@ static void DisasLogicReg(uint32_t insn, DisasCallback *cb) {
|
|||
*/
|
||||
if (invert) {
|
||||
cb->NotReg (rd, rm, sf);
|
||||
} else {
|
||||
cb->MovReg (rd, rm, sf);
|
||||
}
|
||||
cb->MovReg (rd, rm, sf);
|
||||
return;
|
||||
}
|
||||
cb->MovReg (GPR_DUMMY, rm, true);
|
||||
if (shift_amount) {
|
||||
cb->ShiftI64 (rm, rm, shift_type, shift_amount, sf);
|
||||
cb->ShiftI64 (GPR_DUMMY, rm, shift_type, shift_amount, sf);
|
||||
}
|
||||
switch (opc | (invert << 2)) {
|
||||
case 0: /* AND */
|
||||
cb->AndReg (rd, rn, rm, false, sf);
|
||||
cb->AndReg (rd, rn, GPR_DUMMY, false, sf);
|
||||
break;
|
||||
case 3: /* ANDS */
|
||||
cb->AndReg (rd, rn, rm, true, sf);
|
||||
cb->AndReg (rd, rn, GPR_DUMMY, true, sf);
|
||||
break;
|
||||
case 1: /* ORR */
|
||||
cb->OrrReg (rd, rn, rm, sf);
|
||||
cb->OrrReg (rd, rn, GPR_DUMMY, sf);
|
||||
break;
|
||||
case 2: /* EOR */
|
||||
cb->EorReg (rd, rn, rm, sf);
|
||||
cb->EorReg (rd, rn, GPR_DUMMY, sf);
|
||||
break;
|
||||
case 4: /* BIC */
|
||||
cb->BicReg (rd, rn, rm, false, sf);
|
||||
cb->BicReg (rd, rn, GPR_DUMMY, false, sf);
|
||||
break;
|
||||
case 7: /* BICS */
|
||||
cb->BicReg (rd, rn, rm, true, sf);
|
||||
cb->BicReg (rd, rn, GPR_DUMMY, true, sf);
|
||||
break;
|
||||
case 5: /* ORN */
|
||||
cb->NotReg (rm, rm, sf);
|
||||
cb->OrrReg (rd, rn, rm, sf);
|
||||
cb->NotReg (GPR_DUMMY, GPR_DUMMY, sf);
|
||||
cb->OrrReg (rd, rn, GPR_DUMMY, sf);
|
||||
break;
|
||||
case 6: /* EON */
|
||||
cb->NotReg (rm, rm, sf);
|
||||
cb->EorReg (rd, rn, rm, sf);
|
||||
cb->NotReg (GPR_DUMMY, GPR_DUMMY, sf);
|
||||
cb->EorReg (rd, rn, GPR_DUMMY, sf);
|
||||
break;
|
||||
default:
|
||||
ns_abort ("Invalid Logical(Reg) opcode: %u\n", opc);
|
||||
|
@ -644,11 +650,14 @@ static void DisasCondSel(uint32_t insn, DisasCallback *cb) {
|
|||
* CSETM (CSINV <Wd>, WZR, WZR, invert(<cond>)) */
|
||||
cond = cond ^ 1; // i.e. invert(<cond>)
|
||||
}
|
||||
if (else_inv)
|
||||
cb->NotReg (rm, rm, sf);
|
||||
if (else_inc)
|
||||
cb->AddI64 (rm, rm, 1, false, sf);
|
||||
cb->CondMovReg (cond, rd, rn, rm);
|
||||
cb->MovReg (GPR_DUMMY, rm, true);
|
||||
if (else_inv) {
|
||||
cb->NotReg (GPR_DUMMY, GPR_DUMMY, sf);
|
||||
}
|
||||
if (else_inc) {
|
||||
cb->AddI64 (GPR_DUMMY, GPR_DUMMY, 1, false, sf);
|
||||
}
|
||||
cb->CondMovReg (cond, rd, rn, GPR_DUMMY, sf);
|
||||
}
|
||||
|
||||
static void DisasDataProc1src(uint32_t insn, DisasCallback *cb) {
|
||||
|
|
|
@ -17,15 +17,12 @@ int Interpreter::SingleStep() {
|
|||
void Interpreter::Run() {
|
||||
debug_print ("Running with Interpreter\n");
|
||||
static uint64_t counter = 0;
|
||||
uint64_t estimate = 3404800, mx = 10000;
|
||||
uint64_t estimate = 3413800, mx = 10000;
|
||||
while (Cpu::GetState () == Cpu::State::Running) {
|
||||
char c;
|
||||
//scanf("%c", &c);
|
||||
//if (counter >= estimate) {
|
||||
if (counter >= estimate){
|
||||
Cpu::DumpMachine ();
|
||||
}
|
||||
if (counter > estimate + mx)
|
||||
if (counter >= estimate + mx)
|
||||
break;
|
||||
SingleStep ();
|
||||
counter++;
|
||||
|
@ -251,7 +248,7 @@ void IntprCallback::DepositReg(unsigned int rd_idx, unsigned int rn_idx, unsigne
|
|||
|
||||
void IntprCallback::DepositZeroI64(unsigned int rd_idx, uint64_t imm, unsigned int pos, unsigned int len, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
//debug_print ("MOVK: %c[%u] = 0x%lx\n", regc, rd_idx, imm << pos);
|
||||
debug_print ("DepZ: %c[%u](pos:%u, len:%u) = 0x%lx\n", regc, rd_idx, pos, len, imm);
|
||||
X(rd_idx) = (imm & ((1ULL << len) - 1)) << pos;
|
||||
}
|
||||
|
||||
|
@ -275,15 +272,19 @@ void IntprCallback::MovReg(unsigned int rd_idx, unsigned int rn_idx, bool bit64)
|
|||
}
|
||||
|
||||
/* Conditional mov between registers */
|
||||
void IntprCallback::CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned int rn_idx, bool bit64) {
|
||||
void IntprCallback::CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("MOV: %c[%u] = %c[%u]\n", regc, rd_idx, regc, rn_idx);
|
||||
debug_print ("MOV: %c[%u] = 0: %c[%u], 1: %c[%u]\n", regc, rd_idx, regc, rm_idx, regc, rn_idx);
|
||||
if (bit64) {
|
||||
if (CondHold(cond))
|
||||
X(rd_idx) = X(rn_idx);
|
||||
else
|
||||
X(rd_idx) = X(rm_idx);
|
||||
} else {
|
||||
if (CondHold(cond))
|
||||
X(rd_idx) = W(rn_idx);
|
||||
else
|
||||
X(rd_idx) = W(rm_idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,21 +625,29 @@ void IntprCallback::SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsign
|
|||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("SExtract: %c[%u] <= SEXT[%c[%u]: %u, %u]\n", regc, rd_idx, regc, rn_idx, pos, len);
|
||||
if (pos + len == 64) {
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_ASR, 64 - len, bit64);
|
||||
return;
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_ASR, 64 - len, true);
|
||||
goto fin;
|
||||
}
|
||||
ShiftI64 (GPR_DUMMY, rn_idx, AL_TYPE_LSL, 64 - len - pos, bit64);
|
||||
ShiftI64 (GPR_DUMMY, rn_idx, AL_TYPE_LSL, 64 - len - pos, true);
|
||||
ShiftI64 (rd_idx, GPR_DUMMY, AL_TYPE_ASR, 64 - len, true);
|
||||
fin:
|
||||
if (!bit64) {
|
||||
X(rd_idx) = (int32_t) (X(rd_idx) & 0xffffffff);
|
||||
}
|
||||
}
|
||||
void IntprCallback::UExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("UExtract: %c[%u] <= SEXT[%c[%u]: %u, %u]\n", regc, rd_idx, regc, rn_idx, pos, len);
|
||||
if (pos + len == 64) {
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_LSR, 64 - len, bit64);
|
||||
return;
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_LSR, 64 - len, true);
|
||||
goto fin;
|
||||
}
|
||||
ShiftI64 (GPR_DUMMY, rn_idx, AL_TYPE_LSL, 64 - len - pos, bit64);
|
||||
ShiftI64 (GPR_DUMMY, rn_idx, AL_TYPE_LSL, 64 - len - pos, true);
|
||||
ShiftI64 (rd_idx, GPR_DUMMY, AL_TYPE_LSR, 64 - len, true);
|
||||
fin:
|
||||
if (!bit64) {
|
||||
X(rd_idx) = X(rd_idx) & 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reverse bit order */
|
||||
|
@ -767,12 +776,11 @@ void IntprCallback::BranchFlag(unsigned int cond, uint64_t addr) {
|
|||
/* Set PC with reg */
|
||||
void IntprCallback::SetPCReg(unsigned int rt_idx) {
|
||||
PC = X(rt_idx) - 4;
|
||||
ns_print ("Goto: 0x%lx\n", PC);
|
||||
ns_print ("Goto: 0x%lx\n", PC + 4);
|
||||
}
|
||||
|
||||
/* Super Visor Call */
|
||||
void IntprCallback::SVC(unsigned int svc_num) {
|
||||
//debug_print ("SVC: %u\n", svc_num);
|
||||
ns_print ("SVC: 0x%02x\n", svc_num);
|
||||
if (SVC::svc_handlers[svc_num])
|
||||
SVC::svc_handlers[svc_num]();
|
||||
|
|
|
@ -16,7 +16,7 @@ virtual void DepositZeroReg(unsigned int rd_idx, unsigned int rn_idx, unsigned i
|
|||
virtual void MovReg(unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0;
|
||||
|
||||
/* Conditional mov between registers */
|
||||
virtual void CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0;
|
||||
virtual void CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool bit64) = 0;
|
||||
|
||||
/* Add/Sub with Immediate value */
|
||||
virtual void AddI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64) = 0;
|
||||
|
|
|
@ -16,7 +16,7 @@ void DepositZeroReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos,
|
|||
void MovReg(unsigned int rd_idx, unsigned int rn_idx, bool bit64);
|
||||
|
||||
/* Conditional mov between registers */
|
||||
void CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned int rn_idx, bool bit64);
|
||||
void CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool bit64);
|
||||
|
||||
/* Add/Sub with Immediate value */
|
||||
void AddI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64);
|
||||
|
|
Loading…
Reference in a new issue