mirror of
https://github.com/RKX1209/nsemu.git
synced 2024-06-23 14:43:16 -04:00
Fixed some bugs of Interpreter
This commit is contained in:
parent
2507c00b96
commit
c1ec38a76c
|
@ -35,16 +35,14 @@ void Dump() {
|
|||
static uint64_t counter;
|
||||
void DumpJson(FILE *fp) {
|
||||
file_print (fp, "%lu : {\n", counter++);
|
||||
for (int r = 0; r <= GPR_DUMMY; r++) {
|
||||
int r;
|
||||
for (r = 0; r < GPR_DUMMY; r++) {
|
||||
if (r == GPR_LR && X(r))
|
||||
file_print (fp, "\"X%d\" : \"0x%016lx\"", r, X(r) + 4);
|
||||
file_print (fp, "\"X%d\" : \"0x%016lx\",\n", r, X(r) + 4);
|
||||
else
|
||||
file_print (fp, "\"X%d\" : \"0x%016lx\"", r, X(r));
|
||||
if (r == GPR_DUMMY)
|
||||
file_print (fp, "\n");
|
||||
else
|
||||
file_print (fp, ",\n");
|
||||
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");
|
||||
}
|
||||
|
||||
|
|
|
@ -292,8 +292,9 @@ static void DisasTestBrImm(uint32_t insn, DisasCallback *cb) {
|
|||
unsigned int op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
|
||||
unsigned int addr = PC + sextract32(insn, 5, 14) * 4 - 4;
|
||||
uint64_t rt = extract32(insn, 0, 5);
|
||||
cb->AndI64(rt, rt, (1ULL << bit_pos), false, true);
|
||||
cb->BranchCondiI64 (op ? CondType_NE : CondType_EQ, rt, 0, addr, true);
|
||||
/* XXX: Dummy register is used as temporaly register. */
|
||||
cb->AndI64(GPR_DUMMY, rt, (1ULL << bit_pos), false, true);
|
||||
cb->BranchCondiI64 (op ? CondType_NE : CondType_EQ, GPR_DUMMY, 0, addr, true);
|
||||
}
|
||||
|
||||
static void DisasCondBrImm(uint32_t insn, DisasCallback *cb) {
|
||||
|
|
|
@ -59,19 +59,20 @@ static inline unsigned int HandleAsSP(unsigned r_idx) {
|
|||
static bool CondHold(unsigned int cond) {
|
||||
bool result = false;
|
||||
if (cond >> 1 == 0x0) {
|
||||
result = NZCV & Z_MASK;
|
||||
result = ((NZCV & Z_MASK) != 0);
|
||||
} else if (cond >> 1 == 0x1) {
|
||||
result = NZCV & C_MASK;
|
||||
result = ((NZCV & C_MASK) != 0);
|
||||
} else if (cond >> 1 == 0x2) {
|
||||
result = NZCV & N_MASK;
|
||||
result = ((NZCV & N_MASK) != 0);
|
||||
} else if (cond >> 1 == 0x3) {
|
||||
result = NZCV & V_MASK;
|
||||
result = ((NZCV & V_MASK) != 0);
|
||||
} else if (cond >> 1 == 0x4) {
|
||||
result = (NZCV & C_MASK) & !(NZCV & Z_MASK) ;
|
||||
result = ((NZCV & C_MASK) != 0) & ((NZCV & Z_MASK) == 0);
|
||||
//printf("nzcv = 0x%016lx, result=%d(%lx,%lx)\n", NZCV, result, (NZCV & C_MASK), !(NZCV & Z_MASK));
|
||||
} else if (cond >> 1 == 0x5) {
|
||||
result = (NZCV & N_MASK) == (NZCV & V_MASK);
|
||||
result = ((NZCV & N_MASK) != 0) == ((NZCV & V_MASK) != 0);
|
||||
} else if (cond >> 1 == 0x6) {
|
||||
result = ((NZCV & N_MASK) == (NZCV & V_MASK)) & !(NZCV & Z_MASK);
|
||||
result = (((NZCV & N_MASK) != 0) == ((NZCV & V_MASK) != 0)) & ((NZCV & Z_MASK) == 0);
|
||||
} else if (cond >> 1 == 0x7) {
|
||||
return true;
|
||||
} else {
|
||||
|
@ -83,10 +84,13 @@ static bool CondHold(unsigned int cond) {
|
|||
}
|
||||
|
||||
static void UpdateFlag(uint64_t res, uint64_t arg1, uint64_t arg2) {
|
||||
uint32_t nzcv;
|
||||
/* XXX: In ARMv8, nzcv flag is only updated when ADD/SUB/AND/BIC.
|
||||
* So following logic can work correctly(?)
|
||||
*/
|
||||
uint32_t nzcv = 0;
|
||||
if (res & (1ULL << 63)) nzcv |= N_MASK; // N
|
||||
if (res == 0ULL) nzcv |= Z_MASK; // Z
|
||||
if (((arg1 & arg2) + (arg1 ^ arg2) >> 1) >> 63) nzcv |= C_MASK; //C (half adder ((x & y) + ((x ^ y) >> 1)))
|
||||
if (((arg1 & arg2) + ((arg1 ^ arg2) >> 1)) >> 63) nzcv |= C_MASK; //C (half adder ((x & y) + ((x ^ y) >> 1)))
|
||||
if (!(arg1 ^ arg2 && (1ULL < 63)) & (arg2 ^ res && (1ULL < 63))) nzcv |= V_MASK; //V
|
||||
NZCV = nzcv;
|
||||
}
|
||||
|
@ -128,8 +132,8 @@ static int64_t Sdiv64(int64_t arg1, int64_t arg2) {
|
|||
static uint64_t ALCalc(uint64_t arg1, uint64_t arg2, OpType op) {
|
||||
if (op == AL_TYPE_ADD)
|
||||
return arg1 + arg2;
|
||||
if (op == AL_TYPE_SUB)
|
||||
return arg1 - arg2;
|
||||
// if (op == AL_TYPE_SUB)
|
||||
// return arg1 - arg2;
|
||||
if (op == AL_TYPE_AND)
|
||||
return arg1 & arg2;
|
||||
if (op == AL_TYPE_OR)
|
||||
|
@ -155,6 +159,10 @@ static uint64_t ALCalc(uint64_t arg1, uint64_t arg2, OpType op) {
|
|||
|
||||
static void ArithmeticLogic(unsigned int rd_idx, uint64_t arg1, uint64_t arg2, bool setflags, bool bit64, OpType op) {
|
||||
uint64_t result;
|
||||
if (op == AL_TYPE_SUB) {
|
||||
arg2 = -arg2;
|
||||
op = AL_TYPE_ADD;
|
||||
}
|
||||
result = ALCalc (arg1, arg2, op);
|
||||
if (setflags)
|
||||
UpdateFlag (result, arg1, arg2);
|
||||
|
@ -391,9 +399,13 @@ void IntprCallback::ExtendReg(unsigned int rd_idx, unsigned int rn_idx, unsigned
|
|||
/* Load/Store */
|
||||
static void _LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool extend) {
|
||||
debug_print ("Read from addr:0x%lx(%d)\n", addr, size);
|
||||
if (size < 3) {
|
||||
X(rd_idx) = ARMv8::ReadU32 (addr);
|
||||
} else if (size < 4){
|
||||
if (size == 0) {
|
||||
X(rd_idx) = ARMv8::ReadU8 (addr);
|
||||
} else if (size == 1) {
|
||||
X(rd_idx) = ARMv8::ReadU16 (addr);
|
||||
} else if (size == 2) {
|
||||
X(rd_idx) = ARMv8::ReadU32 (addr);
|
||||
} else if (size == 3){
|
||||
X(rd_idx) = ARMv8::ReadU64 (addr);
|
||||
} else {
|
||||
/* 128-bit Qt */
|
||||
|
@ -408,9 +420,13 @@ static void _LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool extend)
|
|||
|
||||
static void _StoreReg(unsigned int rd_idx, uint64_t addr, int size, bool extend) {
|
||||
debug_print ("Write to addr:0x%lx(%d)\n", addr, size);
|
||||
if (size < 3) {
|
||||
if (size == 0) {
|
||||
ARMv8::WriteU8 (addr, (uint8_t) (W(rd_idx) & 0xff));
|
||||
} else if (size == 1) {
|
||||
ARMv8::WriteU16 (addr, (uint16_t) (W(rd_idx) & 0xffff));
|
||||
} else if (size == 2) {
|
||||
ARMv8::WriteU32 (addr, W(rd_idx));
|
||||
} else if (size < 4) {
|
||||
} else if (size == 3) {
|
||||
ARMv8::WriteU64 (addr, X(rd_idx));
|
||||
} else {
|
||||
/* 128-bit Qt */
|
||||
|
@ -498,8 +514,8 @@ void IntprCallback::SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsign
|
|||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_ASR, 64 - len, bit64);
|
||||
return;
|
||||
}
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_LSL, 64 - len - pos, bit64);
|
||||
ShiftI64 (rd_idx, rd_idx, AL_TYPE_ASR, 64 - len, bit64);
|
||||
ShiftI64 (GPR_DUMMY, rn_idx, AL_TYPE_LSL, 64 - len - pos, bit64);
|
||||
ShiftI64 (rd_idx, GPR_DUMMY, AL_TYPE_ASR, 64 - len, true);
|
||||
}
|
||||
void IntprCallback::UExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
|
@ -508,8 +524,8 @@ void IntprCallback::UExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsign
|
|||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_LSR, 64 - len, bit64);
|
||||
return;
|
||||
}
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_LSL, 64 - len - pos, bit64);
|
||||
ShiftI64 (rd_idx, rd_idx, AL_TYPE_LSR, 64 - len, bit64);
|
||||
ShiftI64 (GPR_DUMMY, rn_idx, AL_TYPE_LSL, 64 - len - pos, bit64);
|
||||
ShiftI64 (rd_idx, GPR_DUMMY, AL_TYPE_LSR, 64 - len, true);
|
||||
}
|
||||
|
||||
/* Reverse bit order */
|
||||
|
|
|
@ -38,7 +38,7 @@ extern ARMv8State arm_state;
|
|||
#define GPR_ZERO 31
|
||||
#define GPR_SP 32
|
||||
#define PC_IDX 33 // XXX: bit tricky
|
||||
#define GPR_DUMMY PC_IDX
|
||||
#define GPR_DUMMY 34
|
||||
|
||||
#define GPR(r) ARMv8::arm_state.gpr[r]
|
||||
#define VREG(r) ARMv8::arm_state.vreg[r]
|
||||
|
@ -56,10 +56,10 @@ extern ARMv8State arm_state;
|
|||
#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 N_MASK 0x80000000UL
|
||||
#define Z_MASK 0x40000000UL
|
||||
#define C_MASK 0x20000000UL
|
||||
#define V_MASK 0x10000000UL
|
||||
|
||||
void Init();
|
||||
|
||||
|
|
Loading…
Reference in a new issue