diff --git a/src/rust/iced-x86-js/src/tests/register_ext.test.js b/src/rust/iced-x86-js/src/tests/register_ext.test.js index c64f3c54f..0a08fec88 100644 --- a/src/rust/iced-x86-js/src/tests/register_ext.test.js +++ b/src/rust/iced-x86-js/src/tests/register_ext.test.js @@ -139,4 +139,7 @@ test("RegisterExt funcs", () => { expect(RegisterExt.isMM(Register.CL)).toBe(false); expect(RegisterExt.isMM(Register.MM3)).toBe(true); -}); + + expect(RegisterExt.isTMM(Register.CL)).toBe(false); + expect(RegisterExt.isTMM(Register.TMM3)).toBe(true); +}); \ No newline at end of file diff --git a/src/rust/iced-x86-py/docs/index.rst b/src/rust/iced-x86-py/docs/index.rst index a330bc2f7..216944185 100644 --- a/src/rust/iced-x86-py/docs/index.rst +++ b/src/rust/iced-x86-py/docs/index.rst @@ -19,6 +19,8 @@ Welcome to iced-x86's documentation! src/FpuStackIncrementInfo src/MemorySizeExt src/MemorySizeInfo + src/RegisterExt + src/RegisterInfo src/UsedMemory src/UsedRegister :maxdepth: 2 diff --git a/src/rust/iced-x86-py/docs/src/RegisterExt.rst b/src/rust/iced-x86-py/docs/src/RegisterExt.rst new file mode 100644 index 000000000..49cd2512a --- /dev/null +++ b/src/rust/iced-x86-py/docs/src/RegisterExt.rst @@ -0,0 +1,5 @@ +RegisterExt +=========== + +.. autoclass:: iced_x86::RegisterExt + :members: diff --git a/src/rust/iced-x86-py/docs/src/RegisterInfo.rst b/src/rust/iced-x86-py/docs/src/RegisterInfo.rst new file mode 100644 index 000000000..54f50d322 --- /dev/null +++ b/src/rust/iced-x86-py/docs/src/RegisterInfo.rst @@ -0,0 +1,5 @@ +RegisterInfo +============ + +.. autoclass:: iced_x86::RegisterInfo + :members: diff --git a/src/rust/iced-x86-py/src/iced_x86/__init__.py b/src/rust/iced-x86-py/src/iced_x86/__init__.py index 0b6d42fef..c615e1f31 100644 --- a/src/rust/iced-x86-py/src/iced_x86/__init__.py +++ b/src/rust/iced-x86-py/src/iced_x86/__init__.py @@ -30,7 +30,8 @@ iced-x86 is a high performance and correct x86/x64 disassembler, assembler and i from ._iced_x86_py import BlockEncoder, ConstantOffsets, Decoder, Encoder, FastFormatter, \ Formatter, FpuStackIncrementInfo, Instruction, InstructionInfo, \ - InstructionInfoFactory, MemorySizeExt, MemorySizeInfo, OpCodeInfo, UsedMemory, UsedRegister + InstructionInfoFactory, MemorySizeExt, MemorySizeInfo, OpCodeInfo, RegisterExt, RegisterInfo, \ + UsedMemory, UsedRegister from . import CC_a from . import CC_ae @@ -78,7 +79,11 @@ __all__ = [ "Instruction", "InstructionInfo", "InstructionInfoFactory", + "MemorySizeExt", + "MemorySizeInfo", "OpCodeInfo", + "RegisterExt", + "RegisterInfo", "UsedMemory", "UsedRegister", @@ -106,8 +111,6 @@ __all__ = [ "FormatterSyntax", "MandatoryPrefix", "MemorySize", - "MemorySizeExt", - "MemorySizeInfo", "MemorySizeOptions", "Mnemonic", "OpAccess", diff --git a/src/rust/iced-x86-py/src/iced_x86/_iced_x86_py.pyi b/src/rust/iced-x86-py/src/iced_x86/_iced_x86_py.pyi index a063c1006..203c023c9 100644 --- a/src/rust/iced-x86-py/src/iced_x86/_iced_x86_py.pyi +++ b/src/rust/iced-x86-py/src/iced_x86/_iced_x86_py.pyi @@ -1142,3 +1142,70 @@ class MemorySizeExt: def element_count(memory_size: MemorySize) -> int: ... @staticmethod def is_broadcast(memory_size: MemorySize) -> bool: ... + +class RegisterInfo: + def __init__(self, register: Register) -> None: ... + @property + def register(self) -> Register: ... + @property + def base(self) -> Register: ... + @property + def number(self) -> int: ... + @property + def full_register(self) -> Register: ... + @property + def full_register32(self) -> Register: ... + @property + def size(self) -> int: ... + +class RegisterExt: + @staticmethod + def info(register: Register) -> RegisterInfo: ... + @staticmethod + def base(register: Register) -> Register: ... + @staticmethod + def number(register: Register) -> int: ... + @staticmethod + def full_register(register: Register) -> Register: ... + @staticmethod + def full_register32(register: Register) -> Register: ... + @staticmethod + def size(register: Register) -> int: ... + @staticmethod + def is_segment_register(register: Register) -> bool: ... + @staticmethod + def is_gpr(register: Register) -> bool: ... + @staticmethod + def is_gpr8(register: Register) -> bool: ... + @staticmethod + def is_gpr16(register: Register) -> bool: ... + @staticmethod + def is_gpr32(register: Register) -> bool: ... + @staticmethod + def is_gpr64(register: Register) -> bool: ... + @staticmethod + def is_xmm(register: Register) -> bool: ... + @staticmethod + def is_ymm(register: Register) -> bool: ... + @staticmethod + def is_zmm(register: Register) -> bool: ... + @staticmethod + def is_vector_register(register: Register) -> bool: ... + @staticmethod + def is_ip(register: Register) -> bool: ... + @staticmethod + def is_k(register: Register) -> bool: ... + @staticmethod + def is_cr(register: Register) -> bool: ... + @staticmethod + def is_dr(register: Register) -> bool: ... + @staticmethod + def is_tr(register: Register) -> bool: ... + @staticmethod + def is_st(register: Register) -> bool: ... + @staticmethod + def is_bnd(register: Register) -> bool: ... + @staticmethod + def is_mm(register: Register) -> bool: ... + @staticmethod + def is_tmm(register: Register) -> bool: ... diff --git a/src/rust/iced-x86-py/src/lib.rs b/src/rust/iced-x86-py/src/lib.rs index 7ee0db946..9a8ac41ae 100644 --- a/src/rust/iced-x86-py/src/lib.rs +++ b/src/rust/iced-x86-py/src/lib.rs @@ -90,6 +90,8 @@ mod instruction; mod memory_size_ext; mod memory_size_info; mod op_code_info; +mod register_ext; +mod register_info; use block_encoder::BlockEncoder; use constant_offsets::ConstantOffsets; @@ -103,6 +105,8 @@ use memory_size_ext::MemorySizeExt; use memory_size_info::MemorySizeInfo; use op_code_info::OpCodeInfo; use pyo3::prelude::*; +use register_ext::RegisterExt; +use register_info::RegisterInfo; #[pymodule] fn _iced_x86_py(_py: Python, m: &PyModule) -> PyResult<()> { @@ -123,6 +127,8 @@ fn _iced_x86_py(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/src/rust/iced-x86-py/src/register_ext.rs b/src/rust/iced-x86-py/src/register_ext.rs new file mode 100644 index 000000000..d4f905b03 --- /dev/null +++ b/src/rust/iced-x86-py/src/register_ext.rs @@ -0,0 +1,687 @@ +/* +Copyright (C) 2018-2019 de4dot@gmail.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +use crate::enum_utils::to_register; +use crate::register_info::RegisterInfo; +use pyo3::prelude::*; + +#[pyclass(module = "_iced_x86_py")] +#[text_signature = "(/)"] +pub(crate) struct RegisterExt {} + +/// :class:`Register` enum extension methods, see also :class:`RegisterInfo` +#[pymethods] +impl RegisterExt { + /// Gets register info + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// :class:`RegisterInfo`: Register info + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// info = RegisterExt.info(Register.EAX) + /// assert info.size == 4 + #[staticmethod] + #[text_signature = "(register, /)"] + fn info(register: u32) -> PyResult { + Ok(RegisterInfo { info: to_register(register)?.info() }) + } + + /// Gets the base register, eg. ``AL``, ``AX``, ``EAX``, ``RAX``, ``MM0``, ``XMM0``, ``YMM0``, ``ZMM0``, ``ES`` + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// :class:`Register`: Base register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert RegisterExt.base(Register.GS) == Register.ES + /// assert RegisterExt.base(Register.SIL) == Register.AL + /// assert RegisterExt.base(Register.SP) == Register.AX + /// assert RegisterExt.base(Register.R13D) == Register.EAX + /// assert RegisterExt.base(Register.RBP) == Register.RAX + /// assert RegisterExt.base(Register.MM6) == Register.MM0 + /// assert RegisterExt.base(Register.XMM28) == Register.XMM0 + /// assert RegisterExt.base(Register.YMM12) == Register.YMM0 + /// assert RegisterExt.base(Register.ZMM31) == Register.ZMM0 + /// assert RegisterExt.base(Register.K3) == Register.K0 + /// assert RegisterExt.base(Register.BND1) == Register.BND0 + /// assert RegisterExt.base(Register.ST7) == Register.ST0 + /// assert RegisterExt.base(Register.CR8) == Register.CR0 + /// assert RegisterExt.base(Register.DR6) == Register.DR0 + /// assert RegisterExt.base(Register.TR3) == Register.TR0 + /// assert RegisterExt.base(Register.RIP) == Register.EIP + #[staticmethod] + #[text_signature = "(register, /)"] + fn base(register: u32) -> PyResult { + Ok(to_register(register)?.base() as u32) + } + + /// The register number (index) relative to :class:`RegisterExt.base`, eg. 0-15, or 0-31, or if 8-bit GPR, 0-19 + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// int: Register number (index) relative to the base register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert RegisterExt.number(Register.GS) == 5 + /// assert RegisterExt.number(Register.SIL) == 10 + /// assert RegisterExt.number(Register.SP) == 4 + /// assert RegisterExt.number(Register.R13D) == 13 + /// assert RegisterExt.number(Register.RBP) == 5 + /// assert RegisterExt.number(Register.MM6) == 6 + /// assert RegisterExt.number(Register.XMM28) == 28 + /// assert RegisterExt.number(Register.YMM12) == 12 + /// assert RegisterExt.number(Register.ZMM31) == 31 + /// assert RegisterExt.number(Register.K3) == 3 + /// assert RegisterExt.number(Register.BND1) == 1 + /// assert RegisterExt.number(Register.ST7) == 7 + /// assert RegisterExt.number(Register.CR8) == 8 + /// assert RegisterExt.number(Register.DR6) == 6 + /// assert RegisterExt.number(Register.TR3) == 3 + /// assert RegisterExt.number(Register.RIP) == 1 + #[staticmethod] + #[text_signature = "(register, /)"] + fn number(register: u32) -> PyResult { + Ok(to_register(register)?.number() as u32) + } + + /// Gets the full register that this one is a part of, eg. ``CL``/``CH``/``CX``/``ECX``/``RCX`` -> ``RCX``, ``XMM11``/``YMM11``/``ZMM11`` -> ``ZMM11`` + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// :class:`Register`: Full register (64-bit GPRs) + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert RegisterExt.full_register(Register.GS) == Register.GS + /// assert RegisterExt.full_register(Register.SIL) == Register.RSI + /// assert RegisterExt.full_register(Register.SP) == Register.RSP + /// assert RegisterExt.full_register(Register.R13D) == Register.R13 + /// assert RegisterExt.full_register(Register.RBP) == Register.RBP + /// assert RegisterExt.full_register(Register.MM6) == Register.MM6 + /// assert RegisterExt.full_register(Register.XMM10) == Register.ZMM10 + /// assert RegisterExt.full_register(Register.YMM10) == Register.ZMM10 + /// assert RegisterExt.full_register(Register.ZMM10) == Register.ZMM10 + /// assert RegisterExt.full_register(Register.K3) == Register.K3 + /// assert RegisterExt.full_register(Register.BND1) == Register.BND1 + /// assert RegisterExt.full_register(Register.ST7) == Register.ST7 + /// assert RegisterExt.full_register(Register.CR8) == Register.CR8 + /// assert RegisterExt.full_register(Register.DR6) == Register.DR6 + /// assert RegisterExt.full_register(Register.TR3) == Register.TR3 + /// assert RegisterExt.full_register(Register.RIP) == Register.RIP + #[staticmethod] + #[text_signature = "(register, /)"] + fn full_register(register: u32) -> PyResult { + Ok(to_register(register)?.full_register() as u32) + } + + /// Gets the full register that this one is a part of, except if it's a GPR in which case the 32-bit register is returned, + /// eg. ``CL``/``CH``/``CX``/``ECX``/``RCX`` -> ``ECX``, ``XMM11``/``YMM11``/``ZMM11`` -> ``ZMM11`` + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// :class:`Register`: Full register (32-bit GPRs) + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert RegisterExt.full_register32(Register.GS) == Register.GS + /// assert RegisterExt.full_register32(Register.SIL) == Register.ESI + /// assert RegisterExt.full_register32(Register.SP) == Register.ESP + /// assert RegisterExt.full_register32(Register.R13D) == Register.R13D + /// assert RegisterExt.full_register32(Register.RBP) == Register.EBP + /// assert RegisterExt.full_register32(Register.MM6) == Register.MM6 + /// assert RegisterExt.full_register32(Register.XMM10) == Register.ZMM10 + /// assert RegisterExt.full_register32(Register.YMM10) == Register.ZMM10 + /// assert RegisterExt.full_register32(Register.ZMM10) == Register.ZMM10 + /// assert RegisterExt.full_register32(Register.K3) == Register.K3 + /// assert RegisterExt.full_register32(Register.BND1) == Register.BND1 + /// assert RegisterExt.full_register32(Register.ST7) == Register.ST7 + /// assert RegisterExt.full_register32(Register.CR8) == Register.CR8 + /// assert RegisterExt.full_register32(Register.DR6) == Register.DR6 + /// assert RegisterExt.full_register32(Register.TR3) == Register.TR3 + /// assert RegisterExt.full_register32(Register.RIP) == Register.RIP + #[staticmethod] + #[text_signature = "(register, /)"] + fn full_register32(register: u32) -> PyResult { + Ok(to_register(register)?.full_register32() as u32) + } + + /// Gets the size of the register in bytes + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// int: Size of the register in bytes + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert RegisterExt.size(Register.GS) == 2 + /// assert RegisterExt.size(Register.SIL) == 1 + /// assert RegisterExt.size(Register.SP) == 2 + /// assert RegisterExt.size(Register.R13D) == 4 + /// assert RegisterExt.size(Register.RBP) == 8 + /// assert RegisterExt.size(Register.MM6) == 8 + /// assert RegisterExt.size(Register.XMM10) == 16 + /// assert RegisterExt.size(Register.YMM10) == 32 + /// assert RegisterExt.size(Register.ZMM10) == 64 + /// assert RegisterExt.size(Register.K3) == 8 + /// assert RegisterExt.size(Register.BND1) == 16 + /// assert RegisterExt.size(Register.ST7) == 10 + /// assert RegisterExt.size(Register.CR8) == 8 + /// assert RegisterExt.size(Register.DR6) == 8 + /// assert RegisterExt.size(Register.TR3) == 4 + /// assert RegisterExt.size(Register.RIP) == 8 + #[staticmethod] + #[text_signature = "(register, /)"] + fn size(register: u32) -> PyResult { + Ok(to_register(register)?.size() as u32) + } + + /// Checks if it's a segment register (``ES``, ``CS``, ``SS``, ``DS``, ``FS``, ``GS``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a segment register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert RegisterExt.is_segment_register(Register.GS) + /// assert not RegisterExt.is_segment_register(Register.RCX) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_segment_register(register: u32) -> PyResult { + Ok(to_register(register)?.is_segment_register()) + } + + /// Checks if it's a general purpose register (``AL``-``R15L``, ``AX``-``R15W``, ``EAX``-``R15D``, ``RAX``-``R15``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a general purpose register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_gpr(Register.GS) + /// assert RegisterExt.is_gpr(Register.CH) + /// assert RegisterExt.is_gpr(Register.DX) + /// assert RegisterExt.is_gpr(Register.R13D) + /// assert RegisterExt.is_gpr(Register.RSP) + /// assert not RegisterExt.is_gpr(Register.XMM0) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_gpr(register: u32) -> PyResult { + Ok(to_register(register)?.is_gpr()) + } + + /// Checks if it's an 8-bit general purpose register (``AL``-``R15L``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's an 8-bit general purpose register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_gpr8(Register.GS) + /// assert RegisterExt.is_gpr8(Register.CH) + /// assert not RegisterExt.is_gpr8(Register.DX) + /// assert not RegisterExt.is_gpr8(Register.R13D) + /// assert not RegisterExt.is_gpr8(Register.RSP) + /// assert not RegisterExt.is_gpr8(Register.XMM0) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_gpr8(register: u32) -> PyResult { + Ok(to_register(register)?.is_gpr8()) + } + + /// Checks if it's a 16-bit general purpose register (``AX``-``R15W``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a 16-bit general purpose register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_gpr16(Register.GS) + /// assert not RegisterExt.is_gpr16(Register.CH) + /// assert RegisterExt.is_gpr16(Register.DX) + /// assert not RegisterExt.is_gpr16(Register.R13D) + /// assert not RegisterExt.is_gpr16(Register.RSP) + /// assert not RegisterExt.is_gpr16(Register.XMM0) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_gpr16(register: u32) -> PyResult { + Ok(to_register(register)?.is_gpr16()) + } + + /// Checks if it's a 32-bit general purpose register (``EAX``-``R15D``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a 32-bit general purpose register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_gpr32(Register.GS) + /// assert not RegisterExt.is_gpr32(Register.CH) + /// assert not RegisterExt.is_gpr32(Register.DX) + /// assert RegisterExt.is_gpr32(Register.R13D) + /// assert not RegisterExt.is_gpr32(Register.RSP) + /// assert not RegisterExt.is_gpr32(Register.XMM0) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_gpr32(register: u32) -> PyResult { + Ok(to_register(register)?.is_gpr32()) + } + + /// Checks if it's a 64-bit general purpose register (``RAX``-``R15``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a 64-bit general purpose register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_gpr64(Register.GS) + /// assert not RegisterExt.is_gpr64(Register.CH) + /// assert not RegisterExt.is_gpr64(Register.DX) + /// assert not RegisterExt.is_gpr64(Register.R13D) + /// assert RegisterExt.is_gpr64(Register.RSP) + /// assert not RegisterExt.is_gpr64(Register.XMM0) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_gpr64(register: u32) -> PyResult { + Ok(to_register(register)?.is_gpr64()) + } + + /// Checks if it's a 128-bit vector register (``XMM0``-``XMM31``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's an XMM register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_xmm(Register.R13D) + /// assert not RegisterExt.is_xmm(Register.RSP) + /// assert RegisterExt.is_xmm(Register.XMM0) + /// assert not RegisterExt.is_xmm(Register.YMM0) + /// assert not RegisterExt.is_xmm(Register.ZMM0) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_xmm(register: u32) -> PyResult { + Ok(to_register(register)?.is_xmm()) + } + + /// Checks if it's a 256-bit vector register (``YMM0``-``YMM31``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a YMM register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_ymm(Register.R13D) + /// assert not RegisterExt.is_ymm(Register.RSP) + /// assert not RegisterExt.is_ymm(Register.XMM0) + /// assert RegisterExt.is_ymm(Register.YMM0) + /// assert not RegisterExt.is_ymm(Register.ZMM0) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_ymm(register: u32) -> PyResult { + Ok(to_register(register)?.is_ymm()) + } + + /// Checks if it's a 512-bit vector register (``ZMM0``-``ZMM31``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a ZMM register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_zmm(Register.R13D) + /// assert not RegisterExt.is_zmm(Register.RSP) + /// assert not RegisterExt.is_zmm(Register.XMM0) + /// assert not RegisterExt.is_zmm(Register.YMM0) + /// assert RegisterExt.is_zmm(Register.ZMM0) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_zmm(register: u32) -> PyResult { + Ok(to_register(register)?.is_zmm()) + } + + /// Checks if it's an ``XMM``, ``YMM`` or ``ZMM`` register + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a vector register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_vector_register(Register.R13D) + /// assert not RegisterExt.is_vector_register(Register.RSP) + /// assert RegisterExt.is_vector_register(Register.XMM0) + /// assert RegisterExt.is_vector_register(Register.YMM0) + /// assert RegisterExt.is_vector_register(Register.ZMM0) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_vector_register(register: u32) -> PyResult { + Ok(to_register(register)?.is_vector_register()) + } + + /// Checks if it's ``EIP``/``RIP`` + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's ``EIP``/``RIP`` + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert RegisterExt.is_ip(Register.EIP) + /// assert RegisterExt.is_ip(Register.RIP) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_ip(register: u32) -> PyResult { + Ok(to_register(register)?.is_ip()) + } + + /// Checks if it's an opmask register (``K0``-``K7``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's an opmask register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_k(Register.R13D) + /// assert RegisterExt.is_k(Register.K3) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_k(register: u32) -> PyResult { + Ok(to_register(register)?.is_k()) + } + + /// Checks if it's a control register (``CR0``-``CR15``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a control register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_cr(Register.R13D) + /// assert RegisterExt.is_cr(Register.CR3) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_cr(register: u32) -> PyResult { + Ok(to_register(register)?.is_cr()) + } + + /// Checks if it's a debug register (``DR0``-``DR15``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a debug register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_dr(Register.R13D) + /// assert RegisterExt.is_dr(Register.DR3) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_dr(register: u32) -> PyResult { + Ok(to_register(register)?.is_dr()) + } + + /// Checks if it's a test register (``TR0``-``TR7``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a test register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_tr(Register.R13D) + /// assert RegisterExt.is_tr(Register.TR3) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_tr(register: u32) -> PyResult { + Ok(to_register(register)?.is_tr()) + } + + /// Checks if it's an FPU stack register (``ST0``-``ST7``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's an FPU register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_st(Register.R13D) + /// assert RegisterExt.is_st(Register.ST3) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_st(register: u32) -> PyResult { + Ok(to_register(register)?.is_st()) + } + + /// Checks if it's a bound register (``BND0``-``BND3``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a bnd register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_bnd(Register.R13D) + /// assert RegisterExt.is_bnd(Register.BND3) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_bnd(register: u32) -> PyResult { + Ok(to_register(register)?.is_bnd()) + } + + /// Checks if it's an MMX register (``MM0``-``MM7``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's an mmx register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_mm(Register.R13D) + /// assert RegisterExt.is_mm(Register.MM3) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_mm(register: u32) -> PyResult { + Ok(to_register(register)?.is_mm()) + } + + /// Checks if it's a tile register (``TMM0``-``TMM7``) + /// + /// Args: + /// `register` (:class:`Register`): Enum value + /// + /// Returns: + /// bool: ``True`` if it's a tmm register + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// assert not RegisterExt.is_tmm(Register.R13D) + /// assert RegisterExt.is_tmm(Register.TMM3) + #[staticmethod] + #[text_signature = "(register, /)"] + fn is_tmm(register: u32) -> PyResult { + Ok(to_register(register)?.is_tmm()) + } +} diff --git a/src/rust/iced-x86-py/src/register_info.rs b/src/rust/iced-x86-py/src/register_info.rs new file mode 100644 index 000000000..1fc9a2c4f --- /dev/null +++ b/src/rust/iced-x86-py/src/register_info.rs @@ -0,0 +1,201 @@ +/* +Copyright (C) 2018-2019 de4dot@gmail.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +use crate::enum_utils::to_register; +use pyo3::prelude::*; + +/// :class:`Register` enum info, see also :class:`RegisterExt` +/// +/// Args: +/// `register_size` (:class:`Register`): Enum value +/// +/// Examples: +/// +/// .. testcode:: +/// +/// from iced_x86 import * +/// +/// info = RegisterInfo(Register.GS) +/// assert info.number == 5 +#[pyclass(module = "_iced_x86_py")] +#[text_signature = "(register_size, /)"] +pub(crate) struct RegisterInfo { + pub(crate) info: &'static iced_x86::RegisterInfo, +} + +#[pymethods] +impl RegisterInfo { + #[new] + fn new(register: u32) -> PyResult { + Ok(RegisterInfo { info: to_register(register)?.info() }) + } + + /// :class:`Register`: Gets the register value passed into the constructor + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// info = RegisterInfo(Register.EAX) + /// assert info.register == Register.EAX + #[getter] + fn register(&self) -> u32 { + self.info.register() as u32 + } + + /// :class:`Register`: Gets the base register, eg. ``AL``, ``AX``, ``EAX``, ``RAX``, ``MM0``, ``XMM0``, ``YMM0``, ``ZMM0``, ``ES`` + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// info = RegisterInfo(Register.GS) + /// assert info.base == Register.ES + /// info = RegisterInfo(Register.RDX) + /// assert info.base == Register.RAX + /// info = RegisterInfo(Register.XMM13) + /// assert info.base == Register.XMM0 + /// info = RegisterInfo(Register.YMM13) + /// assert info.base == Register.YMM0 + /// info = RegisterInfo(Register.ZMM13) + /// assert info.base == Register.ZMM0 + #[getter] + fn base(&self) -> u32 { + self.info.base() as u32 + } + + /// int: The register number (index) relative to :class:`RegisterInfo.base`, eg. 0-15, or 0-31, or if 8-bit GPR, 0-19 + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// info = RegisterInfo(Register.GS) + /// assert info.number == 5 + /// info = RegisterInfo(Register.RDX) + /// assert info.number == 2 + /// info = RegisterInfo(Register.XMM13) + /// assert info.number == 13 + /// info = RegisterInfo(Register.YMM13) + /// assert info.number == 13 + /// info = RegisterInfo(Register.ZMM13) + /// assert info.number == 13 + #[getter] + fn number(&self) -> u32 { + self.info.number() as u32 + } + + /// :class:`Register`: The full register that this one is a part of, eg. ``CL``/``CH``/``CX``/``ECX``/``RCX`` -> ``RCX``, ``XMM11``/``YMM11``/``ZMM11`` -> ``ZMM11`` + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// info = RegisterInfo(Register.GS) + /// assert info.full_register == Register.GS + /// info = RegisterInfo(Register.BH) + /// assert info.full_register == Register.RBX + /// info = RegisterInfo(Register.DX) + /// assert info.full_register == Register.RDX + /// info = RegisterInfo(Register.ESP) + /// assert info.full_register == Register.RSP + /// info = RegisterInfo(Register.RCX) + /// assert info.full_register == Register.RCX + /// info = RegisterInfo(Register.XMM3) + /// assert info.full_register == Register.ZMM3 + /// info = RegisterInfo(Register.YMM3) + /// assert info.full_register == Register.ZMM3 + /// info = RegisterInfo(Register.ZMM3) + /// assert info.full_register == Register.ZMM3 + #[getter] + fn full_register(&self) -> u32 { + self.info.full_register() as u32 + } + + /// :class:`Register`: Gets the full register that this one is a part of, except if it's a GPR in which case the 32-bit register is returned, + /// eg. ``CL``/``CH``/``CX``/``ECX``/``RCX`` -> ``ECX``, ``XMM11``/``YMM11``/``ZMM11`` -> ``ZMM11`` + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// info = RegisterInfo(Register.GS) + /// assert info.full_register32 == Register.GS + /// info = RegisterInfo(Register.BH) + /// assert info.full_register32 == Register.EBX + /// info = RegisterInfo(Register.DX) + /// assert info.full_register32 == Register.EDX + /// info = RegisterInfo(Register.ESP) + /// assert info.full_register32 == Register.ESP + /// info = RegisterInfo(Register.RCX) + /// assert info.full_register32 == Register.ECX + /// info = RegisterInfo(Register.XMM3) + /// assert info.full_register32 == Register.ZMM3 + /// info = RegisterInfo(Register.YMM3) + /// assert info.full_register32 == Register.ZMM3 + /// info = RegisterInfo(Register.ZMM3) + /// assert info.full_register32 == Register.ZMM3 + #[getter] + fn full_register32(&self) -> u32 { + self.info.full_register32() as u32 + } + + /// int: Size of the register in bytes + /// + /// Examples: + /// + /// .. testcode:: + /// + /// from iced_x86 import * + /// + /// info = RegisterInfo(Register.GS) + /// assert info.size == 2 + /// info = RegisterInfo(Register.BH) + /// assert info.size == 1 + /// info = RegisterInfo(Register.DX) + /// assert info.size == 2 + /// info = RegisterInfo(Register.ESP) + /// assert info.size == 4 + /// info = RegisterInfo(Register.RCX) + /// assert info.size == 8 + /// info = RegisterInfo(Register.XMM3) + /// assert info.size == 16 + /// info = RegisterInfo(Register.YMM3) + /// assert info.size == 32 + /// info = RegisterInfo(Register.ZMM3) + /// assert info.size == 64 + #[getter] + fn size(&self) -> u32 { + self.info.size() as u32 + } +} diff --git a/src/rust/iced-x86-py/tests/register_test.py b/src/rust/iced-x86-py/tests/register_test.py new file mode 100644 index 000000000..5307fa688 --- /dev/null +++ b/src/rust/iced-x86-py/tests/register_test.py @@ -0,0 +1,262 @@ +# +# Copyright (C) 2018-2019 de4dot@gmail.com +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +import pytest +from iced_x86 import * + +def test_register_ext(): + assert RegisterExt.base(Register.DL) == Register.AL + assert RegisterExt.base(Register.R8W) == Register.AX + assert RegisterExt.base(Register.R15D) == Register.EAX + assert RegisterExt.base(Register.R13) == Register.RAX + assert RegisterExt.base(Register.FS) == Register.ES + assert RegisterExt.base(Register.XMM2) == Register.XMM0 + assert RegisterExt.base(Register.YMM20) == Register.YMM0 + assert RegisterExt.base(Register.ZMM31) == Register.ZMM0 + + assert RegisterExt.number(Register.DL) == 2 + assert RegisterExt.number(Register.R15) == 15 + assert RegisterExt.number(Register.YMM21) == 21 + + assert RegisterExt.full_register(Register.CL) == Register.RCX + assert RegisterExt.full_register(Register.DX) == Register.RDX + assert RegisterExt.full_register(Register.EBX) == Register.RBX + assert RegisterExt.full_register(Register.RSP) == Register.RSP + assert RegisterExt.full_register(Register.XMM2) == Register.ZMM2 + assert RegisterExt.full_register(Register.YMM22) == Register.ZMM22 + assert RegisterExt.full_register(Register.ZMM11) == Register.ZMM11 + + assert RegisterExt.full_register32(Register.CL) == Register.ECX + assert RegisterExt.full_register32(Register.DX) == Register.EDX + assert RegisterExt.full_register32(Register.EBX) == Register.EBX + assert RegisterExt.full_register32(Register.RSP) == Register.ESP + assert RegisterExt.full_register32(Register.XMM2) == Register.ZMM2 + assert RegisterExt.full_register32(Register.YMM22) == Register.ZMM22 + assert RegisterExt.full_register32(Register.ZMM11) == Register.ZMM11 + + assert RegisterExt.size(Register.DL) == 1 + assert RegisterExt.size(Register.R8W) == 2 + assert RegisterExt.size(Register.R15D) == 4 + assert RegisterExt.size(Register.R13) == 8 + assert RegisterExt.size(Register.FS) == 2 + assert RegisterExt.size(Register.XMM2) == 16 + assert RegisterExt.size(Register.YMM20) == 32 + assert RegisterExt.size(Register.ZMM31) == 64 + + assert not RegisterExt.is_segment_register(Register.CX) + assert RegisterExt.is_segment_register(Register.GS) + + assert RegisterExt.is_gpr(Register.CL) + assert RegisterExt.is_gpr(Register.DX) + assert RegisterExt.is_gpr(Register.ESP) + assert RegisterExt.is_gpr(Register.R15) + assert not RegisterExt.is_gpr(Register.ES) + + assert RegisterExt.is_gpr8(Register.CL) + assert not RegisterExt.is_gpr8(Register.DX) + assert not RegisterExt.is_gpr8(Register.ESP) + assert not RegisterExt.is_gpr8(Register.R15) + assert not RegisterExt.is_gpr8(Register.ES) + + assert not RegisterExt.is_gpr16(Register.CL) + assert RegisterExt.is_gpr16(Register.DX) + assert not RegisterExt.is_gpr16(Register.ESP) + assert not RegisterExt.is_gpr16(Register.R15) + assert not RegisterExt.is_gpr16(Register.ES) + + assert not RegisterExt.is_gpr32(Register.CL) + assert not RegisterExt.is_gpr32(Register.DX) + assert RegisterExt.is_gpr32(Register.ESP) + assert not RegisterExt.is_gpr32(Register.R15) + assert not RegisterExt.is_gpr32(Register.ES) + + assert not RegisterExt.is_gpr64(Register.CL) + assert not RegisterExt.is_gpr64(Register.DX) + assert not RegisterExt.is_gpr64(Register.ESP) + assert RegisterExt.is_gpr64(Register.R15) + assert not RegisterExt.is_gpr64(Register.ES) + + assert not RegisterExt.is_vector_register(Register.CL) + assert RegisterExt.is_vector_register(Register.XMM1) + assert RegisterExt.is_vector_register(Register.YMM2) + assert RegisterExt.is_vector_register(Register.ZMM3) + + assert not RegisterExt.is_xmm(Register.CL) + assert RegisterExt.is_xmm(Register.XMM1) + assert not RegisterExt.is_xmm(Register.YMM2) + assert not RegisterExt.is_xmm(Register.ZMM3) + + assert not RegisterExt.is_ymm(Register.CL) + assert not RegisterExt.is_ymm(Register.XMM1) + assert RegisterExt.is_ymm(Register.YMM2) + assert not RegisterExt.is_ymm(Register.ZMM3) + + assert not RegisterExt.is_zmm(Register.CL) + assert not RegisterExt.is_zmm(Register.XMM1) + assert not RegisterExt.is_zmm(Register.YMM2) + assert RegisterExt.is_zmm(Register.ZMM3) + + assert not RegisterExt.is_ip(Register.CL) + assert RegisterExt.is_ip(Register.EIP) + assert RegisterExt.is_ip(Register.RIP) + + assert not RegisterExt.is_k(Register.CL) + assert RegisterExt.is_k(Register.K3) + + assert not RegisterExt.is_cr(Register.CL) + assert RegisterExt.is_cr(Register.CR3) + + assert not RegisterExt.is_dr(Register.CL) + assert RegisterExt.is_dr(Register.DR3) + + assert not RegisterExt.is_tr(Register.CL) + assert RegisterExt.is_tr(Register.TR3) + + assert not RegisterExt.is_st(Register.CL) + assert RegisterExt.is_st(Register.ST3) + + assert not RegisterExt.is_bnd(Register.CL) + assert RegisterExt.is_bnd(Register.BND3) + + assert not RegisterExt.is_mm(Register.CL) + assert RegisterExt.is_mm(Register.MM3) + + assert not RegisterExt.is_tmm(Register.CL) + assert RegisterExt.is_tmm(Register.TMM3) + +@pytest.mark.parametrize("create", [ + lambda register: RegisterExt.info(register), + lambda register: RegisterInfo(register), +]) +def test_register_info(create): + info = create(Register.R10D) + assert info.register == Register.R10D + assert info.base == Register.EAX + assert info.number == 10 + assert info.full_register == Register.R10 + assert info.full_register32 == Register.R10D + assert info.size == 4 + +@pytest.mark.parametrize("create", [ + lambda register: RegisterExt.info(register), + lambda register: RegisterInfo(register), +]) +def test_register_invalid_arg(create): + with pytest.raises(ValueError): + create(1234) + +def test_ext_base_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.base(1234) + +def test_ext_number_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.number(1234) + +def test_ext_full_register_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.full_register(1234) + +def test_ext_full_register32_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.full_register32(1234) + +def test_ext_size_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.size(1234) + +def test_ext_is_segment_register_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_segment_register(1234) + +def test_ext_is_gpr_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_gpr(1234) + +def test_ext_is_gpr8_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_gpr8(1234) + +def test_ext_is_gpr16_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_gpr16(1234) + +def test_ext_is_gpr32_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_gpr32(1234) + +def test_ext_is_gpr64_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_gpr64(1234) + +def test_ext_is_xmm_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_xmm(1234) + +def test_ext_is_ymm_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_ymm(1234) + +def test_ext_is_zmm_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_zmm(1234) + +def test_ext_is_vector_register_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_vector_register(1234) + +def test_ext_is_ip_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_ip(1234) + +def test_ext_is_k_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_k(1234) + +def test_ext_is_cr_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_cr(1234) + +def test_ext_is_dr_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_dr(1234) + +def test_ext_is_tr_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_tr(1234) + +def test_ext_is_st_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_st(1234) + +def test_ext_is_bnd_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_bnd(1234) + +def test_ext_is_mm_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_mm(1234) + +def test_ext_is_tmm_invalid_arg(): + with pytest.raises(ValueError): + RegisterExt.is_tmm(1234) diff --git a/src/rust/iced-x86/src/register.rs b/src/rust/iced-x86/src/register.rs index 95a7e1d65..e960b9ca2 100644 --- a/src/rust/iced-x86/src/register.rs +++ b/src/rust/iced-x86/src/register.rs @@ -367,6 +367,8 @@ mod info { /// The full register that this one is a part of, eg. `CL`/`CH`/`CX`/`ECX`/`RCX` -> `RCX`, `XMM11`/`YMM11`/`ZMM11` -> `ZMM11` /// + /// # Examples + /// /// ``` /// use iced_x86::*; /// let info = Register::GS.info(); @@ -395,6 +397,8 @@ mod info { /// Gets the full register that this one is a part of, except if it's a GPR in which case the 32-bit register is returned, /// eg. `CL`/`CH`/`CX`/`ECX`/`RCX` -> `ECX`, `XMM11`/`YMM11`/`ZMM11` -> `ZMM11` /// + /// # Examples + /// /// ``` /// use iced_x86::*; /// let info = Register::GS.info(); @@ -422,6 +426,8 @@ mod info { /// Size of the register in bytes /// + /// # Examples + /// /// ``` /// use iced_x86::*; /// let info = Register::GS.info();