Add support of extract operations

This commit is contained in:
rkx1209 2018-03-18 04:39:47 +09:00
parent 2f69bb9140
commit fce85f7a91
5 changed files with 99 additions and 53 deletions

View file

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

View file

@ -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 */

View file

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

View file

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

View file

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