diff --git a/bindings/python/unicorn/arch/arm.py b/bindings/python/unicorn/arch/arm.py index 7ef6fe2c..d694db8a 100644 --- a/bindings/python/unicorn/arch/arm.py +++ b/bindings/python/unicorn/arch/arm.py @@ -10,6 +10,8 @@ from .. import Uc, UcError from .. import arm_const as const from ..unicorn_const import UC_ERR_ARG +from .types import UcReg128 + ARMCPReg = Tuple[int, int, int, int, int, int, int] ARMCPRegValue = Tuple[int, int, int, int, int, int, int, int] @@ -43,17 +45,45 @@ class UcAArch32(Uc): """Unicorn subclass for ARM architecture. """ - def reg_read(self, reg_id: int, aux: Any = None): - if reg_id == const.UC_ARM_REG_CP_REG: - return self._reg_read(reg_id, UcRegCP, *aux) + REG_RANGE_Q = range(const.UC_ARM_REG_Q0, const.UC_ARM_REG_Q15 + 1) - # fallback to default reading method - return super().reg_read(reg_id, aux) + @staticmethod + def __select_reg_class(reg_id: int): + """Select class for special architectural registers. + """ + + reg_class = ( + (UcAArch32.REG_RANGE_Q, UcReg128), + ) + + return next((cls for rng, cls in reg_class if reg_id in rng), None) + + + def reg_read(self, reg_id: int, aux: Any = None): + # select register class for special cases + reg_cls = UcAArch32.__select_reg_class(reg_id) + + if reg_cls is None: + if reg_id == const.UC_ARM_REG_CP_REG: + return self._reg_read(reg_id, UcRegCP, *aux) + + else: + # fallback to default reading method + return super().reg_read(reg_id, aux) + + return self._reg_read(reg_id, reg_cls) def reg_write(self, reg_id: int, value) -> None: - if reg_id == const.UC_ARM_REG_CP_REG: - self._reg_write(reg_id, UcRegCP, value) - return + # select register class for special cases + reg_cls = UcAArch32.__select_reg_class(reg_id) - # fallback to default writing method - super().reg_write(reg_id, value) + if reg_cls is None: + if reg_id == const.UC_ARM_REG_CP_REG: + self._reg_write(reg_id, UcRegCP, value) + + else: + # fallback to default writing method + super().reg_write(reg_id, value) + + else: + self._reg_write(reg_id, reg_cls, value)