# This file is auto-generated by /codegen/x86_64.py
# Instruction data is based on package opcodes 0.3.14

import inspect

import peachpy.stream
import peachpy.x86_64.options
import peachpy.x86_64.isa
from peachpy.util import is_sint8, is_sint32
from peachpy.x86_64.encoding import rex, optional_rex, vex2, vex3, evex, modrm_sib_disp
from peachpy.x86_64.instructions import Instruction, BranchInstruction
from peachpy.x86_64.operand import is_al, is_ax, is_eax, is_rax, is_cl, is_xmm0, is_r8, is_r8rex, is_r16, is_r32, is_r64, \
    is_mm, is_xmm, is_ymm, is_m, is_m8, is_m16, is_m32, is_m64, is_m80, is_m128, is_m256, is_m512, \
    is_evex_xmm, is_xmmk, is_xmmkz, is_evex_ymm, is_ymmk, is_ymmkz, is_zmm, is_zmmk, is_zmmkz, is_k, is_kk, \
    is_m32k, is_m64k, is_m16kz, is_m32kz, is_m64kz, is_m128kz, is_m256kz, is_m512kz, \
    is_m64_m32bcst, is_m128_m32bcst, is_m256_m32bcst, is_m512_m32bcst, \
    is_m128_m64bcst, is_m256_m64bcst, is_m512_m64bcst, \
    is_vmx, is_vmy, is_evex_vmx, is_evex_vmy, is_vmz, is_vmxk, is_vmyk, is_vmzk, \
    is_imm, is_imm4, is_imm8, is_imm16, is_imm32, is_imm64, \
    is_rel8, is_rel32, is_label, is_er, is_sae, check_operand, format_operand_type


