mirror of
https://github.com/RKX1209/nsemu.git
synced 2024-06-23 14:43:16 -04:00
Add support of extract operations
This commit is contained in:
parent
2f69bb9140
commit
fce85f7a91
|
@ -502,12 +502,12 @@ static void DisasAddSubExtReg(uint32_t insn, DisasCallback *cb) {
|
|||
UnallocatedOp (insn);
|
||||
return;
|
||||
}
|
||||
cb->ExtendReg (rm, rm, option, sf);
|
||||
cb->ShiftI64 (rm, rm, ShiftType_LSL, imm3, sf);
|
||||
cb->ExtendReg (GPR_DUMMY, rm, option, sf);
|
||||
cb->ShiftI64 (GPR_DUMMY, GPR_DUMMY, ShiftType_LSL, imm3, sf);
|
||||
if (sub_op) {
|
||||
cb->SubReg (rd, rn, rm, setflags, sf);
|
||||
cb->SubReg (rd, rn, GPR_DUMMY, setflags, sf);
|
||||
} else {
|
||||
cb->AddReg (rd, rn, rm, setflags, sf);
|
||||
cb->AddReg (rd, rn, GPR_DUMMY, setflags, sf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -743,7 +743,7 @@ static void DisasLdLit(uint32_t insn, DisasCallback *cb) {
|
|||
is_signed = extract32(opc, 1, 1);
|
||||
}
|
||||
cb->AddI64 (rt, PC_IDX, imm - 4, false, true);
|
||||
cb->LoadRegI64 (rt, rt, size, false);
|
||||
cb->LoadRegI64 (rt, rt, size, is_signed, false);
|
||||
}
|
||||
|
||||
static bool DisasLdstCompute64bit(unsigned int size, bool is_signed, unsigned int opc) {
|
||||
|
@ -792,15 +792,16 @@ static void DisasLdstRegRoffset(uint32_t insn, DisasCallback *cb,
|
|||
}
|
||||
is_store = (opc == 0);
|
||||
is_signed = extract32(opc, 1, 1);
|
||||
is_extended = (size < 3) && extract32(opc, 0, 1);
|
||||
//is_extended = (size < 3) && extract32(opc, 0, 1);
|
||||
is_extended = (size < 3); //TODO: treat other case, size = 0, 1(8bit-> or 16bit->)
|
||||
}
|
||||
bool sf = DisasLdstCompute64bit (size, is_signed, opc);
|
||||
cb->ExtendReg (rm, rm, opt, sf); //FIXME: When rm == GPR_ZERO, it should be handled as GPR_SP
|
||||
cb->ShiftReg (rm, rm, ShiftType_LSL, shift ? size : 0, sf);
|
||||
cb->ExtendReg (GPR_DUMMY, rm, opt, sf); //FIXME: When rm == GPR_ZERO, it should be handled as GPR_SP
|
||||
cb->ShiftI64 (GPR_DUMMY, GPR_DUMMY, ShiftType_LSL, shift ? size : 0, sf);
|
||||
if (is_store) {
|
||||
cb->StoreReg (rt, rn, rm, size, is_extended, false, sf);
|
||||
cb->StoreReg (rt, rn, GPR_DUMMY, size, is_signed, is_extended, false, sf);
|
||||
} else {
|
||||
cb->LoadReg (rt, rn, rm, size, is_extended, false, sf);
|
||||
cb->LoadReg (rt, rn, GPR_DUMMY, size, is_signed, is_extended, false, sf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -850,7 +851,8 @@ static void DisasLdstRegImm9(uint32_t insn, DisasCallback *cb,
|
|||
}
|
||||
is_store = (opc == 0);
|
||||
is_signed = extract32(opc, 1, 1);
|
||||
is_extended = (size < 3) && extract32(opc, 0, 1);
|
||||
//is_extended = (size < 3) && extract32(opc, 0, 1);
|
||||
is_extended = (size < 3); //TODO: treat other case, size = 0, 1(8bit-> or 16bit->)
|
||||
}
|
||||
bool sf = DisasLdstCompute64bit (size, is_signed, opc);
|
||||
switch (idx) {
|
||||
|
@ -876,9 +878,9 @@ static void DisasLdstRegImm9(uint32_t insn, DisasCallback *cb,
|
|||
cb->AddI64 (GPR_DUMMY, rn, imm9, false, true);
|
||||
}
|
||||
if (is_store) {
|
||||
cb->StoreRegI64 (rt, GPR_DUMMY, size, is_extended);
|
||||
cb->StoreRegI64 (rt, GPR_DUMMY, size, is_signed, is_extended);
|
||||
} else {
|
||||
cb->LoadRegI64 (rt, GPR_DUMMY, size, is_extended);
|
||||
cb->LoadRegI64 (rt, GPR_DUMMY, size, is_signed, is_extended);
|
||||
}
|
||||
if (writeback) {
|
||||
cb->AddI64 (rn, rn, imm9, false, true);
|
||||
|
@ -920,23 +922,24 @@ static void DisasLdstRegUnsignedImm(uint32_t insn, DisasCallback *cb,
|
|||
}
|
||||
is_store = (opc == 0);
|
||||
is_signed = extract32(opc, 1, 1);
|
||||
is_extended = (size < 3) && extract32(opc, 0, 1);
|
||||
//is_extended = (size < 3) && extract32(opc, 0, 1);
|
||||
is_extended = (size < 3); //TODO: treat other case, size = 0, 1(8bit-> or 16bit->)
|
||||
}
|
||||
offset = imm12 << size;
|
||||
cb->AddI64 (GPR_DUMMY, rn, offset, false, true);
|
||||
if (is_vector) {
|
||||
/* size must be 4 (128-bit) */
|
||||
if (is_store) {
|
||||
cb->StoreRegI64 (rt, GPR_DUMMY, size, false);
|
||||
cb->StoreRegI64 (rt, GPR_DUMMY, size, is_signed, false);
|
||||
} else {
|
||||
cb->LoadRegI64 (rt, GPR_DUMMY, size, false);
|
||||
cb->LoadRegI64 (rt, GPR_DUMMY, size, is_signed, false);
|
||||
}
|
||||
} else {
|
||||
bool sf = DisasLdstCompute64bit (size, is_signed, opc);
|
||||
if (is_store) {
|
||||
cb->StoreRegI64 (rt, GPR_DUMMY, size, is_extended);
|
||||
cb->StoreRegI64 (rt, GPR_DUMMY, size, is_signed, is_extended);
|
||||
} else {
|
||||
cb->LoadRegI64 (rt, GPR_DUMMY, size, is_extended);
|
||||
cb->LoadRegI64 (rt, GPR_DUMMY, size, is_signed, is_extended);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1042,13 +1045,13 @@ static void DisasLdstPair(uint32_t insn, DisasCallback *cb) {
|
|||
if (is_load) {
|
||||
/* XXX: Do not modify rt register before recognizing any exception
|
||||
* from the second load. */
|
||||
cb->LoadRegI64 (rt, GPR_DUMMY, size, false);
|
||||
cb->LoadRegI64 (rt, GPR_DUMMY, size, is_signed, false);
|
||||
cb->AddI64 (GPR_DUMMY, GPR_DUMMY, 1 << size, false, true);
|
||||
cb->LoadRegI64 (rt2, GPR_DUMMY, size, false);
|
||||
cb->LoadRegI64 (rt2, GPR_DUMMY, size, is_signed, false);
|
||||
} else {
|
||||
cb->StoreRegI64 (rt, GPR_DUMMY, size, false);
|
||||
cb->StoreRegI64 (rt, GPR_DUMMY, size, is_signed, false);
|
||||
cb->AddI64 (GPR_DUMMY, GPR_DUMMY, 1 << size, false, true);
|
||||
cb->StoreRegI64 (rt2, GPR_DUMMY, size, false);
|
||||
cb->StoreRegI64 (rt2, GPR_DUMMY, size, is_signed, false);
|
||||
}
|
||||
if (writeback) {
|
||||
cb->AddI64 (rn, rn, offset, false, true);
|
||||
|
|
|
@ -17,7 +17,7 @@ int Interpreter::SingleStep() {
|
|||
void Interpreter::Run() {
|
||||
debug_print ("Running with Interpreter\n");
|
||||
static uint64_t counter = 0;
|
||||
uint64_t estimate = 3400000;
|
||||
uint64_t estimate = 3404800;
|
||||
while (Cpu::GetState () == Cpu::State::Running) {
|
||||
char c;
|
||||
//scanf("%c", &c);
|
||||
|
@ -382,12 +382,54 @@ void IntprCallback::NotReg(unsigned int rd_idx, unsigned int rm_idx, bool bit64)
|
|||
else
|
||||
X(rd_idx) = ~W(rm_idx);
|
||||
}
|
||||
|
||||
static void ExtendRegI64(unsigned int rd_idx, uint64_t imm, unsigned int option) {
|
||||
int extsize = extract32(option, 0, 2);
|
||||
bool is_signed = extract32(option, 2, 1);
|
||||
if (is_signed) {
|
||||
switch (extsize) {
|
||||
case 0:
|
||||
X(rd_idx) = (int64_t)(int8_t)(imm & 0xff);
|
||||
break;
|
||||
case 1:
|
||||
X(rd_idx) = (int64_t)(int16_t)(imm & 0xffff);
|
||||
break;
|
||||
case 2:
|
||||
X(rd_idx) = (int64_t)(int32_t)(imm & 0xffffffff);
|
||||
break;
|
||||
case 3:
|
||||
X(rd_idx) = imm;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (extsize) {
|
||||
case 0:
|
||||
X(rd_idx) = (uint64_t) (imm & 0xff);
|
||||
break;
|
||||
case 1:
|
||||
X(rd_idx) = (uint64_t) (imm & 0xffff);
|
||||
break;
|
||||
case 2:
|
||||
X(rd_idx) = (uint64_t) (imm & 0xffffffff);
|
||||
break;
|
||||
case 3:
|
||||
X(rd_idx) = imm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void IntprCallback::ExtendReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int extend_type, bool bit64) {
|
||||
/* TODO: */
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("Extend: %c[%u] Ext(%c[%u])\n", regc, rd_idx, regc, rn_idx);
|
||||
if (bit64)
|
||||
ExtendRegI64 (rd_idx, X(rn_idx), extend_type);
|
||||
else
|
||||
ExtendRegI64 (rd_idx, W(rn_idx), extend_type);
|
||||
}
|
||||
|
||||
/* Load/Store */
|
||||
static void _LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool extend) {
|
||||
static void _LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool is_sign, bool extend) {
|
||||
debug_print ("Read from addr:0x%lx(%d)\n", addr, size);
|
||||
if (size == 0) {
|
||||
X(rd_idx) = ARMv8::ReadU8 (addr);
|
||||
|
@ -404,11 +446,13 @@ static void _LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool extend)
|
|||
//ns_debug("Read: Q = 0x%lx, 0x%lx\n", VREG(rd_idx).d[0], VREG(rd_idx).d[1]);
|
||||
}
|
||||
|
||||
/* TODO: if (extend)
|
||||
ExtendReg(rd_idx, rd_idx, type, true); */
|
||||
if (extend && is_sign) {
|
||||
/* TODO: treat other cases (8bit-> or 16bit->)*/
|
||||
X(rd_idx) = (int64_t) (int32_t) W(rd_idx);
|
||||
}
|
||||
}
|
||||
|
||||
static void _StoreReg(unsigned int rd_idx, uint64_t addr, int size, bool extend) {
|
||||
static void _StoreReg(unsigned int rd_idx, uint64_t addr, int size, bool is_sign, bool extend) {
|
||||
debug_print ("Write to addr:0x%lx(%d)\n", addr, size);
|
||||
if (size == 0) {
|
||||
ARMv8::WriteU8 (addr, (uint8_t) (W(rd_idx) & 0xff));
|
||||
|
@ -424,63 +468,61 @@ static void _StoreReg(unsigned int rd_idx, uint64_t addr, int size, bool extend)
|
|||
ARMv8::WriteU64 (addr, VREG(rd_idx).d[1]);
|
||||
//ns_debug("Write: Q = 0x%lx, 0x%lx\n", VREG(rd_idx).d[0], VREG(rd_idx).d[1]);
|
||||
}
|
||||
/* TODO: if (extend)
|
||||
ExtendReg(rd_idx, rd_idx, type, true); */
|
||||
}
|
||||
|
||||
void IntprCallback::LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size,
|
||||
bool extend, bool post, bool bit64) {
|
||||
bool is_sign, bool extend, bool post, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
char regdc = size >= 4 ? 'Q' : (size < 3 ? 'W' : 'X');
|
||||
base_idx = ARMv8::HandleAsSP (base_idx);
|
||||
debug_print ("Load(%d): %c[%u] <= [%c[%u], %c[%u]]\n", size, regdc, rd_idx, regc, base_idx, regc, rm_idx);
|
||||
debug_print ("Load(%d): %c[%u] <= [%c[%u], %c[%u]](extend:%d, sign:%d)\n", size, regdc, rd_idx, regc, base_idx, regc, rm_idx, extend, is_sign);
|
||||
uint64_t addr;
|
||||
if (bit64) {
|
||||
if (post)
|
||||
addr = X(base_idx);
|
||||
else
|
||||
addr = X(base_idx) + X(rm_idx);
|
||||
_LoadReg (rd_idx, addr, size, extend);
|
||||
_LoadReg (rd_idx, addr, size, is_sign, extend);
|
||||
} else {
|
||||
if (post)
|
||||
addr = W(base_idx);
|
||||
else
|
||||
addr = W(base_idx) + W(rm_idx);
|
||||
_LoadReg (rd_idx, addr, size, extend);
|
||||
_LoadReg (rd_idx, addr, size, is_sign, extend);
|
||||
}
|
||||
}
|
||||
void IntprCallback::LoadRegI64(unsigned int rd_idx, unsigned int ad_idx, int size,
|
||||
bool extend) {
|
||||
bool is_sign, bool extend) {
|
||||
char regdc = size >= 4 ? 'Q' : (size < 3 ? 'W' : 'X');
|
||||
debug_print ("Load(%d): %c[%u] <= [0x%lx]\n", size, regdc, rd_idx, X(ad_idx));
|
||||
_LoadReg (rd_idx, X(ad_idx), size, extend);
|
||||
_LoadReg (rd_idx, X(ad_idx), size, is_sign, extend);
|
||||
}
|
||||
void IntprCallback::StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size,
|
||||
bool extend, bool post, bool bit64) {
|
||||
bool is_sign, bool extend, bool post, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
char regdc = size >= 4 ? 'Q' : (size < 3 ? 'W' : 'X');
|
||||
base_idx = ARMv8::HandleAsSP (base_idx);
|
||||
debug_print ("Store(%d): %c[%u] => [%c[%u], %c[%u]]\n", size, regdc, rd_idx, regc, base_idx, regc, rm_idx);
|
||||
debug_print ("Store(%d): %c[%u] => [%c[%u], %c[%u]](extend:%d, sign:%d)\n", size, regdc, rd_idx, regc, base_idx, regc, rm_idx, extend, is_sign);
|
||||
uint64_t addr;
|
||||
if (bit64) {
|
||||
if (post)
|
||||
addr = X(base_idx);
|
||||
else
|
||||
addr = X(base_idx) + X(rm_idx);
|
||||
_StoreReg (rd_idx, addr, size, extend);
|
||||
_StoreReg (rd_idx, addr, size, is_sign, extend);
|
||||
} else {
|
||||
if (post)
|
||||
addr = W(base_idx);
|
||||
else
|
||||
addr = W(base_idx) + W(rm_idx);
|
||||
_StoreReg (rd_idx, addr, size, extend);
|
||||
_StoreReg (rd_idx, addr, size, is_sign, extend);
|
||||
}
|
||||
}
|
||||
void IntprCallback::StoreRegI64(unsigned int rd_idx, unsigned int ad_idx, int size,
|
||||
bool extend) {
|
||||
bool is_sign, bool extend) {
|
||||
char regdc = size >= 4 ? 'Q' : (size < 3 ? 'W' : 'X');
|
||||
debug_print ("Store(%d): %c[%u] => [0x%lx]\n", size, regdc, rd_idx, X(ad_idx));
|
||||
_StoreReg (rd_idx, X(ad_idx), size, extend);
|
||||
_StoreReg (rd_idx, X(ad_idx), size, is_sign, extend);
|
||||
}
|
||||
|
||||
/* Bitfield Signed/Unsigned Extract... with Immediate value */
|
||||
|
@ -631,7 +673,8 @@ void IntprCallback::BranchFlag(unsigned int cond, uint64_t addr) {
|
|||
|
||||
/* Set PC with reg */
|
||||
void IntprCallback::SetPCReg(unsigned int rt_idx) {
|
||||
PC = X(rt_idx);
|
||||
PC = X(rt_idx) - 4;
|
||||
ns_print ("Goto: 0x%lx\n", PC);
|
||||
}
|
||||
|
||||
/* Super Visor Call */
|
||||
|
|
|
@ -47,10 +47,10 @@ virtual void NotReg(unsigned int rd_idx, unsigned int rm_idx, bool bit64) = 0;
|
|||
virtual void ExtendReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int extend_type, bool bit64) = 0;
|
||||
|
||||
/* Load/Store */
|
||||
virtual void LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool extend, bool post, bool bit64) = 0;
|
||||
virtual void LoadRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool extend) = 0;
|
||||
virtual void StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool extend, bool post, bool bit64) = 0;
|
||||
virtual void StoreRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool extend) = 0;
|
||||
virtual void LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool is_sign, bool extend, bool post, bool bit64) = 0;
|
||||
virtual void LoadRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool is_sign, bool extend) = 0;
|
||||
virtual void StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool is_sign, bool extend, bool post, bool bit64) = 0;
|
||||
virtual void StoreRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool is_sign, bool extend) = 0;
|
||||
|
||||
/* Bitfield Signed/Unsigned Extract... with Immediate value */
|
||||
virtual void SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) = 0;
|
||||
|
|
|
@ -47,10 +47,10 @@ void NotReg(unsigned int rd_idx, unsigned int rm_idx, bool bit64);
|
|||
void ExtendReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int extend_type, bool bit64);
|
||||
|
||||
/* Load/Store */
|
||||
void LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool extend, bool post, bool bit64);
|
||||
void LoadRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool extend);
|
||||
void StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool extend, bool post, bool bit64);
|
||||
void StoreRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool extend);
|
||||
void LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool is_sign, bool extend, bool post, bool bit64);
|
||||
void LoadRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool is_sign, bool extend);
|
||||
void StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool is_sign, bool extend, bool post, bool bit64);
|
||||
void StoreRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool is_sign, bool extend);
|
||||
|
||||
/* Bitfield Signed/Unsigned Extract... with Immediate value */
|
||||
void SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64);
|
||||
|
|
|
@ -13,8 +13,8 @@ enum RunLevel {
|
|||
RUN_LEVEL_DEBUG,
|
||||
};
|
||||
|
||||
//static RunLevel curlevel = RUN_LEVEL_DEBUG;
|
||||
static RunLevel curlevel = RUN_LEVEL_RELEASE;
|
||||
static RunLevel curlevel = RUN_LEVEL_DEBUG;
|
||||
//static RunLevel curlevel = RUN_LEVEL_RELEASE;
|
||||
|
||||
static void util_print(RunLevel level, FILE *fp, const char *format, ...) {
|
||||
if (curlevel >= level) {
|
||||
|
|
Loading…
Reference in a new issue