Add support for load/store operation with register offset

This commit is contained in:
rkx1209 2018-03-05 04:28:03 +09:00
parent 0ce05811e9
commit 77e2611ca2
4 changed files with 153 additions and 5 deletions

View file

@ -725,7 +725,91 @@ static void DisasLdLit(uint32_t insn, DisasCallback *cb) {
size = 2 + extract32(opc, 0, 1);
is_signed = extract32(opc, 1, 1);
}
cb->LoadReg (rt, PC + imm - 4, size, false, sf);
cb->LoadRegImm64 (rt, PC + imm - 4, size, false, sf);
}
static bool DisasLdstCompute64bit(unsigned int size, bool is_signed, unsigned int opc) {
unsigned int opc0 = extract32(opc, 0, 1);
unsigned int regsize;
if (is_signed) {
regsize = opc0 ? 32 : 64;
} else {
regsize = size == 3 ? 64 : 32;
}
return regsize == 64;
}
/* Load/Store register ... register offset */
static void DisasLdstRegRoffset(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 shift = extract32(insn, 12, 1);
unsigned int rm = extract32(insn, 16, 5);
unsigned int opt = extract32(insn, 13, 3);
bool is_signed = false;
bool is_store = false;
bool is_extended = false;
bool sf = DisasLdstCompute64bit (size, is_signed, opc);
if (extract32(opt, 1, 1) == 0) {
UnallocatedOp (insn);
return;
}
if (is_vector) {
UnsupportedOp ("LDR/STR (SIMD&FP)");
} else {
if (size == 3 && opc == 2) {
/* PRFM - prefetch */
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);
}
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);
} else {
cb->LoadReg (rt, rm, size, is_extended, sf);
}
}
/* Load/Store register ... register offset mode */
static void DisasLdstReg(uint32_t insn, DisasCallback *cb) {
unsigned int rt = extract32(insn, 0, 5);
unsigned int opc = extract32(insn, 22, 2);
bool is_vector = extract32(insn, 26, 1);
unsigned int size = extract32(insn, 30, 2);
switch (extract32(insn, 24, 2)) {
case 0:
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 immediate pre/post-indexed
* Load/store register unprivileged
*/
//DisasLdstRegImm9 (insn, cb);
}
break;
case 1:
//DisasLdstRegUnsignedImm (insn, cb);
break;
default:
UnallocatedOp (insn);
break;
}
}
static void DisasLdSt(uint32_t insn, DisasCallback *cb) {
@ -743,7 +827,7 @@ static void DisasLdSt(uint32_t insn, DisasCallback *cb) {
break;
case 0x38: case 0x39:
case 0x3c: case 0x3d: /* Load/store register (all forms) */
//DisasLdstReg (insn, cb);
DisasLdstReg (insn, cb);
break;
case 0x0c: /* AdvSIMD load/store multiple structures */
UnsupportedOp("SIMD Load/Store Multi");

View file

@ -344,7 +344,23 @@ void IntprCallback::ExtendReg(unsigned int rd_idx, unsigned int rn_idx, unsigned
}
/* Load/Store */
void IntprCallback::LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool extend, bool bit64) {
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) {
if (bit64) {
if (size == 4)
X(rd_idx) = ARMv8::ReadU32 (addr);
@ -360,6 +376,37 @@ void IntprCallback::LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool e
}
}
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) {
if (bit64) {
if (size == 4)
ARMv8::WriteU32 (addr, X(rd_idx));
if (size == 8)
ARMv8::WriteU64 (addr, X(rd_idx));
/* TODO: if (extend)
ExtendReg(rd_idx, rd_idx, type, true); */
} else {
if (size == 4)
ARMv8::WriteU32 (addr, W(rd_idx));
/* TODO: if (extend)
ExtendReg(rd_idx, rd_idx, type, true); */
}
}
/* 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

@ -44,7 +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, uint64_t addr, int size, bool extend, bool bit64) = 0;
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;
/* 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;
@ -95,6 +98,17 @@ enum ShiftType {
ShiftType_ROR
};
enum ExtendType {
ExtendType_UXTB = 0,
ExtendType_UXTH,
ExtendType_UXTW,
ExtendType_UXTX,
ExtendType_SXTB,
ExtendType_SXTH,
ExtendType_SXTW,
ExtendType_SXTX,
};
enum CondType {
CondType_EQ = 0,
CondType_NE,

View file

@ -44,7 +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, uint64_t addr, int size, bool extend, bool bit64);
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);
/* 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);