Skip to content

Commit

Permalink
Register definitions for treating the 4 ARM64 flags separately
Browse files Browse the repository at this point in the history
As with dataflow analysis on other architectures, each flag should be treated as a distinct unit. Following changes, made as part of this commit, achieve this:
- n, z, c and v have been added as individual register definitions in dyn_regs with their baseIDs indicating their positions in the pstate register. The conversions from Dyninst to ROSE registers for these new additions are also defined.
- The 'nzcv' enum value in ARMv8PstateFields (for use in ARM semantics) is split into 4 different values, one for each flag. Each of these is also added to the register dictionary for ARMv8 in Registers.C.
  • Loading branch information
ssunny7 committed Sep 23, 2016
1 parent 49e7cd9 commit ae8875e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 37 deletions.
11 changes: 11 additions & 0 deletions common/h/dyn_regs.h
Expand Up @@ -1074,10 +1074,12 @@ namespace Dyninst
//arch reg cat:GPR alias&subrange reg ID
const signed int GPR = 0x00010000;
const signed int FPR = 0x00020000;
const signed int FLAG = 0x00030000;
const signed int FSR = 0x00040000;
const signed int SPR = 0x00080000;
const signed int SYSREG = 0x00100000;

const signed int BIT = 0x00008000;
const signed int B_REG = 0x00000100; //8bit byte reg
const signed int W_REG = 0x00000300; //16bit half-wor reg
const signed int D_REG = 0x00000f00; //32bit single-word reg
Expand Down Expand Up @@ -1366,10 +1368,19 @@ namespace Dyninst

//special registers
//PC is not writable in aarch64
const signed int N_FLAG = 31;
const signed int Z_FLAG = 30;
const signed int C_FLAG = 29;
const signed int V_FLAG = 28;

