Skip to content

Commit

Permalink
Added ability to convert the ARM64 SIMD/FP registers between ROSE(sem…
Browse files Browse the repository at this point in the history
…antics) and Dyninst.

- getROSERegister() supports computing the different values of a
RegisterDescriptor for ARM64 SIMD/FP registers
- RegisterDescriptors for all accessible parts of a SIMD/FP register
(8-bit, 16-bit, 32-bit, upper and lower 64-bit and 128-bit) are added to
the RegisterDictionary for ARM64 in ROSE semantics
- SymEvalSemantics now converts from SIMD/FP registers to
Dyninst::MachRegisters.
  • Loading branch information
ssunny7 committed Oct 6, 2016
1 parent 16295d1 commit e255d6e
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 34 deletions.
24 changes: 24 additions & 0 deletions common/src/dyn_regs.C
Expand Up @@ -870,6 +870,30 @@ void MachRegister::getROSERegister(int &c, int &n, int &p)
}
}
break;
case aarch64::FPR: {
c = armv8_regclass_simd_fpr;

int firstRegId;
switch(reg & 0xFF00) {
case aarch64::Q_REG: firstRegId = (aarch64::q0 & 0xFF);
break;
case aarch64::HQ_REG: firstRegId = (aarch64::hq0 & 0xFF);
p = 64;
break;
case aarch64::FULL: firstRegId = (aarch64::d0 & 0xFF);
break;
case aarch64::D_REG: firstRegId = (aarch64::s0 & 0xFF);
break;
case aarch64::W_REG: firstRegId = (aarch64::h0 & 0xFF);
break;
case aarch64::B_REG: firstRegId = (aarch64::b0 & 0xFF);
break;
default:assert(!"invalid register subcategory for ARM64!");
break;
}
n = armv8_simdfpr_v0 + (baseID - firstRegId);
}
break;
case aarch64::FLAG: {
c = armv8_regclass_pstate;
n = 0;
Expand Down
69 changes: 48 additions & 21 deletions dataflowAPI/rose/semantics/Registers.C
Expand Up @@ -648,31 +648,58 @@ RegisterDictionary::print(std::ostream &o) const {
const RegisterDictionary *
RegisterDictionary::dictionary_armv8() {
static RegisterDictionary *regs = NULL;
if(!regs) {
if (!regs) {
regs = new RegisterDictionary("armv8");

/* All 60 variations (32- and 64-bit) of the 32 general purpose registers */
for(unsigned idx = 0; idx < 31; idx++) {
regs->insert("x"+StringUtility::numberToString(idx), armv8_regclass_gpr, armv8_gpr_r0 + idx, 0, 64);
regs->insert("w"+StringUtility::numberToString(idx), armv8_regclass_gpr, armv8_gpr_r0 + idx, 0, 32);
/* All 60 variations (32- and 64-bit) of the 32 general purpose registers */
for (unsigned idx = 0; idx < 31; idx++) {
regs->insert("x" + StringUtility::numberToString(idx), armv8_regclass_gpr, armv8_gpr_r0 + idx, 0, 64);
regs->insert("w" + StringUtility::numberToString(idx), armv8_regclass_gpr, armv8_gpr_r0 + idx, 0, 32);
}

/* 32-bit section of the stack pointer register */
regs->insert("wsp", armv8_regclass_sp, 0, 0, 32);
/* Complete stack pointer regiser */
regs->insert("sp", armv8_regclass_sp, 0, 0, 64);

/* 64-bit program counter register */
regs->insert("pc", armv8_regclass_pc, 0, 0, 64);

/* 32-bit pstate register and the four relevant flags.*/
/* Each flag is added as a separate register for individual access. Only allowed minor is 0 (since there is only one pstate register);
* the different offsets indicate the positions of the flags within the pstate register. */
regs->insert("pstate", armv8_regclass_pstate, 0, armv8_pstatefield_pstate, 32);
regs->insert("n", armv8_regclass_pstate, 0, armv8_pstatefield_n, 1);
regs->insert("z", armv8_regclass_pstate, 0, armv8_pstatefield_z, 1);
regs->insert("c", armv8_regclass_pstate, 0, armv8_pstatefield_c, 1);
regs->insert("v", armv8_regclass_pstate, 0, armv8_pstatefield_v, 1);
/* We have 32 SIMD/FP registers V0 - V31. In ARMv8-A, all of these are 128 bits wide.
* Not considering those instructions that treat each of these registers as an array of fixed-length units,
* each SIMD/FP register is divided can be accessed as the following:
* - A 128-bit register (Q0 - Q31)
* - A 64-bit register with its LSB being bit 0 of the register (D0 - D31)
* - A 64-bit register with its LDB being bit 64 of the register (HQ0 - HQ31)
* - A 32-bit register (S0 - S31)
* - A 16-bit register (H0 - H31)
* - An 8-bit register (B0 - B31) */
for(unsigned idx = 0; idx < 32; idx++) {
/* 128-bit parts of V0 - V31 */
regs->insert("q" + StringUtility::numberToString(idx), armv8_regclass_simd_fpr, armv8_simdfpr_v0 + idx, 0, 128);

/* 64-bit parts of V0 - V31 */
regs->insert("d" + StringUtility::numberToString(idx), armv8_regclass_simd_fpr, armv8_simdfpr_v0 + idx, 0, 64);
regs->insert("hq" + StringUtility::numberToString(idx), armv8_regclass_simd_fpr, armv8_simdfpr_v0 + idx, 64, 64);

/* 32-bit parts of V0 - V31 */
regs->insert("s" + StringUtility::numberToString(idx), armv8_regclass_simd_fpr, armv8_simdfpr_v0 + idx, 0, 32);

/* 16-bit parts of V0 - V31 */
regs->insert("h" + StringUtility::numberToString(idx), armv8_regclass_simd_fpr, armv8_simdfpr_v0 + idx, 0, 16);

/* 8-bit parts of V0 - V31 */
regs->insert("b" + StringUtility::numberToString(idx), armv8_regclass_simd_fpr, armv8_simdfpr_v0 + idx, 0, 8);
}

/* 32-bit section of the stack pointer register */
regs->insert("wsp", armv8_regclass_sp, 0, 0, 32);
/* Complete stack pointer regiser */
regs->insert("sp", armv8_regclass_sp, 0, 0, 64);

/* 64-bit program counter register */
regs->insert("pc", armv8_regclass_pc, 0, 0, 64);

/* 32-bit pstate register and the four relevant flags.*/
/* Each flag is added as a separate register for individual access. Only allowed minor is 0 (since there is only one pstate register);
* the different offsets indicate the positions of the flags within the pstate register. */
regs->insert("pstate", armv8_regclass_pstate, 0, armv8_pstatefield_pstate, 32);
regs->insert("n", armv8_regclass_pstate, 0, armv8_pstatefield_n, 1);
regs->insert("z", armv8_regclass_pstate, 0, armv8_pstatefield_z, 1);
regs->insert("c", armv8_regclass_pstate, 0, armv8_pstatefield_c, 1);
regs->insert("v", armv8_regclass_pstate, 0, armv8_pstatefield_v, 1);
}
return regs;
}
Expand Down
44 changes: 31 additions & 13 deletions dataflowAPI/rose/semantics/SymEvalSemantics.C
Expand Up @@ -53,11 +53,7 @@ void SymEvalSemantics::StateARM64::writeMemory(const BaseSemantics::SValuePtr &a

BaseSemantics::SValuePtr SymEvalSemantics::RegisterStateARM64::readRegister(const RegisterDescriptor &reg,
Dyninst::Address addr) {
if(reg.get_major() != armv8_regclass_simd_fpr) {
return SymEvalSemantics::SValue::instance(wrap(convert(reg), addr));
} else {
ASSERT_not_implemented("readRegister not yet implemented for categories other than GPR");
}
return SymEvalSemantics::SValue::instance(wrap(convert(reg), addr));
}

BaseSemantics::SValuePtr SymEvalSemantics::RegisterStateARM64::readRegister(const RegisterDescriptor &reg,
Expand All @@ -70,14 +66,10 @@ void SymEvalSemantics::RegisterStateARM64::writeRegister(const RegisterDescripto
const BaseSemantics::SValuePtr &value,
Dyninst::DataflowAPI::Result_t &res,
std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap) {
if(reg.get_major() != armv8_regclass_simd_fpr) {
std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(convert(reg));
if (i != aaMap.end()) {
SymEvalSemantics::SValuePtr value_ = SymEvalSemantics::SValue::promote(value);
res[i->second] = value_->get_expression();
}
} else {
ASSERT_not_implemented("writeRegister not yet implemented for categories other than GPR");
std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(convert(reg));
if (i != aaMap.end()) {
SymEvalSemantics::SValuePtr value_ = SymEvalSemantics::SValue::promote(value);
res[i->second] = value_->get_expression();
}
}

Expand Down Expand Up @@ -105,6 +97,32 @@ Dyninst::Absloc SymEvalSemantics::RegisterStateARM64::convert(const RegisterDesc
}
}
break;
case armv8_regclass_simd_fpr: {
Dyninst::MachRegister base;
unsigned int minor = reg.get_minor();

switch(size) {
case 8: base = Dyninst::aarch64::b0;
break;
case 16: base = Dyninst::aarch64::h0;
break;
case 32: base = Dyninst::aarch64::s0;
break;
case 64:
if (reg.get_offset() == 64) {
base = Dyninst::aarch64::hq0;
} else {
base = Dyninst::aarch64::d0;
}
break;
case 128: base = Dyninst::aarch64::q0;
break;
default:assert(!"invalid size of RegisterDescriptor!");
break;
}
mreg = Dyninst::MachRegister(base.val() + (minor - armv8_simdfpr_v0));
}
break;
case armv8_regclass_pc:
mreg = Dyninst::MachRegister(Dyninst::aarch64::pc);
break;
Expand Down
36 changes: 36 additions & 0 deletions external/rose/armv8InstructionEnum.h
Expand Up @@ -50,6 +50,42 @@ enum ARMv8GeneralPurposeRegister {
armv8_gpr_zr
};

/** ARMv8-A SIMD & FP registers */
enum ARMv8SimdFpRegister {
armv8_simdfpr_v0,
armv8_simdfpr_v1,
armv8_simdfpr_v2,
armv8_simdfpr_v3,
armv8_simdfpr_v4,
armv8_simdfpr_v5,
armv8_simdfpr_v6,
armv8_simdfpr_v7,
armv8_simdfpr_v8,
armv8_simdfpr_v9,
armv8_simdfpr_v10,
armv8_simdfpr_v11,
armv8_simdfpr_v12,
armv8_simdfpr_v13,
armv8_simdfpr_v14,
armv8_simdfpr_v15,
armv8_simdfpr_v16,
armv8_simdfpr_v17,
armv8_simdfpr_v18,
armv8_simdfpr_v19,
armv8_simdfpr_v20,
armv8_simdfpr_v21,
armv8_simdfpr_v22,
armv8_simdfpr_v23,
armv8_simdfpr_v24,
armv8_simdfpr_v25,
armv8_simdfpr_v26,
armv8_simdfpr_v27,
armv8_simdfpr_v28,
armv8_simdfpr_v29,
armv8_simdfpr_v30,
armv8_simdfpr_v31
};

/** ARMv8-A fields of the Pstate register */
enum ARMv8PstateFields {
armv8_pstatefield_pstate = 0, /* The entire 32-bit pstate register */
Expand Down

0 comments on commit e255d6e

Please sign in to comment.