mirror of
https://github.com/RKX1209/nsemu.git
synced 2024-06-23 14:43:16 -04:00
Add support of bit extract operations
This commit is contained in:
parent
3a7d4cb8c3
commit
2507c00b96
|
@ -151,7 +151,7 @@ static void DisasMovwImm(uint32_t insn, DisasCallback *cb) {
|
|||
cb->MoviI64 (rd, imm, is_64bit);
|
||||
break;
|
||||
case 3: /* MOVK */
|
||||
cb->DepositiI64 (rd, pos, imm, is_64bit);
|
||||
cb->DepositI64 (rd, imm, pos, 16, is_64bit);
|
||||
break;
|
||||
default:
|
||||
UnallocatedOp (insn);
|
||||
|
@ -176,7 +176,7 @@ static void DisasBitfield(uint32_t insn, DisasCallback *cb) {
|
|||
|
||||
/* Recognize simple(r) extractions. */
|
||||
if (si >= ri) {
|
||||
/* Wd<s-r:0> = Wn<s:r> */
|
||||
/* Xd<0:r> = Xn<(s-r+1):s> */
|
||||
len = (si - ri) + 1;
|
||||
if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
|
||||
cb->SExtractI64(rd, rn, ri, len, is_64bit);
|
||||
|
@ -188,7 +188,7 @@ static void DisasBitfield(uint32_t insn, DisasCallback *cb) {
|
|||
pos = 0;
|
||||
} else {
|
||||
/* Handle the ri > si case with a deposit
|
||||
* Wd<32+s-r,32-r> = Wn<s:0>
|
||||
* Xd<64-r:64-r+s> = Xn<0:s>
|
||||
*/
|
||||
len = si + 1;
|
||||
pos = (bitsize - ri) & (bitsize - 1);
|
||||
|
@ -203,15 +203,14 @@ static void DisasBitfield(uint32_t insn, DisasCallback *cb) {
|
|||
}
|
||||
|
||||
if (opc == 1) { /* BFM, BXFIL */
|
||||
//TODO: deposit
|
||||
UnsupportedOp ("BFM/BXFIL");
|
||||
cb->DepositReg (rd, rd, pos, len, is_64bit);
|
||||
//UnsupportedOp ("BFM/BXFIL");
|
||||
} else {
|
||||
/* SBFM or UBFM: We start with zero, and we haven't modified
|
||||
any bits outside bitsize, therefore the zero-extension
|
||||
below is unneeded. */
|
||||
//TODO: ???
|
||||
//tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
|
||||
UnsupportedOp ("SBFM/UBFM");
|
||||
cb->DepositZeroReg (rd, rd, pos, len, is_64bit);
|
||||
//UnsupportedOp ("SBFM/UBFM");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -167,15 +167,34 @@ void IntprCallback::MoviI64(unsigned int reg_idx, uint64_t imm, bool bit64) {
|
|||
X(reg_idx) = imm;
|
||||
}
|
||||
|
||||
void IntprCallback::DepositiI64(unsigned int reg_idx, unsigned int pos, uint64_t imm, bool bit64) {
|
||||
void IntprCallback::DepositI64(unsigned int rd_idx, uint64_t imm, unsigned int pos, unsigned int len, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("MOVK: %c[%u] = 0x%lx\n", regc, reg_idx, imm << pos);
|
||||
uint32_t mask = (1 << 16) - 1; //XXX: hard coded bit size: 16
|
||||
debug_print ("MOVK: %c[%u] = 0x%lx\n", regc, rd_idx, imm << pos);
|
||||
uint32_t mask = (1 << len) - 1; //XXX: hard coded bit size: 16
|
||||
X(rd_idx) = (X(rd_idx) & ~(mask << pos)) | (imm << pos);
|
||||
}
|
||||
|
||||
void IntprCallback::DepositReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) {
|
||||
if (bit64) {
|
||||
X(reg_idx) = (X(reg_idx) & ~(mask << pos)) | (imm << pos);
|
||||
DepositI64 (rd_idx, X(rn_idx), pos, len, bit64);
|
||||
}
|
||||
else {
|
||||
X(reg_idx) = (W(reg_idx) & ~(mask << pos)) | (imm << pos);
|
||||
DepositI64 (rd_idx, W(rn_idx), pos, len, bit64);
|
||||
}
|
||||
}
|
||||
|
||||
void IntprCallback::DepositZeroI64(unsigned int rd_idx, uint64_t imm, unsigned int pos, unsigned int len, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
//debug_print ("MOVK: %c[%u] = 0x%lx\n", regc, rd_idx, imm << pos);
|
||||
X(rd_idx) = (imm & ((1ULL << len) - 1)) << pos;
|
||||
}
|
||||
|
||||
void IntprCallback::DepositZeroReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) {
|
||||
if (bit64) {
|
||||
DepositZeroI64 (rd_idx, X(rn_idx), pos, len, bit64);
|
||||
}
|
||||
else {
|
||||
DepositZeroI64 (rd_idx, W(rn_idx), pos, len, bit64);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,11 +490,26 @@ void IntprCallback::StoreRegI64(unsigned int rd_idx, unsigned int base_idx, uint
|
|||
}
|
||||
|
||||
/* Bitfield Signed/Unsigned Extract... with Immediate value */
|
||||
/* X(d)<> = X(n)<off:64> */
|
||||
void IntprCallback::SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) {
|
||||
/* TODO: */
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("SExtract: %c[%u] <= SEXT[%c[%u]: %u, %u]\n", regc, rd_idx, regc, rn_idx, pos, len);
|
||||
if (pos + len == 64) {
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_ASR, 64 - len, bit64);
|
||||
return;
|
||||
}
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_LSL, 64 - len - pos, bit64);
|
||||
ShiftI64 (rd_idx, rd_idx, AL_TYPE_ASR, 64 - len, bit64);
|
||||
}
|
||||
void IntprCallback::UExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) {
|
||||
/* TODO: */
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("UExtract: %c[%u] <= SEXT[%c[%u]: %u, %u]\n", regc, rd_idx, regc, rn_idx, pos, len);
|
||||
if (pos + len == 64) {
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_LSR, 64 - len, bit64);
|
||||
return;
|
||||
}
|
||||
ShiftI64 (rd_idx, rn_idx, AL_TYPE_LSL, 64 - len - pos, bit64);
|
||||
ShiftI64 (rd_idx, rd_idx, AL_TYPE_LSR, 64 - len, bit64);
|
||||
}
|
||||
|
||||
/* Reverse bit order */
|
||||
|
|
|
@ -7,7 +7,10 @@ public:
|
|||
virtual void MoviI64(unsigned int reg_idx, uint64_t imm, bool bit64) = 0;
|
||||
|
||||
/* Deposit (i.e. distination register won't be changed) with Immediate value */
|
||||
virtual void DepositiI64(unsigned int reg_idx, unsigned int pos, uint64_t imm, bool bit64) = 0;
|
||||
virtual void DepositI64(unsigned int rd_idx, uint64_t imm, unsigned int pos, unsigned int len, bool bit64) = 0;
|
||||
virtual void DepositReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) = 0;
|
||||
virtual void DepositZeroI64(unsigned int rd_idx, uint64_t imm, unsigned int pos, unsigned int len, bool bit64) = 0;
|
||||
virtual void DepositZeroReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) = 0;
|
||||
|
||||
/* Mov between registers */
|
||||
virtual void MovReg(unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0;
|
||||
|
|
|
@ -7,7 +7,10 @@ public:
|
|||
void MoviI64(unsigned int reg_idx, uint64_t imm, bool bit64);
|
||||
|
||||
/* Deposit (i.e. distination register won't be changed) with Immediate value */
|
||||
void DepositiI64(unsigned int reg_idx, unsigned int pos, uint64_t imm, bool bit64);
|
||||
void DepositI64(unsigned int reg_idx, uint64_t imm, unsigned int pos, unsigned int len, bool bit64);
|
||||
void DepositReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64);
|
||||
void DepositZeroI64(unsigned int reg_idx, uint64_t imm, unsigned int pos, unsigned int len, bool bit64);
|
||||
void DepositZeroReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64);
|
||||
|
||||
/* Mov between registers */
|
||||
void MovReg(unsigned int rd_idx, unsigned int rn_idx, bool bit64);
|
||||
|
|
Loading…
Reference in a new issue