Fixed some bugs of CPU emulation

This commit is contained in:
rkx1209 2018-03-19 03:46:17 +09:00
parent 7907d0dd1a
commit 99a9efa369
5 changed files with 62 additions and 48 deletions

View file

@ -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");

View file

@ -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) {

View file

@ -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]();

View file

@ -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;

View file

@ -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);