1# This file is part of PeachPy package and is licensed under the Simplified BSD license.
2#    See license.rst for the full text of the license.
3
4
5def check_operand(operand):
6    """Validates operand object as an instruction operand and converts it to a standard form"""
7
8    from peachpy.x86_64.registers import Register, MaskedRegister
9    from peachpy.x86_64.pseudo import Label
10    from peachpy.x86_64.function import LocalVariable
11    from peachpy.literal import Constant
12    from peachpy import Argument
13    from peachpy.util import is_int, is_int64
14    from copy import copy, deepcopy
15    if isinstance(operand, Register):
16        return copy(operand)
17    elif isinstance(operand, (MaskedRegister, MemoryOperand)):
18        return deepcopy(operand)
19    elif isinstance(operand, (Argument, RIPRelativeOffset, Label)):
20        return operand
21    elif is_int(operand):
22        if not is_int64(operand):
23            raise ValueError("The immediate operand %d is not representable as a 64-bit value")
24        return operand
25    elif isinstance(operand, list):
26        if len(operand) != 1:
27            raise ValueError("Memory operands must be represented by a list with only one element")
28        return MemoryOperand(operand[0])
29    elif isinstance(operand, Constant):
30        from copy import copy, deepcopy
31        operand = copy(operand)
32        import peachpy.common.function
33        if peachpy.common.function.active_function:
34            operand.name = deepcopy(operand.name, peachpy.common.function.active_function._names_memo)
35        return MemoryOperand(operand)
36    elif isinstance(operand, LocalVariable):
37        return MemoryOperand(operand)
38    elif isinstance(operand, set):
39        if len(operand) != 1:
40            raise ValueError("Rounding control & suppress-all-errors operands must be represented by a set "
41                             "with only one element")
42        return next(iter(operand))
43    else:
44        raise TypeError("Unsupported operand: %s" % str(operand))
45
46
47def get_operand_registers(operand):
48    """Returns a set of registers that comprise the operand"""
49
50    from peachpy.x86_64.registers import Register, MaskedRegister
51    if isinstance(operand, Register):
52        return [operand]
53    elif isinstance(operand, MaskedRegister):
54        return [operand.register, operand.mask.mask_register]
55    elif isinstance(operand, MemoryOperand) and isinstance(operand.address, MemoryAddress):
56        registers = list()
57        if operand.address.base is not None:
58            registers.append(operand.address.base)
59        if operand.address.index is not None:
60            registers.append(operand.address.index)
61        return registers
62    else:
63        return list()
64
65
66def format_operand(operand, assembly_format):
67    assert assembly_format in {"peachpy", "gas", "nasm", "go"}, \
68        "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"
69
70    immediate_prefix_map = {
71        "peachpy": "",
72        "gas": "$",
73        "nasm": "",
74        "go": "$"
75    }
76
77    from peachpy.util import is_int64
78    if is_int64(operand):
79        return immediate_prefix_map[assembly_format] + str(operand)
80    else:
81        return operand.format(assembly_format)
82
83
84def format_operand_type(operand):
85    """Returns string representation of the operand type in assembly language"""
86    from peachpy.x86_64.registers import GeneralPurposeRegister64, GeneralPurposeRegister32, GeneralPurposeRegister16,\
87        GeneralPurposeRegister8, MMXRegister, XMMRegister, YMMRegister, ZMMRegister, MaskedRegister, \
88        al, ax, eax, rax, cl, xmm0
89    from peachpy.x86_64.pseudo import Label
90    from peachpy.util import is_int64, is_int32, is_int16, is_int8
91    if is_int8(operand):
92        return "imm8"
93    elif is_int16(operand):
94        return "imm16"
95    elif is_int32(operand):
96        return "imm32"
97    elif is_int64(operand):
98        return "imm64"
99    elif al == operand:
100        return "al"
101    elif ax == operand:
102        return "ax"
103    elif eax == operand:
104        return "eax"
105    elif rax == operand:
106        return "rax"
107    elif cl == operand:
108        return "cl"
109    elif xmm0 == operand:
110        return "xmm0"
111    elif isinstance(operand, GeneralPurposeRegister64):
112        return "r64"
113    elif isinstance(operand, GeneralPurposeRegister32):
114        return "r32"
115    elif isinstance(operand, GeneralPurposeRegister16):
116        return "r16"
117    elif isinstance(operand, GeneralPurposeRegister8):
118        return "r8"
119    elif isinstance(operand, MMXRegister):
120        return "mm"
121    elif isinstance(operand, XMMRegister):
122        return "xmm"
123    elif isinstance(operand, YMMRegister):
124        return "ymm"
125    elif isinstance(operand, ZMMRegister):
126        return "zmm"
127    elif isinstance(operand, MaskedRegister):
128        if operand.mask.is_zeroing:
129            return format_operand_type(operand.register) + "{k}{z}"
130        else:
131            return format_operand_type(operand.register) + "{k}"
132    elif isinstance(operand, MemoryOperand):
133        if operand.size is None:
134            return "m"
135        else:
136            if operand.mask is None:
137                return "m" + str(operand.size * 8)
138            elif operand.mask.is_zeroing:
139                return "m" + str(operand.size * 8) + "{k}{z}"
140            else:
141                return "m" + str(operand.size * 8) + "{k}"
142    elif isinstance(operand, RoundingControl):
143        return "{er}"
144    elif isinstance(operand, SuppressAllExceptions):
145        return "{sae}"
146    elif isinstance(operand, Label):
147        return "rel"
148    else:
149        return operand.__class__.__name__
150
151
152class MemoryAddress:
153    """An address expression involving a register, e.g. rax - 10, r8d * 4."""
154
155    def __init__(self, base=None, index=None, scale=None, displacement=0):
156        from peachpy.x86_64.registers import GeneralPurposeRegister64, \
157            XMMRegister, YMMRegister, ZMMRegister, MaskedRegister
158        from peachpy.util import is_int, is_sint32
159
160        # Check individual arguments
161        if base is not None and not isinstance(base, GeneralPurposeRegister64):
162            raise TypeError("Base register must be a 64-bit general-purpose register")
163        if index is not None and \
164            not isinstance(index, (GeneralPurposeRegister64, XMMRegister, YMMRegister, ZMMRegister)) and not \
165            (isinstance(index, MaskedRegister) and
166                isinstance(index.register, (XMMRegister, YMMRegister, ZMMRegister)) and
167                not index.mask.is_zeroing):
168            raise TypeError("Index register must be a 64-bit general-purpose register or an XMM/YMM/ZMM register")
169        if scale is not None and not is_int(scale):
170            raise TypeError("Scale must be an integer")
171        if scale is not None and int(scale) not in {1, 2, 4, 8}:
172            raise TypeError("Scale must be 1, 2, 4, or 8")
173        if not is_sint32(displacement):
174            raise ValueError("Displacement value (%s) is not representable as a signed 32-bit integer" %
175                             str(displacement))
176
177        # Check relations of arguments
178        if scale is not None and index is None or scale is None and index is not None:
179            raise ValueError("Either both of neither of scale and index must be defined")
180        if index is None and base is None:
181            raise ValueError("Either base or index * scale must be specified")
182
183        self.base = base
184        self.index = index
185        self.scale = None if scale is None else int(scale)
186        self.displacement = int(displacement)
187
188    def __add__(self, addend):
189        from peachpy.x86_64.registers import GeneralPurposeRegister64
190        from peachpy.util import is_int, is_sint32
191        if is_int(addend):
192            if not is_sint32(addend):
193                raise ValueError("The addend value (%d) is not representable as a signed 32-bit integer" % addend)
194            return MemoryAddress(self.base, self.index, self.scale, self.displacement + addend)
195        elif isinstance(addend, GeneralPurposeRegister64):
196            if self.base is not None:
197                raise TypeError("Can not add a general-purpose register to a memory operand with existing base")
198            if self.index.size != addend.size:
199                raise TypeError("Index (%s) and addend (%s) registers have different size" %
200                                (str(self.index), str(addend)))
201            return MemoryAddress(addend, self.index, self.scale, self.displacement)
202        elif isinstance(addend, MemoryAddress):
203            if self.base is not None and addend.base is not None:
204                raise ValueError("Can not add memory address: both address expressions use base registers")
205            if self.index is not None and addend.index is not None:
206                raise ValueError("Can not add memory address: both address expressions use index registers")
207            sum_base = self.base if self.base is not None else addend.base
208            (sum_index, sum_scale) = (self.index, self.scale) \
209                if self.index is not None else (addend.index, addend.scale)
210            return MemoryAddress(sum_base, sum_index, sum_scale, self.displacement + addend.displacement)
211        else:
212            raise TypeError("Can not add %s: unsupported addend type" % str(addend))
213
214    def __sub__(self, minuend):
215        from peachpy.util import is_int, is_sint32
216        if is_int(minuend):
217            if not is_sint32(-minuend):
218                raise ValueError("The addend value (%d) is not representable as a signed 32-bit integer" % minuend)
219            return MemoryAddress(self.base, self.index, self.scale, self.displacement - minuend)
220        else:
221            raise TypeError("Can not add %s: unsupported addend type" % str(minuend))
222
223    def __str__(self):
224        parts = []
225        if self.base is not None:
226            parts.append(str(self.base))
227        if self.index is not None:
228            parts.append(str(self.index) + "*" + str(self.scale))
229        if self.displacement >= 0:
230            if self.displacement > 0:
231                parts.append(str(self.displacement))
232            return " + ".join(parts)
233        else:
234            return " + ".join(parts) + " - " + str(-self.displacement)
235
236    def __repr__(self):
237        return str(self)
238
239
240class MemoryOperand:
241    def __init__(self, address, size=None, mask=None, broadcast=None):
242        from peachpy.x86_64.registers import GeneralPurposeRegister64, \
243            XMMRegister, YMMRegister, ZMMRegister, MaskedRegister
244        from peachpy.x86_64.function import LocalVariable
245        from peachpy.literal import Constant
246        assert isinstance(address, (GeneralPurposeRegister64, XMMRegister, YMMRegister, ZMMRegister,
247                                    MemoryAddress, Constant, LocalVariable)) or \
248            isinstance(address, MaskedRegister) and \
249            isinstance(address.register, (XMMRegister, YMMRegister, ZMMRegister)) and \
250            not address.mask.is_zeroing, \
251            "Only MemoryAddress, 64-bit general-purpose registers, XMM/YMM/ZMM registers, " \
252            "and merge-masked XMM/YMM/ZMM registers may be specified as an address"
253        from peachpy.util import is_int
254        assert size is None or is_int(size) and int(size) in SizeSpecification._size_name_map, \
255            "Unsupported size: %d" % size
256
257        self.symbol = None
258        self.size = size
259        self.mask = mask
260        self.broadcast = broadcast
261
262        if isinstance(address, MemoryAddress):
263            if isinstance(address.index, MaskedRegister):
264                self.address = MemoryAddress(address.base, address.index.register, address.scale, address.displacement)
265                assert mask is None, "Mask argument can't be used when address index is a masked XMM/YMM/ZMM register"
266                self.mask = address.index.mask
267            else:
268                self.address = address
269        elif isinstance(address, MaskedRegister):
270            self.address = MemoryAddress(index=address.register, scale=1)
271            assert mask is None, "Mask argument can't be used when address is a masked XMM/YMM/ZMM register"
272            self.mask = address.mask
273        elif isinstance(address, Constant):
274            self.address = RIPRelativeOffset(0)
275            self.symbol = address
276            self.size = address.size
277        elif isinstance(address, LocalVariable):
278            from peachpy.x86_64.registers import rsp
279            self.address = MemoryAddress(rsp, displacement=address.offset)
280            self.symbol = address
281            self.size = address.size
282        else:
283            # Convert register to memory address expression
284            self.address = MemoryAddress(address)
285
286    def __str__(self):
287        if self.size is None:
288            return "[" + str(self.address) + "]"
289        else:
290            return SizeSpecification._size_name_map[self.size] + " [" + str(self.address) + "]"
291
292    def __repr__(self):
293        return str(self)
294
295    def __call__(self, mask):
296        from peachpy.x86_64.registers import KRegister, RegisterMask
297        if not isinstance(mask, (KRegister, RegisterMask)):
298            raise SyntaxError("zmm(mask) syntax requires mask to be a KRegister or KRegister.z")
299        if self.broadcast:
300            raise ValueError("mask can not be applied to memory operands with broadcasting")
301        if isinstance(mask, KRegister):
302            mask = RegisterMask(mask)
303        return MemoryOperand(self.address, self.size, mask)
304
305    def format(self, assembly_format):
306        assert assembly_format in {"peachpy", "gas", "nasm", "go"}, \
307            "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"
308
309        if assembly_format == "go":
310            text = str(self.address.displacement)
311            if self.address.base is not None:
312                text += "(" + self.address.base.format(assembly_format) + ")"
313            if self.address.index is not None:
314                text += "(%s*%d)" % (self.address.index.format(assembly_format), self.address.scale)
315            return text
316        elif assembly_format == "gas":
317            if isinstance(self.address, RIPRelativeOffset):
318                return str(self.address.offset) + "(%%rip)"
319            else:
320                base = self.address.base
321                if self.address.index is None:
322                    return "{displacement}({base})".format(
323                        displacement=self.address.displacement,
324                        base=base.format(assembly_format))
325                else:
326                    return "{displacement}({base},{index},{scale})".format(
327                        displacement=self.address.displacement,
328                        base="" if base is None else base.format(assembly_format),
329                        index=self.address.index,
330                        scale=self.address.scale)
331        else:
332            return str(self)
333
334    @property
335    def bcode(self):
336        return int(self.broadcast is not None)
337
338    @property
339    def kcode(self):
340        if self.mask is None:
341            return 0
342        else:
343            return self.mask.kcode
344
345    @property
346    def zcode(self):
347        if self.mask is None:
348            return 0
349        else:
350            return self.mask.zcode
351
352
353class SizeSpecification:
354    _size_name_map = {
355        1: "byte",
356        2: "word",
357        4: "dword",
358        8: "qword",
359        10: "tword",
360        16: "oword",
361        32: "hword",
362        64: "zword"
363    }
364
365    def __init__(self, size):
366        from peachpy.util import is_int
367        assert is_int(size) and int(size) in SizeSpecification._size_name_map, \
368            "Unsupported size: %d" % size
369        self.size = size
370
371    def __str__(self):
372        return SizeSpecification._size_name_map[self.size]
373
374    def __getitem__(self, address):
375        return MemoryOperand(address, self.size)
376
377    @property
378    def to2(self):
379        if self.size not in [4, 8]:
380            raise ValueError("{1to2} broadcasting is only supported for dword and qword memory locations")
381        return BroadcastSpecification(self.size, 2)
382
383    @property
384    def to4(self):
385        if self.size not in [4, 8]:
386            raise ValueError("{1to4} broadcasting is only supported for dword and qword memory locations")
387        return BroadcastSpecification(self.size, 4)
388
389    @property
390    def to8(self):
391        if self.size not in [4, 8]:
392            raise ValueError("{1to8} broadcasting is only supported for dword and qword memory locations")
393        return BroadcastSpecification(self.size, 8)
394
395    @property
396    def to16(self):
397        if self.size != 4:
398            raise ValueError("{1to16} broadcasting is only supported for dword memory locations")
399        return BroadcastSpecification(self.size, 16)
400
401
402class BroadcastSpecification:
403    def __init__(self, size, broadcast):
404        assert size in [4, 8]
405        assert broadcast in [2, 4, 8, 16]
406        assert size * broadcast in [16, 32, 64]
407        self.size = size
408        self.broadcast = broadcast
409
410    def __str__(self):
411        return SizeSpecification._size_name_map[self.size] + "{1to%d}" % self.broadcast
412
413    def __getitem__(self, address):
414        return MemoryOperand(address, self.size, broadcast=self.broadcast)
415
416
417class RIPRelativeOffset:
418    def __init__(self, offset):
419        import peachpy.util
420        if not peachpy.util.is_sint32(offset):
421            raise ValueError("RIP-relative offset must be a 32-bit signed integer")
422        self.offset = offset
423
424    def __add__(self, extra_offset):
425        return RIPRelativeOffset(self.offset + extra_offset)
426
427    def __sub__(self, extra_offset):
428        return RIPRelativeOffset(self.offset - extra_offset)
429
430
431def is_al(operand):
432    from peachpy.x86_64.registers import GeneralPurposeRegister8, al
433    return isinstance(operand, GeneralPurposeRegister8) and (operand.is_virtual or operand == al)
434
435
436def is_cl(operand):
437    from peachpy.x86_64.registers import GeneralPurposeRegister8, cl
438    return isinstance(operand, GeneralPurposeRegister8) and (operand.is_virtual or operand == cl)
439
440
441def is_ax(operand):
442    from peachpy.x86_64.registers import GeneralPurposeRegister16, ax
443    return isinstance(operand, GeneralPurposeRegister16) and (operand.is_virtual or operand == ax)
444
445
446def is_eax(operand):
447    from peachpy.x86_64.registers import GeneralPurposeRegister32, eax
448    return isinstance(operand, GeneralPurposeRegister32) and (operand.is_virtual or operand == eax)
449
450
451def is_rax(operand):
452    from peachpy.x86_64.registers import GeneralPurposeRegister64, rax
453    return isinstance(operand, GeneralPurposeRegister64) and (operand.is_virtual or operand == rax)
454
455
456def is_xmm0(operand):
457    from peachpy.x86_64.registers import XMMRegister, xmm0
458    return isinstance(operand, XMMRegister) and (operand.is_virtual or operand == xmm0)
459
460
461def is_r8(operand):
462    import peachpy.x86_64.registers
463    return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister8)
464
465
466def is_r8rex(operand):
467    import peachpy.x86_64.registers
468    return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister8) and \
469        operand.physical_id >= 4
470
471
472def is_r8h(operand):
473    import peachpy.x86_64.registers
474    return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister8) and \
475        operand.mask == peachpy.x86_64.registers.GeneralPurposeRegister8._high_mask
476
477
478def is_r16(operand):
479    import peachpy.x86_64.registers
480    return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister16)
481
482
483def is_r32(operand):
484    import peachpy.x86_64.registers
485    return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister32)
486
487
488def is_r64(operand):
489    import peachpy.x86_64.registers
490    return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister64)
491
492
493def is_mm(operand):
494    import peachpy.x86_64.registers
495    return isinstance(operand, peachpy.x86_64.registers.MMXRegister)
496
497
498def is_xmm(operand):
499    import peachpy.x86_64.registers
500    return isinstance(operand, peachpy.x86_64.registers.XMMRegister) and \
501           (operand.physical_id is None or operand.physical_id < 16)
502
503
504def is_evex_xmm(operand):
505    import peachpy.x86_64.registers
506    return isinstance(operand, peachpy.x86_64.registers.XMMRegister)
507
508
509def is_xmmk(operand):
510    import peachpy.x86_64.registers
511    return isinstance(operand, peachpy.x86_64.registers.XMMRegister) or \
512        isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \
513        isinstance(operand.register, peachpy.x86_64.registers.XMMRegister) and \
514        not operand.mask.is_zeroing
515
516
517def is_xmmkz(operand):
518    import peachpy.x86_64.registers
519    return isinstance(operand, peachpy.x86_64.registers.XMMRegister) or \
520        isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \
521        isinstance(operand.register, peachpy.x86_64.registers.XMMRegister)
522
523
524def is_ymm(operand):
525    import peachpy.x86_64.registers
526    return isinstance(operand, peachpy.x86_64.registers.YMMRegister) and \
527           (operand.physical_id is None or operand.physical_id < 16)
528
529
530def is_evex_ymm(operand):
531    import peachpy.x86_64.registers
532    return isinstance(operand, peachpy.x86_64.registers.YMMRegister)
533
534
535def is_ymmk(operand):
536    import peachpy.x86_64.registers
537    return isinstance(operand, peachpy.x86_64.registers.YMMRegister) or \
538        isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \
539        isinstance(operand.register, peachpy.x86_64.registers.YMMRegister) and \
540        not operand.mask.is_zeroing
541
542
543def is_ymmkz(operand):
544    import peachpy.x86_64.registers
545    return isinstance(operand, peachpy.x86_64.registers.YMMRegister) or \
546        isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \
547        isinstance(operand.register, peachpy.x86_64.registers.YMMRegister)
548
549
550def is_zmm(operand):
551    import peachpy.x86_64.registers
552    return isinstance(operand, peachpy.x86_64.registers.ZMMRegister)
553
554
555def is_zmmk(operand):
556    import peachpy.x86_64.registers
557    return isinstance(operand, peachpy.x86_64.registers.ZMMRegister) or \
558        isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \
559        isinstance(operand.register, peachpy.x86_64.registers.ZMMRegister) and \
560        not operand.mask.is_zeroing
561
562
563def is_zmmkz(operand):
564    import peachpy.x86_64.registers
565    return isinstance(operand, peachpy.x86_64.registers.ZMMRegister) or \
566        isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \
567        isinstance(operand.register, peachpy.x86_64.registers.ZMMRegister)
568
569
570def is_k(operand):
571    import peachpy.x86_64.registers
572    return isinstance(operand, peachpy.x86_64.registers.KRegister)
573
574
575def is_kk(operand):
576    import peachpy.x86_64.registers
577    return isinstance(operand, peachpy.x86_64.registers.KRegister) or \
578        isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \
579        isinstance(operand.register, peachpy.x86_64.registers.KRegister) and \
580        not operand.mask.is_zeroing
581
582
583def is_m(operand):
584    if not isinstance(operand, MemoryOperand) or operand.mask is not None or operand.broadcast is not None:
585        return False
586    # Check that the operand does not use vector index
587    from peachpy.x86_64.registers import GeneralPurposeRegister
588    return isinstance(operand.address, RIPRelativeOffset) or \
589        operand.address.index is None or isinstance(operand.address.index, GeneralPurposeRegister)
590
591
592def is_mk(operand):
593    if not isinstance(operand, MemoryOperand) or operand.broadcast is not None:
594        return False
595    # Check that the no zero-masking applied to the operand
596    if operand.mask is not None and operand.mask.is_zeroing:
597        return False
598    # Check that the operand does not use vector index
599    from peachpy.x86_64.registers import GeneralPurposeRegister
600    return operand.address.index is None or isinstance(operand.address.index, GeneralPurposeRegister)
601
602
603def is_mkz(operand):
604    if not isinstance(operand, MemoryOperand) or operand.broadcast is not None:
605        return False
606    # Check that the operand does not use vector index
607    from peachpy.x86_64.registers import GeneralPurposeRegister
608    return operand.address.index is None or isinstance(operand.address.index, GeneralPurposeRegister)
609
610
611def is_vmx(operand):
612    from peachpy.x86_64.registers import XMMRegister
613    return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, XMMRegister) and \
614        (operand.address.index is None or operand.address.index.physical_id < 16) and \
615        operand.mask is None
616
617
618def is_evex_vmx(operand):
619    from peachpy.x86_64.registers import XMMRegister
620    return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, XMMRegister) and \
621        operand.mask is None
622
623
624def is_vmxk(operand):
625    from peachpy.x86_64.registers import XMMRegister
626    return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, XMMRegister)
627
628
629def is_vmy(operand):
630    from peachpy.x86_64.registers import YMMRegister
631    return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, YMMRegister) and \
632        (operand.address.index is None or operand.address.index.physical_id < 16) and \
633        operand.mask is None
634
635
636def is_evex_vmy(operand):
637    from peachpy.x86_64.registers import YMMRegister
638    return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, YMMRegister) and \
639        operand.mask is None
640
641
642def is_vmyk(operand):
643    from peachpy.x86_64.registers import YMMRegister
644    return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, YMMRegister)
645
646
647def is_vmz(operand):
648    from peachpy.x86_64.registers import ZMMRegister
649    return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, ZMMRegister) and \
650        operand.mask is None
651
652
653def is_vmzk(operand):
654    from peachpy.x86_64.registers import ZMMRegister
655    return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, ZMMRegister)
656
657
658def is_m8(operand, strict=False):
659    return is_m(operand) and (operand.size is None and not strict or operand.size == 1)
660
661
662def is_m16(operand, strict=False):
663    import peachpy.literal
664    return is_m(operand) and (operand.size is None and not strict or operand.size == 2) or \
665        isinstance(operand, peachpy.literal.Constant) and operand.size == 2
666
667
668def is_m16kz(operand):
669    return is_mkz(operand) and (operand.size is None or operand.size == 2)
670
671
672def is_m32(operand, strict=False):
673    import peachpy.literal
674    return is_m(operand) and (operand.size is None and not strict or operand.size == 4) or \
675        isinstance(operand, peachpy.literal.Constant) and operand.size == 4
676
677
678def is_m32k(operand):
679    return is_mk(operand) and (operand.size is None or operand.size == 4)
680
681
682def is_m32kz(operand):
683    return is_mkz(operand) and (operand.size is None or operand.size == 4)
684
685
686def is_m64(operand, strict=False):
687    import peachpy.literal
688    return is_m(operand) and (operand.size is None and not strict or operand.size == 8) or \
689        isinstance(operand, peachpy.literal.Constant) and operand.size == 8
690
691
692def is_m64k(operand):
693    return is_mk(operand) and (operand.size is None or operand.size == 8)
694
695
696def is_m64kz(operand):
697    return is_mkz(operand) and (operand.size is None or operand.size == 8)
698
699
700def is_m80(operand, strict=False):
701    return is_m(operand) and (operand.size is None and not strict or operand.size == 10)
702
703
704def is_m128(operand, strict=False):
705    import peachpy.literal
706    return is_m(operand) and (operand.size is None and not strict or operand.size == 16) or \
707        isinstance(operand, peachpy.literal.Constant) and operand.size == 16
708
709
710def is_m128kz(operand):
711    return is_mkz(operand) and (operand.size is None or operand.size == 16)
712
713
714def is_m256(operand, strict=False):
715    import peachpy.literal
716    return is_m(operand) and (operand.size is None and not strict or operand.size == 32) or \
717        isinstance(operand, peachpy.literal.Constant) and operand.size == 32
718
719
720def is_m256kz(operand):
721    return is_mkz(operand) and (operand.size is None or operand.size == 32)
722
723
724def is_m512(operand, strict=False):
725    import peachpy.literal
726    return is_m(operand) and (operand.size is None and not strict or operand.size == 64) or \
727        isinstance(operand, peachpy.literal.Constant) and operand.size == 64
728
729
730def is_m512kz(operand):
731    return is_mkz(operand) and (operand.size is None or operand.size == 64)
732
733
734def is_m64_m32bcst(operand):
735    return is_m64(operand) or isinstance(operand, MemoryOperand) and operand.size == 4 and operand.broadcast == 2
736
737
738def is_m128_m32bcst(operand):
739    return is_m128(operand) or isinstance(operand, MemoryOperand) and operand.size == 4 and operand.broadcast == 4
740
741
742def is_m256_m32bcst(operand):
743    return is_m256(operand) or isinstance(operand, MemoryOperand) and operand.size == 4 and operand.broadcast == 8
744
745
746def is_m512_m32bcst(operand):
747    return is_m512(operand) or isinstance(operand, MemoryOperand) and operand.size == 4 and operand.broadcast == 16
748
749
750def is_m128_m64bcst(operand):
751    return is_m128(operand) or isinstance(operand, MemoryOperand) and operand.size == 8 and operand.broadcast == 2
752
753
754def is_m256_m64bcst(operand):
755    return is_m256(operand) or isinstance(operand, MemoryOperand) and operand.size == 8 and operand.broadcast == 4
756
757
758def is_m512_m64bcst(operand):
759    return is_m512(operand) or isinstance(operand, MemoryOperand) and operand.size == 8 and operand.broadcast == 8
760
761
762def is_m32bcst(operand):
763    return False
764
765
766def is_m64bcst(operand):
767    return False
768
769
770def is_imm(operand):
771    import peachpy.util
772    return peachpy.util.is_int(operand)
773
774
775def is_imm4(operand):
776    import peachpy.util
777    return peachpy.util.is_int(operand) and 0 <= operand <= 15
778
779
780def is_imm8(operand, ext_size=None):
781    import peachpy.util
782    if ext_size is None:
783        return peachpy.util.is_int8(operand)
784    else:
785        sup = 2**(8*ext_size)
786        return peachpy.util.is_int(operand) and \
787            (-128 <= operand <= 127 or sup - 128 <= operand < sup)
788
789
790def is_imm16(operand, ext_size=None):
791    import peachpy.util
792    if ext_size is None:
793        return peachpy.util.is_int16(operand)
794    else:
795        sup = 2**(8*ext_size)
796        return peachpy.util.is_int(operand) and \
797            (-32768 <= operand <= 32767 or sup - 32768 <= operand < sup)
798
799
800def is_imm32(operand, ext_size=None):
801    import peachpy.util
802    if ext_size is None:
803        return peachpy.util.is_int32(operand)
804    else:
805        sup = 2**(8*ext_size)
806        return peachpy.util.is_int(operand) and \
807            (-2147483648 <= operand <= 2147483647 or sup - 2147483648 <= operand < sup)
808
809
810def is_imm64(operand):
811    import peachpy.util
812    return peachpy.util.is_int64(operand)
813
814
815def is_rel8(operand):
816    from peachpy.util import is_sint8
817    return isinstance(operand, RIPRelativeOffset) and is_sint8(operand.offset)
818
819
820def is_rel32(operand):
821    from peachpy.util import is_sint32
822    return isinstance(operand, RIPRelativeOffset) and is_sint32(operand.offset)
823
824
825def is_label(operand):
826    import peachpy.x86_64.pseudo
827    return isinstance(operand, peachpy.x86_64.pseudo.Label)
828
829
830def is_er(operand):
831    return isinstance(operand, RoundingControl)
832
833
834def is_sae(operand):
835    return isinstance(operand, SuppressAllExceptions)
836
837
838byte = SizeSpecification(1)
839word = SizeSpecification(2)
840dword = SizeSpecification(4)
841qword = SizeSpecification(8)
842tword = SizeSpecification(10)
843oword = SizeSpecification(16)
844hword = SizeSpecification(32)
845yword = SizeSpecification(32)
846zword = SizeSpecification(64)
847
848
849class RoundingControl:
850    def __init__(self, name, code):
851        self.name = name
852        self.code = code
853
854    def __hash__(self):
855        return hash(self.name)
856
857    def __eq__(self, other):
858        return isinstance(other, RoundingControl) and other.name == self.name and other.code == self.code
859
860    def __ne__(self, other):
861        return not isinstance(other, RoundingControl) or other.name != self.name or other.code != self.code
862
863    def __str__(self):
864        return "{" + self.name + "}"
865
866
867class SuppressAllExceptions:
868    def __init__(self, name):
869        self.name = name
870
871    def __hash__(self):
872        return hash(self.name)
873
874    def __eq__(self, other):
875        return isinstance(other, SuppressAllExceptions) and other.name == self.name
876
877    def __ne__(self, other):
878        return not isinstance(other, SuppressAllExceptions) or other.name != self.name
879
880    def __str__(self):
881        return "{" + self.name + "}"
882
883
884rn_sae = RoundingControl("rn-sae", 0b00)
885rz_sae = RoundingControl("rz-sae", 0b11)
886ru_sae = RoundingControl("ru-sae", 0b10)
887rd_sae = RoundingControl("rd-sae", 0b01)
888sae = SuppressAllExceptions("sae")
889