py: Add a MemoryOperand.ctor_u64() ctor, closes #179

This commit is contained in:
wtfsck 2021-07-08 14:37:54 +02:00
parent bd7abf27e4
commit 4b87bbcfa5
3 changed files with 56 additions and 2 deletions

View File

@ -6732,17 +6732,41 @@ class MemoryOperand:
"""
Memory operand passed to one of `Instruction`'s `create*()` constructor methods
See also `MemoryOperand.ctor_u64()` if you need to pass in a `u64` `displ` argument value.
### Args:
- `base` (`Register`): (default = `Register.NONE`) Base register or `Register.NONE`
- `index` (`Register`): (default = `Register.NONE`) Index register or `Register.NONE`
- `scale` (int): (default = `1`) Index register scale (1, 2, 4, or 8)
- `displ` (int): (`i32`) (default = `0`) Memory displacement
- `displ` (int): (`i64`) (default = `0`) Memory displacement
- `displ_size` (int): (default = `0`) 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
- `is_broadcast` (bool): (default = `False`) `True` if it's broadcasted memory (EVEX instructions)
- `seg` (`Register`): (default = `Register.NONE`) Segment override or `Register.NONE`
"""
def __init__(self, base: Register = Register.NONE, index: Register = Register.NONE, scale: int = 1, displ: int = 0, displ_size: int = 0, is_broadcast: bool = False, seg: Register = Register.NONE) -> None: ...
@staticmethod
def ctor_u64(base: Register = Register.NONE, index: Register = Register.NONE, scale: int = 1, displ: int = 0, displ_size: int = 0, is_broadcast: bool = False, seg: Register = Register.NONE) -> MemoryOperand:
"""
Memory operand passed to one of `Instruction`'s `create*()` constructor methods
The only difference between this method and the constructor is that this method takes a `u64` `displ` argument instead of an `i64`.
### Args:
- `base` (`Register`): (default = `Register.NONE`) Base register or `Register.NONE`
- `index` (`Register`): (default = `Register.NONE`) Index register or `Register.NONE`
- `scale` (int): (default = `1`) Index register scale (1, 2, 4, or 8)
- `displ` (int): (`u64`) (default = `0`) Memory displacement
- `displ_size` (int): (default = `0`) 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
- `is_broadcast` (bool): (default = `False`) `True` if it's broadcasted memory (EVEX instructions)
- `seg` (`Register`): (default = `Register.NONE`) Segment override or `Register.NONE`
### Returns:
- MemoryOperand: A new instance
"""
...
def __copy__(self) -> MemoryOperand:
"""
Returns a copy of this instance.

View File

@ -11,11 +11,13 @@ use std::collections::hash_map::DefaultHasher;
/// Memory operand passed to one of :class:`Instruction`'s `create*()` constructor methods
///
/// See also ``MemoryOperand.ctor_u64()`` if you need to pass in a ``u64`` ``displ`` argument value.
///
/// Args:
/// `base` (:class:`Register`): (default = :class:`Register.NONE`) Base register or :class:`Register.NONE`
/// `index` (:class:`Register`): (default = :class:`Register.NONE`) Index register or :class:`Register.NONE`
/// `scale` (int): (default = ``1``) Index register scale (1, 2, 4, or 8)
/// `displ` (int): (``i32``) (default = ``0``) Memory displacement
/// `displ` (int): (``i64``) (default = ``0``) Memory displacement
/// `displ_size` (int): (default = ``0``) 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
/// `is_broadcast` (bool): (default = ``False``) ``True`` if it's broadcasted memory (EVEX instructions)
/// `seg` (:class:`Register`): (default = :class:`Register.NONE`) Segment override or :class:`Register.NONE`
@ -43,6 +45,28 @@ impl MemoryOperand {
})
}
/// Memory operand passed to one of :class:`Instruction`'s `create*()` constructor methods
///
/// The only difference between this method and the constructor is that this method takes a ``u64`` ``displ`` argument instead of an ``i64``.
///
/// Args:
/// `base` (:class:`Register`): (default = :class:`Register.NONE`) Base register or :class:`Register.NONE`
/// `index` (:class:`Register`): (default = :class:`Register.NONE`) Index register or :class:`Register.NONE`
/// `scale` (int): (default = ``1``) Index register scale (1, 2, 4, or 8)
/// `displ` (int): (``u64``) (default = ``0``) Memory displacement
/// `displ_size` (int): (default = ``0``) 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
/// `is_broadcast` (bool): (default = ``False``) ``True`` if it's broadcasted memory (EVEX instructions)
/// `seg` (:class:`Register`): (default = :class:`Register.NONE`) Segment override or :class:`Register.NONE`
///
/// Returns:
/// MemoryOperand: A new instance
#[pyo3(text_signature = "(base, index, scale, displ, displ_size, is_broadcast, seg, /)")]
#[args(base = 0, index = 0, scale = 1, displ = 0, displ_size = 0, is_broadcast = false, seg = 0)]
#[staticmethod]
fn ctor_u64(base: u32, index: u32, scale: u32, displ: u64, displ_size: u32, is_broadcast: bool, seg: u32) -> PyResult<Self> {
MemoryOperand::new(base, index, scale, displ as i64, displ_size, is_broadcast, seg)
}
/// Returns a copy of this instance.
///
/// Returns:

View File

@ -5,6 +5,12 @@ import copy
import pytest
from iced_x86 import *
def test_ctor_signed_and_unsigned_displ():
m1 = MemoryOperand(displ=-1)
m2 = MemoryOperand.ctor_u64(displ=0xFFFF_FFFF_FFFF_FFFF)
assert m1 == m2
MemoryOperand.ctor_u64(displ=0xFFFF_FFFF)
def test_eq_ne_hash():
mem1 = MemoryOperand()
mem2 = MemoryOperand(Register.NONE, Register.NONE, 1, 0, 0, False, Register.NONE)