Skip to content

Commit

Permalink
Fixes to correctly handle aliases in the conditional select instructi…
Browse files Browse the repository at this point in the history
…on category.

This includes changes to the instruction and decoder tables: all instructions in this category map to either CSINC, CSINV, CSNEG or CSEL and the correct alias is applied when handling one of these instructions. One or more of the source registers may need to be skipped for processing when the alias is applied, and the condition code should accordingly be modified.
  • Loading branch information
ssunny7 committed May 20, 2016
1 parent ee0d48c commit 9a2f15b
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 19 deletions.
78 changes: 69 additions & 9 deletions instructionAPI/src/InstructionDecoder-aarch64.C
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ namespace Dyninst {
aarch64_op_sbfx_sbfm, "sbfx")(aarch64_op_ubfiz_ubfm, "ubfiz")(aarch64_op_ubfx_ubfm, "ubfx")(
aarch64_op_sxtb_sbfm, "sxtb")(aarch64_op_sxth_sbfm, "sxth")(aarch64_op_sxtw_sbfm, "sxtw")(
aarch64_op_uxtb_ubfm, "uxtb")(aarch64_op_uxth_ubfm, "uxth")(aarch64_op_lsl_ubfm, "lsl")(aarch64_op_lsr_ubfm, "lsr");
std::map<entryID, std::string> InstructionDecoder_aarch64::condInsnAliasMap = boost::assign::map_list_of(aarch64_op_csinc, "csinc")(aarch64_op_csinv, "csinv")(aarch64_op_csneg, "csneg")
(aarch64_op_cinc_csinc, "cinc")(aarch64_op_cset_csinc, "cset")
(aarch64_op_cinv_csinv, "cinv")(aarch64_op_csetm_csinv, "csetm")
(aarch64_op_cneg_csneg, "cneg");