DEF_REGISTER(sp, 0 | FULL |SPR | Arch_aarch64, "aarch64");
DEF_REGISTER(wsp, 0 | D_REG |SPR | Arch_aarch64, "aarch64");
DEF_REGISTER(pc, 1 | FULL |SPR | Arch_aarch64, "aarch64");
DEF_REGISTER(pstate, 2 | D_REG |SPR | Arch_aarch64, "aarch64");
DEF_REGISTER(n, N_FLAG | BIT |FLAG| Arch_aarch64, "aarch64");
DEF_REGISTER(z, Z_FLAG | BIT |FLAG| Arch_aarch64, "aarch64");
DEF_REGISTER(c, C_FLAG | BIT |FLAG| Arch_aarch64, "aarch64");
DEF_REGISTER(v, V_FLAG | BIT |FLAG| Arch_aarch64, "aarch64");
DEF_REGISTER(zr, 3 | FULL |SPR | Arch_aarch64, "aarch64");
DEF_REGISTER(wzr, 3 | D_REG |SPR | Arch_aarch64, "aarch64");
DEF_REGISTER(fpcr, 4 | D_REG |SPR | Arch_aarch64, "aarch64");
Expand Down
86 changes: 55 additions & 31 deletions common/src/dyn_regs.C
Expand Up @@ -202,11 +202,13 @@ unsigned int MachRegister::size() const {
return 0;
}
}
else if((reg & 0x00ff0000) == aarch64::GPR || (reg & 0x00ff0000) == aarch64::SPR || (reg & 0x00ff0000) == aarch64::SYSREG)
else if((reg & 0x00ff0000) == aarch64::GPR || (reg & 0x00ff0000) == aarch64::SPR ||
(reg & 0x00ff0000) == aarch64::SYSREG || (reg & 0x00ff0000) == aarch64::FLAG)
switch(reg & 0x0000ff00)
{
case aarch64::FULL : return 8;
case aarch64::D_REG: return 4;
case aarch64::BIT: return 0;
default: return 0;
}
else
Expand Down Expand Up @@ -808,36 +810,58 @@ void MachRegister::getROSERegister(int &c, int &n, int &p)
return;
}
break;
case Arch_aarch64:
{
switch(category) {
case aarch64::GPR: {
c = armv8_regclass_gpr;
if(baseID == (aarch64::zr & 0xFF) || baseID == (aarch64::wzr & 0xFF))
n = armv8_gpr_zr;
else {
int regnum = baseID - (aarch64::x0 & 0xFF);
n = armv8_gpr_r0 + regnum;
}
}
break;
case aarch64::SPR: {
n = 0;
if(baseID == (aarch64::pstate & 0xFF)) {
c = armv8_regclass_pstate;
p = armv8_pstatefield_nzcv;
} else if(baseID == (aarch64::pc & 0xFF)) {
c = armv8_regclass_pc;
} else if(baseID == (aarch64::sp & 0xFF) || baseID == (aarch64::wsp & 0xFF)) {
c = armv8_regclass_sp;
}
}
break;
default:assert(!"unknown register type!");
break;
}
return;
}
case Arch_aarch64: {
p = 0;
switch (category) {
case aarch64::GPR: {
c = armv8_regclass_gpr;
if (baseID == (aarch64::zr & 0xFF) || baseID == (aarch64::wzr & 0xFF))
n = armv8_gpr_zr;
else {
int regnum = baseID - (aarch64::x0 & 0xFF);
n = armv8_gpr_r0 + regnum;
}
}
break;
case aarch64::SPR: {
n = 0;
if (baseID == (aarch64::pstate & 0xFF)) {
c = armv8_regclass_pstate;
} else if (baseID == (aarch64::pc & 0xFF)) {
c = armv8_regclass_pc;
} else if (baseID == (aarch64::sp & 0xFF) || baseID == (aarch64::wsp & 0xFF)) {
c = armv8_regclass_sp;
}
}
break;
case aarch64::FLAG: {
c = armv8_regclass_pstate;
n = 0;
switch (baseID) {
case aarch64::N_FLAG:
p = armv8_pstatefield_n;
break;
case aarch64::Z_FLAG:
p = armv8_pstatefield_z;
break;
case aarch64::V_FLAG:
p = armv8_pstatefield_v;
break;
case aarch64::C_FLAG:
p = armv8_pstatefield_c;
break;
default:
assert(!"unknown flag type!");
break;
}
}
break;
default:
assert(!"unknown register type!");
break;
}
return;
}
break;
default:
c = x86_regclass_unknown;
Expand Down
10 changes: 7 additions & 3 deletions dataflowAPI/rose/semantics/Registers.C
Expand Up @@ -665,10 +665,14 @@ RegisterDictionary::dictionary_armv8() {
/* 64-bit program counter register */
regs->insert("pc", armv8_regclass_pc, 0, 0, 64);

/* 32-bit pstate register and the four relevant flags.
* Only allowed minor is 0, but different fields (for now, this is only nzcv) are different in the ARMv8_PstateFields enum. */
/* 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("nzcv", armv8_regclass_pstate, 0, armv8_pstatefield_nzcv, 4);
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
8 changes: 5 additions & 3 deletions external/rose/armv8InstructionEnum.h
Expand Up @@ -53,9 +53,11 @@ enum ARMv8GeneralPurposeRegister {
/** ARMv8-A fields of the Pstate register */
enum ARMv8PstateFields {
armv8_pstatefield_pstate = 0, /* The entire 32-bit pstate register */
armv8_pstatefield_nzcv = 28 /* The upper four bits, representing the
* negative (bit 31), zero (bit 30), carry (bit 29) and overflow (bit 28) flags.
* These are not added are distinct flags because the four bits are almost always accessed together. */
/* Values for each enum member below match the position of the bit in the pstate register */
armv8_pstatefield_n = 31, /* The negative flag */
armv8_pstatefield_z = 30, /* The zero flag */
armv8_pstatefield_c = 29, /* The carry flag */
armv8_pstatefield_v = 28 /* The overflow flag */
};

/** ARMv8-A instructions for the AArch64 processor mode
Expand Down

0 comments on commit ae8875e

Please sign in to comment.