mirror of
https://github.com/RKX1209/nsemu.git
synced 2024-06-23 14:43:16 -04:00
Add support for load/store operation with 128bit register(FP)
This commit is contained in:
parent
3679e913a5
commit
adde42797b
|
@ -10,6 +10,11 @@ static inline void UnallocatedOp(uint32_t insn) {
|
|||
ns_abort ("Unallocated operation 0x%08lx\n", insn);
|
||||
}
|
||||
|
||||
static inline bool FpAccessCheck(uint32_t insn) {
|
||||
/* TODO: */
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool LogicImmDecode(uint64_t *wmask, unsigned int immn, unsigned int imms, unsigned int immr) {
|
||||
assert (immn < 2 && imms < 64 && immr < 64);
|
||||
uint64_t mask;
|
||||
|
@ -863,7 +868,16 @@ static void DisasLdstRegUnsignedImm(uint32_t insn, DisasCallback *cb,
|
|||
bool is_extended = false;
|
||||
|
||||
if (is_vector) {
|
||||
UnsupportedOp ("LDR/STR [base, #simm12] (SIMD&FP)");
|
||||
/* LDR/STR [base, #simm12] (SIMD&FP) */
|
||||
size |= (opc & 2) << 1;
|
||||
if (size > 4) {
|
||||
UnallocatedOp (insn);
|
||||
return;
|
||||
}
|
||||
is_store = !extract32(opc, 0, 1);
|
||||
if (!FpAccessCheck (insn)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (size == 3 && opc == 2) {
|
||||
/* PRFM - prefetch */
|
||||
|
@ -877,12 +891,21 @@ static void DisasLdstRegUnsignedImm(uint32_t insn, DisasCallback *cb,
|
|||
is_signed = extract32(opc, 1, 1);
|
||||
is_extended = (size < 3) && extract32(opc, 0, 1);
|
||||
}
|
||||
bool sf = DisasLdstCompute64bit (size, is_signed, opc);
|
||||
offset = imm12 << size;
|
||||
if (is_store) {
|
||||
cb->StoreRegImm64 (rt, rn, offset, size, is_extended, false, false, sf);
|
||||
if (is_vector) {
|
||||
/* size must be 4 (128-bit) */
|
||||
if (is_store) {
|
||||
cb->StoreRegImm64 (rt, rn, offset, size, false, false, false, true);
|
||||
} else {
|
||||
cb->LoadRegImm64 (rt, rn, offset, size, false, false, false, true);
|
||||
}
|
||||
} else {
|
||||
cb->LoadRegImm64 (rt, rn, offset, size, is_extended, false, false, sf);
|
||||
bool sf = DisasLdstCompute64bit (size, is_signed, opc);
|
||||
if (is_store) {
|
||||
cb->StoreRegImm64 (rt, rn, offset, size, is_extended, false, false, sf);
|
||||
} else {
|
||||
cb->LoadRegImm64 (rt, rn, offset, size, is_extended, false, false, sf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -346,49 +346,43 @@ 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, bool bit64) {
|
||||
if (bit64) {
|
||||
if (size == 4)
|
||||
W(rd_idx) = ARMv8::ReadU32 (addr);
|
||||
if (size == 8)
|
||||
X(rd_idx) = ARMv8::ReadU64 (addr);
|
||||
/* TODO: if (extend)
|
||||
ExtendReg(rd_idx, rd_idx, type, true); */
|
||||
} else {
|
||||
if (size == 4)
|
||||
W(rd_idx) = ARMv8::ReadU32 (addr);
|
||||
/* TODO: if (extend)
|
||||
ExtendReg(rd_idx, rd_idx, type, true); */
|
||||
}
|
||||
static void _LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool extend) {
|
||||
if (size < 4) {
|
||||
X(rd_idx) = ARMv8::ReadU64 (addr);
|
||||
} else {
|
||||
/* 128-bit Qt */
|
||||
VREG(rd_idx).d[0] = ARMv8::ReadU64 (addr + 8);
|
||||
VREG(rd_idx).d[1] = ARMv8::ReadU64 (addr);
|
||||
}
|
||||
|
||||
/* TODO: if (extend)
|
||||
ExtendReg(rd_idx, rd_idx, type, true); */
|
||||
}
|
||||
|
||||
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));
|
||||
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); */
|
||||
}
|
||||
static void _StoreReg(unsigned int rd_idx, uint64_t addr, int size, bool extend) {
|
||||
if (size < 4) {
|
||||
ARMv8::WriteU64 (addr, X(rd_idx));
|
||||
} else {
|
||||
/* 128-bit Qt */
|
||||
ARMv8::WriteU64 (addr + 8, VREG(rd_idx).d[0]);
|
||||
ARMv8::WriteU64 (addr, 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 writeback, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("Load(%d): %c[%u] <= [%c[%u], %c[%u]]\n", size, regc, rd_idx, regc, base_idx, regc, rm_idx);
|
||||
char regdc = bit64 && size >= 4 ? 'Q' : regc;
|
||||
debug_print ("Load(%d): %c[%u] <= [%c[%u], %c[%u]]\n", size, regdc, rd_idx, regc, base_idx, regc, rm_idx);
|
||||
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);
|
||||
_LoadReg (rd_idx, addr, size, extend);
|
||||
if (writeback)
|
||||
X(base_idx) = addr;
|
||||
} else {
|
||||
|
@ -396,7 +390,7 @@ void IntprCallback::LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned
|
|||
addr = W(base_idx);
|
||||
else
|
||||
addr = W(base_idx) + W(rm_idx);
|
||||
_LoadReg (rd_idx, addr, size, extend, false);
|
||||
_LoadReg (rd_idx, addr, size, extend);
|
||||
if (writeback)
|
||||
W(base_idx) = addr;
|
||||
}
|
||||
|
@ -404,14 +398,15 @@ void IntprCallback::LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned
|
|||
void IntprCallback::LoadRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size,
|
||||
bool extend, bool post, bool writeback, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("Load(%d): %c[%u] <= [%c[%u], 0x%lx]\n", size, regc, rd_idx, regc, base_idx, offset);
|
||||
char regdc = bit64 && size >= 4 ? 'Q' : regc;
|
||||
debug_print ("Load(%d): %c[%u] <= [%c[%u], 0x%lx]\n", size, regdc, rd_idx, regc, base_idx, offset);
|
||||
uint64_t addr;
|
||||
if (bit64) {
|
||||
if (post)
|
||||
addr = X(base_idx);
|
||||
else
|
||||
addr = X(base_idx) + offset;
|
||||
_LoadReg (rd_idx, addr, size, extend, true);
|
||||
_LoadReg (rd_idx, addr, size, extend);
|
||||
if (writeback)
|
||||
X(base_idx) = addr;
|
||||
} else {
|
||||
|
@ -419,7 +414,7 @@ void IntprCallback::LoadRegImm64(unsigned int rd_idx, unsigned int base_idx, uin
|
|||
addr = W(base_idx);
|
||||
else
|
||||
addr = W(base_idx) + offset;
|
||||
_LoadReg (rd_idx, addr, size, extend, false);
|
||||
_LoadReg (rd_idx, addr, size, extend);
|
||||
if (writeback)
|
||||
W(base_idx) = addr;
|
||||
}
|
||||
|
@ -427,14 +422,15 @@ void IntprCallback::LoadRegImm64(unsigned int rd_idx, unsigned int base_idx, uin
|
|||
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) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("Store(%d): %c[%u] => [%c[%u], %c[%u]]\n", size, regc, rd_idx, regc, base_idx, regc, rm_idx);
|
||||
char regdc = bit64 && size >= 4 ? 'Q' : regc;
|
||||
debug_print ("Store(%d): %c[%u] => [%c[%u], %c[%u]]\n", size, regdc, rd_idx, regc, base_idx, regc, rm_idx);
|
||||
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);
|
||||
_StoreReg (rd_idx, addr, size, extend);
|
||||
if (writeback)
|
||||
X(base_idx) = addr;
|
||||
} else {
|
||||
|
@ -442,7 +438,7 @@ void IntprCallback::StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigne
|
|||
addr = W(base_idx);
|
||||
else
|
||||
addr = W(base_idx) + W(rm_idx);
|
||||
_StoreReg (rd_idx, addr, size, extend, false);
|
||||
_StoreReg (rd_idx, addr, size, extend);
|
||||
if (writeback)
|
||||
W(base_idx) = addr;
|
||||
}
|
||||
|
@ -450,14 +446,15 @@ void IntprCallback::StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigne
|
|||
void IntprCallback::StoreRegImm64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size,
|
||||
bool extend, bool post, bool writeback, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("Store(%d): %c[%u] => [%c[%u], 0x%lx]\n", size, regc, rd_idx, regc, base_idx, offset);
|
||||
char regdc = bit64 && size >= 4 ? 'Q' : regc;
|
||||
debug_print ("Store(%d): %c[%u] => [%c[%u], 0x%lx]\n", size, regdc, rd_idx, regc, base_idx, offset);
|
||||
uint64_t addr;
|
||||
if (bit64) {
|
||||
if (post)
|
||||
addr = X(base_idx);
|
||||
else
|
||||
addr = X(base_idx) + offset;
|
||||
_StoreReg (rd_idx, addr, size, extend, true);
|
||||
_StoreReg (rd_idx, addr, size, extend);
|
||||
if (writeback)
|
||||
X(base_idx) = addr;
|
||||
} else {
|
||||
|
@ -465,7 +462,7 @@ void IntprCallback::StoreRegImm64(unsigned int rd_idx, unsigned int base_idx, ui
|
|||
addr = W(base_idx);
|
||||
else
|
||||
addr = W(base_idx) + offset;
|
||||
_StoreReg (rd_idx, addr, size, extend, false);
|
||||
_StoreReg (rd_idx, addr, size, extend);
|
||||
if (writeback)
|
||||
W(base_idx) = addr;
|
||||
}
|
||||
|
|
|
@ -8,11 +8,24 @@ typedef union {
|
|||
uint64_t x;
|
||||
}reg_t;
|
||||
|
||||
/* NEON & FP register */
|
||||
typedef union {
|
||||
uint8_t b[16];
|
||||
uint16_t h[8];
|
||||
uint32_t s[4];
|
||||
uint64_t d[2];
|
||||
}vreg_t;
|
||||
|
||||
struct ARMv8State {
|
||||
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. */
|
||||
* NOTE: In nsemu, 'PC' register is respresented as x32 internally.
|
||||
*/
|
||||
reg_t gpr[34];
|
||||
|
||||
/* v0 - v31 (128 bit vector register, sometime treated as set of smaller size regs) */
|
||||
vreg_t vreg[32];
|
||||
|
||||
uint32_t nzcv; // flag register
|
||||
};
|
||||
|
||||
|
@ -25,8 +38,14 @@ extern ARMv8State arm_state;
|
|||
#define GPR_DUMMY 33
|
||||
|
||||
#define GPR(r) ARMv8::arm_state.gpr[r]
|
||||
#define VREG(r) ARMv8::arm_state.vreg[r]
|
||||
|
||||
#define X(r) GPR(r).x
|
||||
#define W(r) GPR(r).w[1]
|
||||
#define W(r) GPR(r).w[0]
|
||||
#define D(r) VREG(r).d[0]
|
||||
#define S(r) VREG(r).s[0]
|
||||
#define H(r) VREG(r).h[0]
|
||||
#define B(r) VREG(r).b[0]
|
||||
|
||||
#define LR X(GPR_LR)
|
||||
#define SP X(GPR_SP)
|
||||
|
|
Loading…
Reference in a new issue