struct aarch64_insn_entry {
aarch64_insn_entry(entryID o, const char *m, operandSpec ops) :
Expand Down Expand Up @@ -135,7 +139,7 @@ namespace Dyninst {

InstructionDecoder_aarch64::InstructionDecoder_aarch64(Architecture a)
: InstructionDecoderImpl(a), isPstateRead(false), isPstateWritten(false), isFPInsn(false),
isSIMDInsn(false),
isSIMDInsn(false), skipRn(false), skipRm(false),
is64Bit(true), isValid(true), insn(0), insn_in_progress(NULL),
hasHw(false), hasShift(false), hasOption(false), hasN(false),
immr(0), immrLen(0), sField(0), nField(0), nLen(0),
Expand Down Expand Up @@ -167,6 +171,7 @@ namespace Dyninst {
isPstateRead = isPstateWritten = false;
isFPInsn = false;
isSIMDInsn = false;
skipRm = skipRn = false;
isValid = true;
is64Bit = true;

Expand Down Expand Up @@ -1664,6 +1669,9 @@ Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){

// This function is for non-writeback
void InstructionDecoder_aarch64::OPRRn() {
if(skipRn)
return;

if (IS_INSN_B_UNCOND_REG(insn)) //unconditional branch (register)
{
int branchType = field<21, 22>(insn);
Expand Down Expand Up @@ -1827,11 +1835,8 @@ Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){
}

void InstructionDecoder_aarch64::OPRRm() {
if (IS_INSN_LDST_REG(insn) ||
IS_INSN_ADDSUB_EXT(insn) ||
IS_INSN_ADDSUB_SHIFT(insn) ||
IS_INSN_LOGICAL_SHIFT(insn))
return;
if(skipRm)
return;

if (IS_INSN_FP_COMPARE(insn) && field<3, 3>(insn) == 1)
insn_in_progress->appendOperand(
Expand Down Expand Up @@ -2146,15 +2151,19 @@ Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){

template<unsigned int endBit, unsigned int startBit>
void InstructionDecoder_aarch64::OPRcond() {
unsigned char condVal = static_cast<unsigned char>(field<startBit, endBit>(insn));
int condVal = field<startBit, endBit>(insn);
if (IS_INSN_B_COND(insn)) {
insn_in_progress->getOperation().mnemonic += ".";
insn_in_progress->getOperation().mnemonic += condStringMap[condVal];
}
else {
if(IS_INSN_COND_SELECT(insn))
fix_condinsn_alias_and_cond(condVal);
else
oprRotateAmt++;

Expression::Ptr cond = Immediate::makeImmediate(Result(u8, condVal));
insn_in_progress->appendOperand(cond, true, false);
oprRotateAmt++;
}

isPstateRead = true;
Expand Down Expand Up @@ -2405,6 +2414,50 @@ Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){
return do_further_processing;
}

void InstructionDecoder_aarch64::fix_condinsn_alias_and_cond(int &cond) {
entryID modifiedID = insn_in_progress->getOperation().operationID;
if (modifiedID == aarch64_op_csel)
return;

int Rm = field<16, 20>(insn), Rn = field<5, 9>(insn);

if (Rm == Rn && (cond & 0xE) != 0xE && modifiedID == aarch64_op_csneg) {
modifiedID = aarch64_op_cneg_csneg;
skipRm = true;
} else if (Rm != 31 && Rn != 31 && (cond & 0xE) != 0xE && Rm == Rn) {
switch (modifiedID) {
case aarch64_op_csinc:
modifiedID = aarch64_op_cinc_csinc;
break;
case aarch64_op_csinv:
modifiedID = aarch64_op_cinv_csinv;
break;
default:
isValid = false;
}

skipRm = true;
} else if (Rm == 31 && Rn == 31 && (cond & 0xE) != 0xE) {
switch (modifiedID) {
case aarch64_op_csinc:
modifiedID = aarch64_op_cset_csinc;
break;
case aarch64_op_csinv:
modifiedID = aarch64_op_csetm_csinv;
break;
default:
isValid = false;
}

skipRn = skipRm = true;
}

insn_in_progress->getOperation().operationID = modifiedID;
insn_in_progress->getOperation().mnemonic = condInsnAliasMap[modifiedID];
if(skipRm)
cond = ((cond % 2) == 0) ? (cond + 1) : (cond - 1);
}

template<unsigned int endBit, unsigned int startBit>
void InstructionDecoder_aarch64::OPRimm() {
int immVal = field<startBit, endBit>(insn);
Expand Down Expand Up @@ -2749,7 +2802,14 @@ Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){

insn = insn_to_complete->m_RawInsn.small_insn;
insn_in_progress = const_cast<Instruction *>(insn_to_complete);
for (operandSpec::const_iterator fn = insn_table_entry->operands.begin();

if (IS_INSN_LDST_REG(insn) ||
IS_INSN_ADDSUB_EXT(insn) ||
IS_INSN_ADDSUB_SHIFT(insn) ||
IS_INSN_LOGICAL_SHIFT(insn))
skipRm = true;

for (operandSpec::const_iterator fn = insn_table_entry->operands.begin();
fn != insn_table_entry->operands.end(); fn++) {
std::mem_fun(*fn)(this);
}
Expand Down
4 changes: 4 additions & 0 deletions instructionAPI/src/InstructionDecoder-aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ namespace Dyninst {
static std::vector<std::string> condStringMap;
static std::map<unsigned int, MachRegister> sysRegMap;
static std::map<entryID, std::string> bitfieldInsnAliasMap;
static std::map<entryID, std::string> condInsnAliasMap;

#define IS_INSN_LOGICAL_SHIFT(I) (field<24, 28>(I) == 0x0A)
#define IS_INSN_ADDSUB_EXT(I) (field<24, 28>(I) == 0x0B && field<21, 21>(I) == 1)
Expand Down Expand Up @@ -114,6 +115,7 @@ namespace Dyninst {
#define IS_INSN_B_UNCOND(I) (field<26, 30>(I) == 0x05)
#define IS_INSN_B_UNCOND_REG(I) (field<25, 31>(I) == 0x6B)
#define IS_INSN_B_COMPARE(I) (field<25, 30>(I) == 0x1A)
#define IS_INSN_COND_SELECT(I) (field<21, 28>(I) == 0xD4)
#define IS_INSN_B_TEST(I) (field<25, 30>(I) == 0x1B)
#define IS_INSN_B_COND(I) (field<25, 31>(I) == 0x2A)
#define IS_INSN_PCREL_ADDR(I) (field<24, 28>(I) == 0x10)
Expand Down Expand Up @@ -147,6 +149,7 @@ namespace Dyninst {
bool isPstateRead, isPstateWritten;
bool isFPInsn, isSIMDInsn;
bool is64Bit;
bool skipRn, skipRm;
bool isValid;

void mainDecode();
Expand Down Expand Up @@ -265,6 +268,7 @@ namespace Dyninst {
bool isSinglePrec();

bool fix_bitfieldinsn_alias(int, int);
void fix_condinsn_alias_and_cond(int &);

MachRegister makeAarch64RegID(MachRegister, unsigned int);

Expand Down
20 changes: 10 additions & 10 deletions instructionAPI/src/aarch64_opcode_tables.C
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ void aarch64_insn_entry::buildInsnTable()
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_ccmn_reg, "ccmn", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRnzcv) ), 977272832, 2145389584) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_ccmp_imm, "ccmp", list_of( fn(OPRsf) )( fn(OPRimm<20 COMMA 16>) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRnzcv) ), 2051016704, 2145389584) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_ccmp_reg, "ccmp", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRnzcv) ), 2051014656, 2145389584) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cinc_csinc, "cinc", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 444597248, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cinv_csinv, "cinv", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 1518338048, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cinc_csinc, "cinc", list_of( fn(OPRsf) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 444597248, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cinv_csinv, "cinv", list_of( fn(OPRsf) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 1518338048, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_clrex, "clrex", list_of( fn(OPRCRm) ), 3573755999, 4294963455) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cls_advsimd, "cls", list_of( fn(setSIMDMode) )( fn(OPRQ) )( fn(OPRsize<23 COMMA 22>) )( fn(OPRRn) )( fn(OPRRd) ), 236996608, 3208641536) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cls_int, "cls", list_of( fn(OPRsf) )( fn(OPRRn) )( fn(OPRRd) ), 1522537472, 2147482624) );
Expand Down Expand Up @@ -130,16 +130,16 @@ void aarch64_insn_entry::buildInsnTable()
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cmp_subs_addsub_shift, "cmp", list_of( fn(setFlags) )( fn(OPRsf) )( fn(OPRshift) )( fn(OPRRm) )( fn(OPRimm<15 COMMA 10>) )( fn(OPRRn) ), 1795162143, 2132803615) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cmtst_advsimd, "cmtst", list_of( fn(setSIMDMode) )( fn(OPRsize<23 COMMA 22>) )( fn(OPRRm) )( fn(OPRRn) )( fn(OPRRd) ), 1579191296, 4280351744) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cmtst_advsimd, "cmtst", list_of( fn(setSIMDMode) )( fn(OPRQ) )( fn(OPRsize<23 COMMA 22>) )( fn(OPRRm) )( fn(OPRRn) )( fn(OPRRd) ), 237014016, 3206609920) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cneg_csneg, "cneg", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 1518339072, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cneg_csneg, "cneg", list_of( fn(OPRsf) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 1518339072, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cnt_advsimd, "cnt", list_of( fn(setSIMDMode) )( fn(OPRQ) )( fn(OPRsize<23 COMMA 22>) )( fn(OPRRn) )( fn(OPRRd) ), 237000704, 3208641536) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_crc32, "crc32", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRsz<11 COMMA 10>) )( fn(OPRRn) )( fn(OPRRd) ), 448806912, 2145447936) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_crc32c, "crc32c", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRsz<11 COMMA 10>) )( fn(OPRRn) )( fn(OPRRd) ), 448811008, 2145447936) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_csel, "csel", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 444596224, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_csel, "csel", list_of( fn(OPRsf) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRm) )( fn(OPRRn) )( fn(OPRRd) ), 444596224, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_cset_csinc, "cset", list_of( fn(OPRsf) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRd) ), 446629856, 2147422176) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_csetm_csinv, "csetm", list_of( fn(OPRsf) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRd) ), 1520370656, 2147422176) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_csinc, "csinc", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 444597248, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_csinv, "csinv", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 1518338048, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_csneg, "csneg", list_of( fn(OPRsf) )( fn(OPRRm) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRn) )( fn(OPRRd) ), 1518339072, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_csinc, "csinc", list_of( fn(OPRsf) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRm) )( fn(OPRRn) )( fn(OPRRd) ), 444597248, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_csinv, "csinv", list_of( fn(OPRsf) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRm) )( fn(OPRRn) )( fn(OPRRd) ), 1518338048, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_csneg, "csneg", list_of( fn(OPRsf) )( fn(OPRcond<15 COMMA 12>) )( fn(OPRRm) )( fn(OPRRn) )( fn(OPRRd) ), 1518339072, 2145389568) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_dc_sys, "dc", list_of( fn(OPRop1) )( fn(OPRCRm) )( fn(OPRop2) )( fn(OPRRt) ), 3574099968, 4294504448) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_dcps1, "dcps1", list_of( (operandFactory) fn(OPRimm<20 COMMA 5>) ), 3567255553, 4292870175) );
main_insn_table.push_back(aarch64_insn_entry(aarch64_op_dcps2, "dcps2", list_of( (operandFactory) fn(OPRimm<20 COMMA 5>) ), 3567255554, 4292870175) );
Expand Down Expand Up @@ -1306,7 +1306,7 @@ void aarch64_mask_entry::buildDecoderTable()
main_decoder_table[511]=aarch64_mask_entry(0x0, branchMap(),3);
main_decoder_table[512]=aarch64_mask_entry(0xc00, map_list_of(0,517)(1,518),-1);
main_decoder_table[517]=aarch64_mask_entry(0x0, branchMap(),93);
main_decoder_table[518]=aarch64_mask_entry(0x0, branchMap(),54);
main_decoder_table[518]=aarch64_mask_entry(0x0, branchMap(),96);
main_decoder_table[513]=aarch64_mask_entry(0xf000, map_list_of(0,519)(2,520)(4,521)(5,522),-1);
main_decoder_table[519]=aarch64_mask_entry(0xc00, map_list_of(2,523)(3,524),-1);
main_decoder_table[523]=aarch64_mask_entry(0x0, branchMap(),661);
Expand All @@ -1321,8 +1321,8 @@ void aarch64_mask_entry::buildDecoderTable()
main_decoder_table[514]=aarch64_mask_entry(0xfc00, map_list_of(0,529),-1);
main_decoder_table[529]=aarch64_mask_entry(0x0, branchMap(),441);
main_decoder_table[515]=aarch64_mask_entry(0xc00, map_list_of(0,530)(1,531),-1);
main_decoder_table[530]=aarch64_mask_entry(0x0, branchMap(),55);
main_decoder_table[531]=aarch64_mask_entry(0x0, branchMap(),89);
main_decoder_table[530]=aarch64_mask_entry(0x0, branchMap(),97);
main_decoder_table[531]=aarch64_mask_entry(0x0, branchMap(),98);
main_decoder_table[516]=aarch64_mask_entry(0x1ff800, map_list_of(0,532)(1,533)(2,534),-1);
main_decoder_table[532]=aarch64_mask_entry(0x400, map_list_of(0,535)(1,536),-1);
main_decoder_table[535]=aarch64_mask_entry(0x0, branchMap(),419);
Expand Down

0 comments on commit 9a2f15b

Please sign in to comment.