diff --git a/common/h/dyn_regs.h b/common/h/dyn_regs.h index 65c9faf7db..9632b67fca 100644 --- a/common/h/dyn_regs.h +++ b/common/h/dyn_regs.h @@ -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 @@ -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"); diff --git a/common/src/dyn_regs.C b/common/src/dyn_regs.C index b148b32625..d0ce3d31a3 100644 --- a/common/src/dyn_regs.C +++ b/common/src/dyn_regs.C @@ -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 @@ -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; diff --git a/dataflowAPI/rose/semantics/Registers.C b/dataflowAPI/rose/semantics/Registers.C index b957dde535..f167de350e 100644 --- a/dataflowAPI/rose/semantics/Registers.C +++ b/dataflowAPI/rose/semantics/Registers.C @@ -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; } diff --git a/external/rose/armv8InstructionEnum.h b/external/rose/armv8InstructionEnum.h index 77b13975b7..83041683e5 100644 --- a/external/rose/armv8InstructionEnum.h +++ b/external/rose/armv8InstructionEnum.h @@ -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