class AESDEC(Instruction):
    """Perform One Round of an AES Decryption Flow"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * AESDEC(xmm, xmm/m128)    [AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(AESDEC, self).__init__("AESDEC", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"AESDEC\" requires 2 operands")
        self.go_name = "AESDEC"
        self.in_regs = (False, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: bytearray([0x66]) + optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xDE, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: bytearray([0x66]) + optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xDE]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: AESDEC " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class AESDECLAST(Instruction):
    """Perform Last Round of an AES Decryption Flow"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * AESDECLAST(xmm, xmm/m128)    [AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(AESDECLAST, self).__init__("AESDECLAST", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"AESDECLAST\" requires 2 operands")
        self.go_name = "AESDECLAST"
        self.in_regs = (False, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: bytearray([0x66]) + optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xDF, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: bytearray([0x66]) + optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xDF]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: AESDECLAST " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class AESENC(Instruction):
    """Perform One Round of an AES Encryption Flow"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * AESENC(xmm, xmm/m128)    [AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(AESENC, self).__init__("AESENC", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"AESENC\" requires 2 operands")
        self.go_name = "AESENC"
        self.in_regs = (True, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: bytearray([0x66]) + optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xDC, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: bytearray([0x66]) + optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xDC]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: AESENC " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class AESENCLAST(Instruction):
    """Perform Last Round of an AES Encryption Flow"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * AESENCLAST(xmm, xmm/m128)    [AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(AESENCLAST, self).__init__("AESENCLAST", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"AESENCLAST\" requires 2 operands")
        self.go_name = "AESENCLAST"
        self.in_regs = (True, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: bytearray([0x66]) + optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xDD, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: bytearray([0x66]) + optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xDD]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: AESENCLAST " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class AESIMC(Instruction):
    """Perform the AES InvMixColumn Transformation"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * AESIMC(xmm, xmm/m128)    [AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(AESIMC, self).__init__("AESIMC", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"AESIMC\" requires 2 operands")
        self.go_name = "AESIMC"
        self.in_regs = (False, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: bytearray([0x66]) + optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xDB, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: bytearray([0x66]) + optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xDB]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: AESIMC " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class AESKEYGENASSIST(Instruction):
    """AES Round Key Generation Assist"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * AESKEYGENASSIST(xmm, xmm/m128, imm8)    [AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(AESKEYGENASSIST, self).__init__("AESKEYGENASSIST", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 3:
            raise SyntaxError("Instruction \"AESKEYGENASSIST\" requires 3 operands")
        self.go_name = "AESKEYGENASSIST"
        self.in_regs = (False, True, False)
        self.out_regs = (True, False, False)
        self.out_operands = (True, False, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_imm(self.operands[2]):
            if not is_imm8(self.operands[2]):
                raise ValueError("Argument #2 can not be encoded as imm8")
            self.encodings.append((0x20, lambda op, rex=False: bytearray([0x66]) + optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x3A, 0xDF, 0xC0 | op[0].lcode << 3 | op[1].lcode, op[2] & 0xFF])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]) and is_imm(self.operands[2]):
            if not is_imm8(self.operands[2]):
                raise ValueError("Argument #2 can not be encoded as imm8")
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: bytearray([0x66]) + optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x3A, 0xDF]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp) + bytearray([op[2] & 0xFF])))
        else:
            raise SyntaxError("Invalid operand types: AESKEYGENASSIST " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class VAESDEC(Instruction):
    """Perform One Round of an AES Decryption Flow"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * VAESDEC(xmm, xmm, xmm/m128)    [AVX and AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(VAESDEC, self).__init__("VAESDEC", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 3:
            raise SyntaxError("Instruction \"VAESDEC\" requires 3 operands")
        self.in_regs = (False, True, True)
        self.out_regs = (True, False, False)
        self.out_operands = (True, False, False)
        self.avx_mode = True
        self.isa_extensions = frozenset([peachpy.x86_64.isa.avx, peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_xmm(self.operands[2]):
            self.encodings.append((0x00, lambda op: bytearray([0xC4, 0xE2 ^ (op[0].hcode << 7) ^ (op[2].hcode << 5), 0x79 ^ (op[1].hlcode << 3), 0xDE, 0xC0 | op[0].lcode << 3 | op[2].lcode])))
        elif is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_m128(self.operands[2]):
            self.encodings.append((0x10, lambda op, sib=False, min_disp=0: vex3(0xC4, 0b10, 0x01, op[0].hcode, op[2].address, op[1].hlcode) + bytearray([0xDE]) + modrm_sib_disp(op[0].lcode, op[2].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: VAESDEC " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class VAESDECLAST(Instruction):
    """Perform Last Round of an AES Decryption Flow"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * VAESDECLAST(xmm, xmm, xmm/m128)    [AVX and AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(VAESDECLAST, self).__init__("VAESDECLAST", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 3:
            raise SyntaxError("Instruction \"VAESDECLAST\" requires 3 operands")
        self.in_regs = (False, True, True)
        self.out_regs = (True, False, False)
        self.out_operands = (True, False, False)
        self.avx_mode = True
        self.isa_extensions = frozenset([peachpy.x86_64.isa.avx, peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_xmm(self.operands[2]):
            self.encodings.append((0x00, lambda op: bytearray([0xC4, 0xE2 ^ (op[0].hcode << 7) ^ (op[2].hcode << 5), 0x79 ^ (op[1].hlcode << 3), 0xDF, 0xC0 | op[0].lcode << 3 | op[2].lcode])))
        elif is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_m128(self.operands[2]):
            self.encodings.append((0x10, lambda op, sib=False, min_disp=0: vex3(0xC4, 0b10, 0x01, op[0].hcode, op[2].address, op[1].hlcode) + bytearray([0xDF]) + modrm_sib_disp(op[0].lcode, op[2].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: VAESDECLAST " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class VAESENC(Instruction):
    """Perform One Round of an AES Encryption Flow"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * VAESENC(xmm, xmm, xmm/m128)    [AVX and AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(VAESENC, self).__init__("VAESENC", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 3:
            raise SyntaxError("Instruction \"VAESENC\" requires 3 operands")
        self.in_regs = (False, True, True)
        self.out_regs = (True, False, False)
        self.out_operands = (True, False, False)
        self.avx_mode = True
        self.isa_extensions = frozenset([peachpy.x86_64.isa.avx, peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_xmm(self.operands[2]):
            self.encodings.append((0x00, lambda op: bytearray([0xC4, 0xE2 ^ (op[0].hcode << 7) ^ (op[2].hcode << 5), 0x79 ^ (op[1].hlcode << 3), 0xDC, 0xC0 | op[0].lcode << 3 | op[2].lcode])))
        elif is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_m128(self.operands[2]):
            self.encodings.append((0x10, lambda op, sib=False, min_disp=0: vex3(0xC4, 0b10, 0x01, op[0].hcode, op[2].address, op[1].hlcode) + bytearray([0xDC]) + modrm_sib_disp(op[0].lcode, op[2].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: VAESENC " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class VAESENCLAST(Instruction):
    """Perform Last Round of an AES Encryption Flow"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * VAESENCLAST(xmm, xmm, xmm/m128)    [AVX and AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(VAESENCLAST, self).__init__("VAESENCLAST", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 3:
            raise SyntaxError("Instruction \"VAESENCLAST\" requires 3 operands")
        self.in_regs = (False, True, True)
        self.out_regs = (True, False, False)
        self.out_operands = (True, False, False)
        self.avx_mode = True
        self.isa_extensions = frozenset([peachpy.x86_64.isa.avx, peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_xmm(self.operands[2]):
            self.encodings.append((0x00, lambda op: bytearray([0xC4, 0xE2 ^ (op[0].hcode << 7) ^ (op[2].hcode << 5), 0x79 ^ (op[1].hlcode << 3), 0xDD, 0xC0 | op[0].lcode << 3 | op[2].lcode])))
        elif is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_m128(self.operands[2]):
            self.encodings.append((0x10, lambda op, sib=False, min_disp=0: vex3(0xC4, 0b10, 0x01, op[0].hcode, op[2].address, op[1].hlcode) + bytearray([0xDD]) + modrm_sib_disp(op[0].lcode, op[2].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: VAESENCLAST " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class VAESIMC(Instruction):
    """Perform the AES InvMixColumn Transformation"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * VAESIMC(xmm, xmm/m128)    [AVX and AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(VAESIMC, self).__init__("VAESIMC", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"VAESIMC\" requires 2 operands")
        self.in_regs = (False, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = True
        self.isa_extensions = frozenset([peachpy.x86_64.isa.avx, peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x00, lambda op: bytearray([0xC4, 0xE2 ^ (op[0].hcode << 7) ^ (op[1].hcode << 5), 0x79, 0xDB, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x10, lambda op, sib=False, min_disp=0: vex3(0xC4, 0b10, 0x01, op[0].hcode, op[1].address) + bytearray([0xDB]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: VAESIMC " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class VAESKEYGENASSIST(Instruction):
    """AES Round Key Generation Assist"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * VAESKEYGENASSIST(xmm, xmm/m128, imm8)    [AVX and AES]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(VAESKEYGENASSIST, self).__init__("VAESKEYGENASSIST", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 3:
            raise SyntaxError("Instruction \"VAESKEYGENASSIST\" requires 3 operands")
        self.in_regs = (False, True, False)
        self.out_regs = (True, False, False)
        self.out_operands = (True, False, False)
        self.avx_mode = True
        self.isa_extensions = frozenset([peachpy.x86_64.isa.avx, peachpy.x86_64.isa.aes])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_imm(self.operands[2]):
            if not is_imm8(self.operands[2]):
                raise ValueError("Argument #2 can not be encoded as imm8")
            self.encodings.append((0x00, lambda op: bytearray([0xC4, 0xE3 ^ (op[0].hcode << 7) ^ (op[1].hcode << 5), 0x79, 0xDF, 0xC0 | op[0].lcode << 3 | op[1].lcode, op[2] & 0xFF])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]) and is_imm(self.operands[2]):
            if not is_imm8(self.operands[2]):
                raise ValueError("Argument #2 can not be encoded as imm8")
            self.encodings.append((0x10, lambda op, sib=False, min_disp=0: vex3(0xC4, 0b11, 0x01, op[0].hcode, op[1].address) + bytearray([0xDF]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp) + bytearray([op[2] & 0xFF])))
        else:
            raise SyntaxError("Invalid operand types: VAESKEYGENASSIST " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class SHA1MSG1(Instruction):
    """Perform an Intermediate Calculation for the Next Four SHA1 Message Doublewords"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * SHA1MSG1(xmm, xmm/m128)    [SHA]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(SHA1MSG1, self).__init__("SHA1MSG1", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"SHA1MSG1\" requires 2 operands")
        self.in_regs = (True, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.sha])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xC9, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xC9]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: SHA1MSG1 " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class SHA1MSG2(Instruction):
    """Perform a Final Calculation for the Next Four SHA1 Message Doublewords"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * SHA1MSG2(xmm, xmm/m128)    [SHA]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(SHA1MSG2, self).__init__("SHA1MSG2", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"SHA1MSG2\" requires 2 operands")
        self.in_regs = (True, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.sha])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xCA, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xCA]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: SHA1MSG2 " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class SHA1NEXTE(Instruction):
    """Calculate SHA1 State Variable E after Four Rounds"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * SHA1NEXTE(xmm, xmm/m128)    [SHA]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(SHA1NEXTE, self).__init__("SHA1NEXTE", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"SHA1NEXTE\" requires 2 operands")
        self.in_regs = (True, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.sha])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xC8, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xC8]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: SHA1NEXTE " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class SHA1RNDS4(Instruction):
    """Perform Four Rounds of SHA1 Operation"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * SHA1RNDS4(xmm, xmm/m128, imm8)    [SHA]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(SHA1RNDS4, self).__init__("SHA1RNDS4", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 3:
            raise SyntaxError("Instruction \"SHA1RNDS4\" requires 3 operands")
        self.in_regs = (True, True, False)
        self.out_regs = (True, False, False)
        self.out_operands = (True, False, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.sha])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_imm(self.operands[2]):
            if not is_imm8(self.operands[2]):
                raise ValueError("Argument #2 can not be encoded as imm8")
            self.encodings.append((0x20, lambda op, rex=False: optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x3A, 0xCC, 0xC0 | op[0].lcode << 3 | op[1].lcode, op[2] & 0xFF])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]) and is_imm(self.operands[2]):
            if not is_imm8(self.operands[2]):
                raise ValueError("Argument #2 can not be encoded as imm8")
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x3A, 0xCC]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp) + bytearray([op[2] & 0xFF])))
        else:
            raise SyntaxError("Invalid operand types: SHA1RNDS4 " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class SHA256MSG1(Instruction):
    """Perform an Intermediate Calculation for the Next Four SHA256 Message Doublewords"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * SHA256MSG1(xmm, xmm/m128)    [SHA]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(SHA256MSG1, self).__init__("SHA256MSG1", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"SHA256MSG1\" requires 2 operands")
        self.in_regs = (True, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.sha])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xCC, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xCC]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: SHA256MSG1 " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class SHA256MSG2(Instruction):
    """Perform a Final Calculation for the Next Four SHA256 Message Doublewords"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * SHA256MSG2(xmm, xmm/m128)    [SHA]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(SHA256MSG2, self).__init__("SHA256MSG2", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 2:
            raise SyntaxError("Instruction \"SHA256MSG2\" requires 2 operands")
        self.in_regs = (True, True)
        self.out_regs = (True, False)
        self.out_operands = (True, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.sha])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]):
            self.encodings.append((0x20, lambda op, rex=False: optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xCD, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xCD]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: SHA256MSG2 " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class SHA256RNDS2(Instruction):
    """Perform Two Rounds of SHA256 Operation"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * SHA256RNDS2(xmm, xmm/m128, xmm0)    [SHA]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(SHA256RNDS2, self).__init__("SHA256RNDS2", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 3:
            raise SyntaxError("Instruction \"SHA256RNDS2\" requires 3 operands")
        self.in_regs = (True, True, True)
        self.out_regs = (True, False, False)
        self.out_operands = (True, False, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.sha])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_xmm0(self.operands[2]):
            self.encodings.append((0x20, lambda op, rex=False: optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x38, 0xCB, 0xC0 | op[0].lcode << 3 | op[1].lcode])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]) and is_xmm0(self.operands[2]):
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x38, 0xCB]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp)))
        else:
            raise SyntaxError("Invalid operand types: SHA256RNDS2 " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class PCLMULQDQ(Instruction):
    """Carry-Less Quadword Multiplication"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * PCLMULQDQ(xmm, xmm/m128, imm8)    [PCLMULQDQ]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(PCLMULQDQ, self).__init__("PCLMULQDQ", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 3:
            raise SyntaxError("Instruction \"PCLMULQDQ\" requires 3 operands")
        self.go_name = "PCLMULQDQ"
        self.in_regs = (True, True, False)
        self.out_regs = (True, False, False)
        self.out_operands = (True, False, False)
        self.avx_mode = False
        self.isa_extensions = frozenset([peachpy.x86_64.isa.pclmulqdq])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_imm(self.operands[2]):
            if not is_imm8(self.operands[2]):
                raise ValueError("Argument #2 can not be encoded as imm8")
            self.encodings.append((0x20, lambda op, rex=False: bytearray([0x66]) + optional_rex(op[0].hcode, op[1], rex) + bytearray([0x0F, 0x3A, 0x44, 0xC0 | op[0].lcode << 3 | op[1].lcode, op[2] & 0xFF])))
        elif is_xmm(self.operands[0]) and is_m128(self.operands[1]) and is_imm(self.operands[2]):
            if not is_imm8(self.operands[2]):
                raise ValueError("Argument #2 can not be encoded as imm8")
            self.encodings.append((0x30, lambda op, rex=False, sib=False, min_disp=0: bytearray([0x66]) + optional_rex(op[0].hcode, op[1].address, rex) + bytearray([0x0F, 0x3A, 0x44]) + modrm_sib_disp(op[0].lcode, op[1].address, sib, min_disp) + bytearray([op[2] & 0xFF])))
        else:
            raise SyntaxError("Invalid operand types: PCLMULQDQ " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class VPCLMULQDQ(Instruction):
    """Carry-Less Quadword Multiplication"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * VPCLMULQDQ(xmm, xmm, xmm/m128, imm8)    [AVX and PCLMULQDQ]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(VPCLMULQDQ, self).__init__("VPCLMULQDQ", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 4:
            raise SyntaxError("Instruction \"VPCLMULQDQ\" requires 4 operands")
        self.in_regs = (False, True, True, False)
        self.out_regs = (True, False, False, False)
        self.out_operands = (True, False, False, False)
        self.avx_mode = True
        self.isa_extensions = frozenset([peachpy.x86_64.isa.avx, peachpy.x86_64.isa.pclmulqdq])
        if is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_xmm(self.operands[2]) and is_imm(self.operands[3]):
            if not is_imm8(self.operands[3]):
                raise ValueError("Argument #3 can not be encoded as imm8")
            self.encodings.append((0x00, lambda op: bytearray([0xC4, 0xE3 ^ (op[0].hcode << 7) ^ (op[2].hcode << 5), 0x79 ^ (op[1].hlcode << 3), 0x44, 0xC0 | op[0].lcode << 3 | op[2].lcode, op[3] & 0xFF])))
        elif is_xmm(self.operands[0]) and is_xmm(self.operands[1]) and is_m128(self.operands[2]) and is_imm(self.operands[3]):
            if not is_imm8(self.operands[3]):
                raise ValueError("Argument #3 can not be encoded as imm8")
            self.encodings.append((0x10, lambda op, sib=False, min_disp=0: vex3(0xC4, 0b11, 0x01, op[0].hcode, op[2].address, op[1].hlcode) + bytearray([0x44]) + modrm_sib_disp(op[0].lcode, op[2].address, sib, min_disp) + bytearray([op[3] & 0xFF])))
        else:
            raise SyntaxError("Invalid operand types: VPCLMULQDQ " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class RDRAND(Instruction):
    """Read Random Number"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * RDRAND(r16)    [RDRAND]
            * RDRAND(r32)    [RDRAND]
            * RDRAND(r64)    [RDRAND]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(RDRAND, self).__init__("RDRAND", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 1:
            raise SyntaxError("Instruction \"RDRAND\" requires 1 operands")
        self.in_regs = (False,)
        self.out_regs = (True,)
        self.out_operands = (True,)
        self.isa_extensions = frozenset([peachpy.x86_64.isa.rdrand])
        if is_r16(self.operands[0]):
            self.encodings.append((0x20, lambda op, rex=False: bytearray([0x66]) + optional_rex(0, op[0], rex) + bytearray([0x0F, 0xC7, 0xF0 | op[0].lcode])))
        elif is_r32(self.operands[0]):
            self.encodings.append((0x20, lambda op, rex=False: optional_rex(0, op[0], rex) + bytearray([0x0F, 0xC7, 0xF0 | op[0].lcode])))
        elif is_r64(self.operands[0]):
            self.encodings.append((0x00, lambda op: bytearray([0x48 | op[0].hcode, 0x0F, 0xC7, 0xF0 | op[0].lcode])))
        else:
            raise SyntaxError("Invalid operand types: RDRAND " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


class RDSEED(Instruction):
    """Read Random SEED"""

    def __init__(self, *args, **kwargs):
        """Supported forms:

            * RDSEED(r16)    [RDSEED]
            * RDSEED(r32)    [RDSEED]
            * RDSEED(r64)    [RDSEED]
        """

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(RDSEED, self).__init__("RDSEED", origin=origin, prototype=prototype)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) != 1:
            raise SyntaxError("Instruction \"RDSEED\" requires 1 operands")
        self.in_regs = (False,)
        self.out_regs = (True,)
        self.out_operands = (True,)
        self.isa_extensions = frozenset([peachpy.x86_64.isa.rdseed])
        if is_r16(self.operands[0]):
            self.encodings.append((0x20, lambda op, rex=False: bytearray([0x66]) + optional_rex(0, op[0], rex) + bytearray([0x0F, 0xC7, 0xF8 | op[0].lcode])))
        elif is_r32(self.operands[0]):
            self.encodings.append((0x20, lambda op, rex=False: optional_rex(0, op[0], rex) + bytearray([0x0F, 0xC7, 0xF8 | op[0].lcode])))
        elif is_r64(self.operands[0]):
            self.encodings.append((0x00, lambda op: bytearray([0x48 | op[0].hcode, 0x0F, 0xC7, 0xF8 | op[0].lcode])))
        else:
            raise SyntaxError("Invalid operand types: RDSEED " + ", ".join(map(format_operand_type, self.operands)))
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)


