Add support of bit extract operations

This commit is contained in:
rkx1209 2018-03-11 23:19:31 +09:00
parent 3a7d4cb8c3
commit 2507c00b96
4 changed files with 56 additions and 17 deletions

View file

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

View file

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

View file

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

View file

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