Add support for load/store operation with register immediate

This commit is contained in:
rkx1209 2018-03-05 07:18:11 +09:00
parent 77e2611ca2
commit ad2cfdc816
5 changed files with 175 additions and 51 deletions

View file

@ -725,7 +725,7 @@ static void DisasLdLit(uint32_t insn, DisasCallback *cb) {
size = 2 + extract32(opc, 0, 1);
is_signed = extract32(opc, 1, 1);
}
cb->LoadRegImm64 (rt, PC + imm - 4, size, false, sf);
cb->LoadRegImm64 (rt, PC_IDX, imm - 4, size, false, false, false, sf);
}
static bool DisasLdstCompute64bit(unsigned int size, bool is_signed, unsigned int opc) {
@ -761,7 +761,7 @@ static void DisasLdstRegRoffset(uint32_t insn, DisasCallback *cb,
}
if (is_vector) {
UnsupportedOp ("LDR/STR (SIMD&FP)");
UnsupportedOp ("LDR/STR [base, Xm/Wm] (SIMD&FP)");
} else {
if (size == 3 && opc == 2) {
/* PRFM - prefetch */
@ -778,9 +778,75 @@ static void DisasLdstRegRoffset(uint32_t insn, DisasCallback *cb,
cb->ExtendReg (rm, rm, opt, sf);
cb->ShiftReg (rm, rm, ShiftType_LSL, shift ? size : 0, sf);
if (is_store) {
cb->StoreReg (rt, rm, size, is_extended, sf);
cb->StoreReg (rt, rn, rm, size, is_extended, false, false, sf);
} else {
cb->LoadReg (rt, rm, size, is_extended, sf);
cb->LoadReg (rt, rn, rm, size, is_extended, false, false, sf);
}
}
/*
* Load/store register (unscaled immediate)
* Load/store immediate pre/post-indexed
* Load/store register unprivileged
*/
static void DisasLdstRegImm9(uint32_t insn, DisasCallback *cb,
unsigned int opc,
unsigned int size,
unsigned int rt,
bool is_vector) {
unsigned int rn = extract32(insn, 5, 5);
unsigned int imm9 = sextract32(insn, 12, 9);
unsigned int idx = extract32(insn, 10, 2);
bool is_signed = false;
bool is_store = false;
bool is_extended = false;
bool is_unpriv = (idx == 2);
bool iss_valid = !is_vector;
bool post_index;
bool writeback;
bool sf = DisasLdstCompute64bit (size, is_signed, opc);
if (is_vector) {
UnsupportedOp ("LDR/STR [base, #imm9] (SIMD&FP)");
} else {
if (size == 3 && opc == 2) {
/* PRFM - prefetch */
if (is_unpriv) {
UnallocatedOp (insn);
return;
}
return;
}
if (opc == 3 && size > 1) {
UnallocatedOp (insn);
return;
}
is_store = (opc == 0);
is_signed = extract32(opc, 1, 1);
is_extended = (size < 3) && extract32(opc, 0, 1);
}
switch (idx) {
case 0:
case 2:
post_index = false;
writeback = false;
break;
case 1:
post_index = true;
writeback = true;
break;
case 3:
post_index = false;
writeback = true;
break;
default:
ns_abort ("Unreachable status\n");
}
if (is_store) {
cb->StoreRegImm64 (rt, rn, imm9, size, is_extended, post_index, writeback, sf);
} else {
cb->LoadRegImm64 (rt, rn, imm9, size, is_extended, post_index, writeback, sf);
}
}
@ -796,11 +862,12 @@ static void DisasLdstReg(uint32_t insn, DisasCallback *cb) {
if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
DisasLdstRegRoffset (insn, cb, opc, size, rt, is_vector);
} else {
/* Load/store register (unscaled immediate)
/*
* Load/store register (unscaled immediate)
* Load/store immediate pre/post-indexed
* Load/store register unprivileged
*/
//DisasLdstRegImm9 (insn, cb);
DisasLdstRegImm9 (insn, cb, opc, size, rt, is_vector);
}
break;
case 1:

View file

@ -344,23 +344,7 @@ void IntprCallback::ExtendReg(unsigned int rd_idx, unsigned int rn_idx, unsigned
}
/* Load/Store */
void IntprCallback::LoadReg(unsigned int rd_idx, unsigned int rm_idx, int size, bool extend, bool bit64) {
if (bit64) {
if (size == 4)
X(rd_idx) = ARMv8::ReadU32 (X(rm_idx));
if (size == 8)
X(rd_idx) = ARMv8::ReadU64 (X(rm_idx));
/* TODO: if (extend)
ExtendReg(rd_idx, rd_idx, type, true); */
} else {
if (size == 4)
W(rd_idx) = ARMv8::ReadU32 (W(rm_idx));
/* TODO: if (extend)
ExtendReg(rd_idx, rd_idx, type, true); */
}
}
void IntprCallback::LoadRegImm64(unsigned int rd_idx, uint64_t addr, int size, bool extend, bool bit64) {
static void _LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool extend, bool bit64) {
if (bit64) {
if (size == 4)
X(rd_idx) = ARMv8::ReadU32 (addr);
@ -376,22 +360,7 @@ void IntprCallback::LoadRegImm64(unsigned int rd_idx, uint64_t addr, int size, b
}
}
void IntprCallback::StoreReg(unsigned int rd_idx, unsigned int rm_idx, int size, bool extend, bool bit64) {
if (bit64) {
if (size == 4)
ARMv8::WriteU32 (X(rm_idx), X(rd_idx));
if (size == 8)
ARMv8::WriteU64 (X(rm_idx), X(rd_idx));
/* TODO: if (extend)
ExtendReg(rd_idx, rd_idx, type, true); */
} else {
if (size == 4)
ARMv8::WriteU32 (W(rm_idx), W(rd_idx));
/* TODO: if (extend)
ExtendReg(rd_idx, rd_idx, type, true); */
}
}
void IntprCallback::StoreRegImm64(unsigned int rd_idx, uint64_t addr, int size, bool extend, bool bit64) {
static void _StoreReg(unsigned int rd_idx, uint64_t addr, int size, bool extend, bool bit64) {
if (bit64) {
if (size == 4)
ARMv8::WriteU32 (addr, X(rd_idx));
@ -407,6 +376,91 @@ void IntprCallback::StoreRegImm64(unsigned int rd_idx, uint64_t addr, int size,
}
}
void IntprCallback::LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size,
bool extend, bool post, bool writeback, bool bit64) {
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, true);
if (writeback)
X(base_idx) = addr;
} else {
if (post)
addr = W(base_idx);
else
addr = W(base_idx) + W(rm_idx);
_LoadReg (rd_idx, addr, size, extend, false);
if (writeback)
W(base_idx) = addr;
}
}
void IntprCallback::LoadRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size,
bool extend, bool post, bool writeback, bool bit64) {
uint64_t addr;
if (bit64) {
if (post)
addr = X(base_idx);
else
addr = X(base_idx) + offset;
_LoadReg (rd_idx, addr, size, extend, true);
if (writeback)
X(base_idx) = addr;
} else {
if (post)
addr = W(base_idx);
else
addr = W(base_idx) + offset;
_LoadReg (rd_idx, addr, size, extend, false);
if (writeback)
W(base_idx) = addr;
}
}
void IntprCallback::StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size,
bool extend, bool post, bool writeback, bool bit64) {
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, true);
if (writeback)
X(base_idx) = addr;
} else {
if (post)
addr = W(base_idx);
else
addr = W(base_idx) + W(rm_idx);
_StoreReg (rd_idx, addr, size, extend, false);
if (writeback)
W(base_idx) = addr;
}
}
void IntprCallback::StoreRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size,
bool extend, bool post, bool writeback, bool bit64) {
uint64_t addr;
if (bit64) {
if (post)
addr = X(base_idx);
else
addr = X(base_idx) + offset;
_StoreReg (rd_idx, addr, size, extend, true);
if (writeback)
X(base_idx) = addr;
} else {
if (post)
addr = W(base_idx);
else
addr = W(base_idx) + offset;
_StoreReg (rd_idx, addr, size, extend, false);
if (writeback)
W(base_idx) = addr;
}
}
/* Bitfield Signed/Unsigned Extract... with Immediate value */
void IntprCallback::SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) {
/* TODO: */

View file

@ -9,8 +9,10 @@ typedef union {
}reg_t;
struct ARMv8State {
reg_t gpr[33]; // x0 - x31 (x30 is usually "link regsiter" and x31 is "stack pointer" or "zero register" )
uint64_t pc;
reg_t gpr[34];
/*
* x0 - x31 (x30 is usually "link regsiter" and x31 is "stack pointer" or "zero register" )
* NOTE: In nsemu, 'PC' register is respresented as x32 internally. */
uint32_t nzcv; // flag register
};
@ -19,12 +21,13 @@ extern ARMv8State arm_state;
#define GPR_LR 30
#define GPR_SP 31
#define GPR_ZERO 31
#define GPR_DUMMY 32
#define PC_IDX 32
#define GPR_DUMMY 33
#define LR ARMv8::arm_state.gpr[GPR_LR]
#define SP ARMv8::arm_state.gpr[GPR_SP]
#define ZERO ARMv8::arm_state.gpr[GPR_ZERO]
#define PC ARMv8::arm_state.pc
#define PC ARMv8::arm_state.gpr[PC_IDX].x // XXX: bit tricky
#define NZCV ARMv8::arm_state.nzcv
#define N_MASK 0x80000000
#define Z_MASK 0x40000000

View file

@ -44,10 +44,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 rm_idx, int size, bool extend, bool bit64) = 0;
virtual void LoadRegImm64(unsigned int rd_idx, uint64_t addr, int size, bool extend, bool bit64) = 0;
virtual void StoreReg(unsigned int rd_idx, unsigned int rm_idx, int size, bool extend, bool bit64) = 0;
virtual void StoreRegImm64(unsigned int rd_idx, uint64_t addr, int size, bool extend, bool bit64) = 0;
virtual void LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool extend, bool post, bool writeback, bool bit64) = 0;
virtual void LoadRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size, bool extend, bool post, bool writeback, bool bit64) = 0;
virtual void StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool extend, bool post, bool writeback, bool bit64) = 0;
virtual void StoreRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size, bool extend, bool post, bool writeback, bool bit64) = 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

@ -44,10 +44,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 rm_idx, int size, bool extend, bool bit64);
void LoadRegImm64(unsigned int rd_idx, uint64_t addr, int size, bool extend, bool bit64);
void StoreReg(unsigned int rd_idx, unsigned int rm_idx, int size, bool extend, bool bit64);
void StoreRegImm64(unsigned int rd_idx, uint64_t addr, int size, bool extend, bool bit64);
void LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool extend, bool post, bool writeback, bool bit64);
void LoadRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size, bool extend, bool post, bool writeback, bool bit64);
void StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool extend, bool post, bool writeback, bool bit64);
void StoreRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size, bool extend, bool post, bool writeback, bool bit64);
/* 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);