package UnicornEngine;

use 5.014002;
use strict;
use warnings;
use Carp;
use Math::Int64;

require Exporter;
use AutoLoader;

our @ISA = qw(Exporter);

# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.

# This allows declaration	use UnicornEngine ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = ( 'all' => [ qw(
	UC_ARCH_ARM
	UC_ARCH_ARM64
	UC_ARCH_M68K
	UC_ARCH_MAX
	UC_ARCH_MIPS
	UC_ARCH_PPC
	UC_ARCH_SPARC
	UC_ARCH_X86
	UC_ERR_ARCH
	UC_ERR_ARG
	UC_ERR_EXCEPTION
	UC_ERR_FETCH_PROT
	UC_ERR_FETCH_UNALIGNED
	UC_ERR_FETCH_UNMAPPED
	UC_ERR_HANDLE
	UC_ERR_HOOK
	UC_ERR_HOOK_EXIST
	UC_ERR_INSN_INVALID
	UC_ERR_MAP
	UC_ERR_MODE
	UC_ERR_NOMEM
	UC_ERR_OK
	UC_ERR_READ_PROT
	UC_ERR_READ_UNALIGNED
	UC_ERR_READ_UNMAPPED
	UC_ERR_RESOURCE
	UC_ERR_VERSION
	UC_ERR_WRITE_PROT
	UC_ERR_WRITE_UNALIGNED
	UC_ERR_WRITE_UNMAPPED
	UC_HOOK_BLOCK
	UC_HOOK_CODE
	UC_HOOK_INSN
	UC_HOOK_INTR
	UC_HOOK_MEM_FETCH
	UC_HOOK_MEM_FETCH_PROT
	UC_HOOK_MEM_FETCH_UNMAPPED
	UC_HOOK_MEM_READ
	UC_HOOK_MEM_READ_PROT
	UC_HOOK_MEM_READ_UNMAPPED
	UC_HOOK_MEM_WRITE
	UC_HOOK_MEM_WRITE_PROT
	UC_HOOK_MEM_WRITE_UNMAPPED
	UC_MEM_FETCH
	UC_MEM_FETCH_PROT
	UC_MEM_FETCH_UNMAPPED
	UC_MEM_READ
	UC_MEM_READ_PROT
	UC_MEM_READ_UNMAPPED
	UC_MEM_WRITE
	UC_MEM_WRITE_PROT
	UC_MEM_WRITE_UNMAPPED
	UC_MODE_16
	UC_MODE_32
	UC_MODE_64
	UC_MODE_ARM
	UC_MODE_BIG_ENDIAN
	UC_MODE_LITTLE_ENDIAN
	UC_MODE_MCLASS
	UC_MODE_MICRO
	UC_MODE_MIPS3
	UC_MODE_MIPS32
	UC_MODE_MIPS32R6
	UC_MODE_MIPS64
	UC_MODE_PPC32
	UC_MODE_PPC64
	UC_MODE_QPX
	UC_MODE_SPARC32
	UC_MODE_SPARC64
	UC_MODE_THUMB
	UC_MODE_V8
	UC_MODE_V9
	UC_PROT_ALL
	UC_PROT_EXEC
	UC_PROT_NONE
	UC_PROT_READ
	UC_PROT_WRITE
	UC_QUERY_MODE
	UC_QUERY_PAGE_SIZE
    UC_HOOK_MEM_VALID
    UC_HOOK_MEM_INVALID
    UC_HOOK_MEM_PROT
    UC_HOOK_MEM_UNMAPPED
    UC_HOOK_MEM_READ_INVALID
    UC_HOOK_MEM_WRITE_INVALID
    UC_HOOK_MEM_FETCH_INVALID
	UC_X86_REG_AH UC_X86_REG_AL UC_X86_REG_AX UC_X86_REG_BH UC_X86_REG_BL
	UC_X86_REG_BP UC_X86_REG_BPL UC_X86_REG_BX UC_X86_REG_CH UC_X86_REG_CL
	UC_X86_REG_CS UC_X86_REG_CX UC_X86_REG_DH UC_X86_REG_DI UC_X86_REG_DIL
	UC_X86_REG_DL UC_X86_REG_DS UC_X86_REG_DX UC_X86_REG_EAX UC_X86_REG_EBP
	UC_X86_REG_EBX UC_X86_REG_ECX UC_X86_REG_EDI UC_X86_REG_EDX UC_X86_REG_EFLAGS
	UC_X86_REG_EIP UC_X86_REG_EIZ UC_X86_REG_ES UC_X86_REG_ESI UC_X86_REG_ESP
	UC_X86_REG_FPSW UC_X86_REG_FS UC_X86_REG_GS UC_X86_REG_IP UC_X86_REG_RAX
	UC_X86_REG_RBP UC_X86_REG_RBX UC_X86_REG_RCX UC_X86_REG_RDI UC_X86_REG_RDX
	UC_X86_REG_RIP UC_X86_REG_RIZ UC_X86_REG_RSI UC_X86_REG_RSP UC_X86_REG_SI
	UC_X86_REG_SIL UC_X86_REG_SP UC_X86_REG_SPL UC_X86_REG_SS UC_X86_REG_CR0
	UC_X86_REG_CR1 UC_X86_REG_CR2 UC_X86_REG_CR3 UC_X86_REG_CR4 UC_X86_REG_CR5
	UC_X86_REG_CR6 UC_X86_REG_CR7 UC_X86_REG_CR8 UC_X86_REG_CR9 UC_X86_REG_CR10
	UC_X86_REG_CR11 UC_X86_REG_CR12 UC_X86_REG_CR13 UC_X86_REG_CR14 UC_X86_REG_CR15
	UC_X86_REG_DR0 UC_X86_REG_DR1 UC_X86_REG_DR2 UC_X86_REG_DR3 UC_X86_REG_DR4
	UC_X86_REG_DR5 UC_X86_REG_DR6 UC_X86_REG_DR7 UC_X86_REG_DR8 UC_X86_REG_DR9
	UC_X86_REG_DR10 UC_X86_REG_DR11 UC_X86_REG_DR12 UC_X86_REG_DR13 UC_X86_REG_DR14
	UC_X86_REG_DR15 UC_X86_REG_FP0 UC_X86_REG_FP1 UC_X86_REG_FP2 UC_X86_REG_FP3
	UC_X86_REG_FP4 UC_X86_REG_FP5 UC_X86_REG_FP6 UC_X86_REG_FP7
	UC_X86_REG_K0 UC_X86_REG_K1 UC_X86_REG_K2 UC_X86_REG_K3 UC_X86_REG_K4
	UC_X86_REG_K5 UC_X86_REG_K6 UC_X86_REG_K7 UC_X86_REG_MM0 UC_X86_REG_MM1
	UC_X86_REG_MM2 UC_X86_REG_MM3 UC_X86_REG_MM4 UC_X86_REG_MM5 UC_X86_REG_MM6
	UC_X86_REG_MM7 UC_X86_REG_R8 UC_X86_REG_R9 UC_X86_REG_R10 UC_X86_REG_R11
	UC_X86_REG_R12 UC_X86_REG_R13 UC_X86_REG_R14 UC_X86_REG_R15
	UC_X86_REG_ST0 UC_X86_REG_ST1 UC_X86_REG_ST2 UC_X86_REG_ST3
	UC_X86_REG_ST4 UC_X86_REG_ST5 UC_X86_REG_ST6 UC_X86_REG_ST7
	UC_X86_REG_XMM0 UC_X86_REG_XMM1 UC_X86_REG_XMM2 UC_X86_REG_XMM3 UC_X86_REG_XMM4
	UC_X86_REG_XMM5 UC_X86_REG_XMM6 UC_X86_REG_XMM7 UC_X86_REG_XMM8 UC_X86_REG_XMM9
	UC_X86_REG_XMM10 UC_X86_REG_XMM11 UC_X86_REG_XMM12 UC_X86_REG_XMM13 UC_X86_REG_XMM14
	UC_X86_REG_XMM15 UC_X86_REG_XMM16 UC_X86_REG_XMM17 UC_X86_REG_XMM18 UC_X86_REG_XMM19
	UC_X86_REG_XMM20 UC_X86_REG_XMM21 UC_X86_REG_XMM22 UC_X86_REG_XMM23 UC_X86_REG_XMM24
	UC_X86_REG_XMM25 UC_X86_REG_XMM26 UC_X86_REG_XMM27 UC_X86_REG_XMM28 UC_X86_REG_XMM29
	UC_X86_REG_XMM30 UC_X86_REG_XMM31 UC_X86_REG_YMM0 UC_X86_REG_YMM1 UC_X86_REG_YMM2
	UC_X86_REG_YMM3 UC_X86_REG_YMM4 UC_X86_REG_YMM5 UC_X86_REG_YMM6 UC_X86_REG_YMM7
	UC_X86_REG_YMM8 UC_X86_REG_YMM9 UC_X86_REG_YMM10 UC_X86_REG_YMM11 UC_X86_REG_YMM12
	UC_X86_REG_YMM13 UC_X86_REG_YMM14 UC_X86_REG_YMM15 UC_X86_REG_YMM16 UC_X86_REG_YMM17
	UC_X86_REG_YMM18 UC_X86_REG_YMM19 UC_X86_REG_YMM20 UC_X86_REG_YMM21 UC_X86_REG_YMM22
	UC_X86_REG_YMM23 UC_X86_REG_YMM24 UC_X86_REG_YMM25 UC_X86_REG_YMM26 UC_X86_REG_YMM27
	UC_X86_REG_YMM28 UC_X86_REG_YMM29 UC_X86_REG_YMM30 UC_X86_REG_YMM31 UC_X86_REG_ZMM0
	UC_X86_REG_ZMM1 UC_X86_REG_ZMM2 UC_X86_REG_ZMM3 UC_X86_REG_ZMM4 UC_X86_REG_ZMM5
	UC_X86_REG_ZMM6 UC_X86_REG_ZMM7 UC_X86_REG_ZMM8 UC_X86_REG_ZMM9 UC_X86_REG_ZMM10
	UC_X86_REG_ZMM11 UC_X86_REG_ZMM12 UC_X86_REG_ZMM13 UC_X86_REG_ZMM14 UC_X86_REG_ZMM15
	UC_X86_REG_ZMM16 UC_X86_REG_ZMM17 UC_X86_REG_ZMM18 UC_X86_REG_ZMM19 UC_X86_REG_ZMM20
	UC_X86_REG_ZMM21 UC_X86_REG_ZMM22 UC_X86_REG_ZMM23 UC_X86_REG_ZMM24 UC_X86_REG_ZMM25
	UC_X86_REG_ZMM26 UC_X86_REG_ZMM27 UC_X86_REG_ZMM28 UC_X86_REG_ZMM29 UC_X86_REG_ZMM30
	UC_X86_REG_ZMM31 UC_X86_REG_R8B UC_X86_REG_R9B UC_X86_REG_R10B UC_X86_REG_R11B
	UC_X86_REG_R12B UC_X86_REG_R13B UC_X86_REG_R14B UC_X86_REG_R15B UC_X86_REG_R8D
	UC_X86_REG_R9D UC_X86_REG_R10D UC_X86_REG_R11D UC_X86_REG_R12D UC_X86_REG_R13D
	UC_X86_REG_R14D UC_X86_REG_R15D UC_X86_REG_R8W UC_X86_REG_R9W UC_X86_REG_R10W
	UC_X86_REG_R11W UC_X86_REG_R12W UC_X86_REG_R13W UC_X86_REG_R14W UC_X86_REG_R15W
	UC_X86_REG_IDTR UC_X86_REG_GDTR UC_X86_REG_LDTR UC_X86_REG_TR UC_X86_REG_FPCW
	UC_X86_REG_FPTAG
	UC_ARM_REG_APSR
	UC_ARM_REG_APSR_NZCV
	UC_ARM_REG_CPSR
	UC_ARM_REG_FPEXC
	UC_ARM_REG_FPINST
	UC_ARM_REG_FPSCR
	UC_ARM_REG_FPSCR_NZCV
	UC_ARM_REG_FPSID
	UC_ARM_REG_ITSTATE
	UC_ARM_REG_LR
	UC_ARM_REG_PC
	UC_ARM_REG_SP
	UC_ARM_REG_SPSR
	UC_ARM_REG_D0
	UC_ARM_REG_D1
	UC_ARM_REG_D2
	UC_ARM_REG_D3
	UC_ARM_REG_D4
	UC_ARM_REG_D5
	UC_ARM_REG_D6
	UC_ARM_REG_D7
	UC_ARM_REG_D8
	UC_ARM_REG_D9
	UC_ARM_REG_D10
	UC_ARM_REG_D11
	UC_ARM_REG_D12
	UC_ARM_REG_D13
	UC_ARM_REG_D14
	UC_ARM_REG_D15
	UC_ARM_REG_D16
	UC_ARM_REG_D17
	UC_ARM_REG_D18
	UC_ARM_REG_D19
	UC_ARM_REG_D20
	UC_ARM_REG_D21
	UC_ARM_REG_D22
	UC_ARM_REG_D23
	UC_ARM_REG_D24
	UC_ARM_REG_D25
	UC_ARM_REG_D26
	UC_ARM_REG_D27
	UC_ARM_REG_D28
	UC_ARM_REG_D29
	UC_ARM_REG_D30
	UC_ARM_REG_D31
	UC_ARM_REG_FPINST2
	UC_ARM_REG_MVFR0
	UC_ARM_REG_MVFR1
	UC_ARM_REG_MVFR2
	UC_ARM_REG_Q0
	UC_ARM_REG_Q1
	UC_ARM_REG_Q2
	UC_ARM_REG_Q3
	UC_ARM_REG_Q4
	UC_ARM_REG_Q5
	UC_ARM_REG_Q6
	UC_ARM_REG_Q7
	UC_ARM_REG_Q8
	UC_ARM_REG_Q9
	UC_ARM_REG_Q10
	UC_ARM_REG_Q11
	UC_ARM_REG_Q12
	UC_ARM_REG_Q13
	UC_ARM_REG_Q14
	UC_ARM_REG_Q15
	UC_ARM_REG_R0
	UC_ARM_REG_R1
	UC_ARM_REG_R2
	UC_ARM_REG_R3
	UC_ARM_REG_R4
	UC_ARM_REG_R5
	UC_ARM_REG_R6
	UC_ARM_REG_R7
	UC_ARM_REG_R8
	UC_ARM_REG_R9
	UC_ARM_REG_R10
	UC_ARM_REG_R11
	UC_ARM_REG_R12
	UC_ARM_REG_S0
	UC_ARM_REG_S1
	UC_ARM_REG_S2
	UC_ARM_REG_S3
	UC_ARM_REG_S4
	UC_ARM_REG_S5
	UC_ARM_REG_S6
	UC_ARM_REG_S7
	UC_ARM_REG_S8
	UC_ARM_REG_S9
	UC_ARM_REG_S10
	UC_ARM_REG_S11
	UC_ARM_REG_S12
	UC_ARM_REG_S13
	UC_ARM_REG_S14
	UC_ARM_REG_S15
	UC_ARM_REG_S16
	UC_ARM_REG_S17
	UC_ARM_REG_S18
	UC_ARM_REG_S19
	UC_ARM_REG_S20
	UC_ARM_REG_S21
	UC_ARM_REG_S22
	UC_ARM_REG_S23
	UC_ARM_REG_S24
	UC_ARM_REG_S25
	UC_ARM_REG_S26
	UC_ARM_REG_S27
	UC_ARM_REG_S28
	UC_ARM_REG_S29
	UC_ARM_REG_S30
	UC_ARM_REG_S31
	UC_ARM_REG_R13
	UC_ARM_REG_R14
	UC_ARM_REG_R15
	UC_ARM_REG_SB
	UC_ARM_REG_SL
	UC_ARM_REG_FP
	UC_ARM_REG_IP
) ]
);

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw(
	UC_ARCH_ARM
	UC_ARCH_ARM64
	UC_ARCH_M68K
	UC_ARCH_MAX
	UC_ARCH_MIPS
	UC_ARCH_PPC
	UC_ARCH_SPARC
	UC_ARCH_X86
	UC_ERR_ARCH
	UC_ERR_ARG
	UC_ERR_EXCEPTION
	UC_ERR_FETCH_PROT
	UC_ERR_FETCH_UNALIGNED
	UC_ERR_FETCH_UNMAPPED
	UC_ERR_HANDLE
	UC_ERR_HOOK
	UC_ERR_HOOK_EXIST
	UC_ERR_INSN_INVALID
	UC_ERR_MAP
	UC_ERR_MODE
	UC_ERR_NOMEM
	UC_ERR_OK
	UC_ERR_READ_PROT
	UC_ERR_READ_UNALIGNED
	UC_ERR_READ_UNMAPPED
	UC_ERR_RESOURCE
	UC_ERR_VERSION
	UC_ERR_WRITE_PROT
	UC_ERR_WRITE_UNALIGNED
	UC_ERR_WRITE_UNMAPPED
	UC_HOOK_BLOCK
	UC_HOOK_CODE
	UC_HOOK_INSN
	UC_HOOK_INTR
	UC_HOOK_MEM_FETCH
	UC_HOOK_MEM_FETCH_PROT
	UC_HOOK_MEM_FETCH_UNMAPPED
	UC_HOOK_MEM_READ
	UC_HOOK_MEM_READ_PROT
	UC_HOOK_MEM_READ_UNMAPPED
	UC_HOOK_MEM_WRITE
	UC_HOOK_MEM_WRITE_PROT
	UC_HOOK_MEM_WRITE_UNMAPPED
    UC_HOOK_MEM_VALID
    UC_HOOK_MEM_INVALID
    UC_HOOK_MEM_PROT
    UC_HOOK_MEM_UNMAPPED
    UC_HOOK_MEM_READ_INVALID
    UC_HOOK_MEM_WRITE_INVALID
    UC_HOOK_MEM_FETCH_INVALID
	UC_MEM_FETCH
	UC_MEM_FETCH_PROT
	UC_MEM_FETCH_UNMAPPED
	UC_MEM_READ
	UC_MEM_READ_PROT
	UC_MEM_READ_UNMAPPED
	UC_MEM_WRITE
	UC_MEM_WRITE_PROT
	UC_MEM_WRITE_UNMAPPED
	UC_MODE_16
	UC_MODE_32
	UC_MODE_64
	UC_MODE_ARM
	UC_MODE_BIG_ENDIAN
	UC_MODE_LITTLE_ENDIAN
	UC_MODE_MCLASS
	UC_MODE_MICRO
	UC_MODE_MIPS3
	UC_MODE_MIPS32
	UC_MODE_MIPS32R6
	UC_MODE_MIPS64
	UC_MODE_PPC32
	UC_MODE_PPC64
	UC_MODE_QPX
	UC_MODE_SPARC32
	UC_MODE_SPARC64
	UC_MODE_THUMB
	UC_MODE_V8
	UC_MODE_V9
	UC_PROT_ALL
	UC_PROT_EXEC
	UC_PROT_NONE
	UC_PROT_READ
	UC_PROT_WRITE
	UC_QUERY_MODE
	UC_QUERY_PAGE_SIZE
	UC_X86_REG_AH UC_X86_REG_AL UC_X86_REG_AX UC_X86_REG_BH UC_X86_REG_BL
	UC_X86_REG_BP UC_X86_REG_BPL UC_X86_REG_BX UC_X86_REG_CH UC_X86_REG_CL
	UC_X86_REG_CS UC_X86_REG_CX UC_X86_REG_DH UC_X86_REG_DI UC_X86_REG_DIL
	UC_X86_REG_DL UC_X86_REG_DS UC_X86_REG_DX UC_X86_REG_EAX UC_X86_REG_EBP
	UC_X86_REG_EBX UC_X86_REG_ECX UC_X86_REG_EDI UC_X86_REG_EDX UC_X86_REG_EFLAGS
	UC_X86_REG_EIP UC_X86_REG_EIZ UC_X86_REG_ES UC_X86_REG_ESI UC_X86_REG_ESP
	UC_X86_REG_FPSW UC_X86_REG_FS UC_X86_REG_GS UC_X86_REG_IP UC_X86_REG_RAX
	UC_X86_REG_RBP UC_X86_REG_RBX UC_X86_REG_RCX UC_X86_REG_RDI UC_X86_REG_RDX
	UC_X86_REG_RIP UC_X86_REG_RIZ UC_X86_REG_RSI UC_X86_REG_RSP UC_X86_REG_SI
	UC_X86_REG_SIL UC_X86_REG_SP UC_X86_REG_SPL UC_X86_REG_SS UC_X86_REG_CR0
	UC_X86_REG_CR1 UC_X86_REG_CR2 UC_X86_REG_CR3 UC_X86_REG_CR4 UC_X86_REG_CR5
	UC_X86_REG_CR6 UC_X86_REG_CR7 UC_X86_REG_CR8 UC_X86_REG_CR9 UC_X86_REG_CR10
	UC_X86_REG_CR11 UC_X86_REG_CR12 UC_X86_REG_CR13 UC_X86_REG_CR14 UC_X86_REG_CR15
	UC_X86_REG_DR0 UC_X86_REG_DR1 UC_X86_REG_DR2 UC_X86_REG_DR3 UC_X86_REG_DR4
	UC_X86_REG_DR5 UC_X86_REG_DR6 UC_X86_REG_DR7 UC_X86_REG_DR8 UC_X86_REG_DR9
	UC_X86_REG_DR10 UC_X86_REG_DR11 UC_X86_REG_DR12 UC_X86_REG_DR13 UC_X86_REG_DR14
	UC_X86_REG_DR15 UC_X86_REG_FP0 UC_X86_REG_FP1 UC_X86_REG_FP2 UC_X86_REG_FP3
	UC_X86_REG_FP4 UC_X86_REG_FP5 UC_X86_REG_FP6 UC_X86_REG_FP7
	UC_X86_REG_K0 UC_X86_REG_K1 UC_X86_REG_K2 UC_X86_REG_K3 UC_X86_REG_K4
	UC_X86_REG_K5 UC_X86_REG_K6 UC_X86_REG_K7 UC_X86_REG_MM0 UC_X86_REG_MM1
	UC_X86_REG_MM2 UC_X86_REG_MM3 UC_X86_REG_MM4 UC_X86_REG_MM5 UC_X86_REG_MM6
	UC_X86_REG_MM7 UC_X86_REG_R8 UC_X86_REG_R9 UC_X86_REG_R10 UC_X86_REG_R11
	UC_X86_REG_R12 UC_X86_REG_R13 UC_X86_REG_R14 UC_X86_REG_R15
	UC_X86_REG_ST0 UC_X86_REG_ST1 UC_X86_REG_ST2 UC_X86_REG_ST3
	UC_X86_REG_ST4 UC_X86_REG_ST5 UC_X86_REG_ST6 UC_X86_REG_ST7
	UC_X86_REG_XMM0 UC_X86_REG_XMM1 UC_X86_REG_XMM2 UC_X86_REG_XMM3 UC_X86_REG_XMM4
	UC_X86_REG_XMM5 UC_X86_REG_XMM6 UC_X86_REG_XMM7 UC_X86_REG_XMM8 UC_X86_REG_XMM9
	UC_X86_REG_XMM10 UC_X86_REG_XMM11 UC_X86_REG_XMM12 UC_X86_REG_XMM13 UC_X86_REG_XMM14
	UC_X86_REG_XMM15 UC_X86_REG_XMM16 UC_X86_REG_XMM17 UC_X86_REG_XMM18 UC_X86_REG_XMM19
	UC_X86_REG_XMM20 UC_X86_REG_XMM21 UC_X86_REG_XMM22 UC_X86_REG_XMM23 UC_X86_REG_XMM24
	UC_X86_REG_XMM25 UC_X86_REG_XMM26 UC_X86_REG_XMM27 UC_X86_REG_XMM28 UC_X86_REG_XMM29
	UC_X86_REG_XMM30 UC_X86_REG_XMM31 UC_X86_REG_YMM0 UC_X86_REG_YMM1 UC_X86_REG_YMM2
	UC_X86_REG_YMM3 UC_X86_REG_YMM4 UC_X86_REG_YMM5 UC_X86_REG_YMM6 UC_X86_REG_YMM7
	UC_X86_REG_YMM8 UC_X86_REG_YMM9 UC_X86_REG_YMM10 UC_X86_REG_YMM11 UC_X86_REG_YMM12
	UC_X86_REG_YMM13 UC_X86_REG_YMM14 UC_X86_REG_YMM15 UC_X86_REG_YMM16 UC_X86_REG_YMM17
	UC_X86_REG_YMM18 UC_X86_REG_YMM19 UC_X86_REG_YMM20 UC_X86_REG_YMM21 UC_X86_REG_YMM22
	UC_X86_REG_YMM23 UC_X86_REG_YMM24 UC_X86_REG_YMM25 UC_X86_REG_YMM26 UC_X86_REG_YMM27
	UC_X86_REG_YMM28 UC_X86_REG_YMM29 UC_X86_REG_YMM30 UC_X86_REG_YMM31 UC_X86_REG_ZMM0
	UC_X86_REG_ZMM1 UC_X86_REG_ZMM2 UC_X86_REG_ZMM3 UC_X86_REG_ZMM4 UC_X86_REG_ZMM5
	UC_X86_REG_ZMM6 UC_X86_REG_ZMM7 UC_X86_REG_ZMM8 UC_X86_REG_ZMM9 UC_X86_REG_ZMM10
	UC_X86_REG_ZMM11 UC_X86_REG_ZMM12 UC_X86_REG_ZMM13 UC_X86_REG_ZMM14 UC_X86_REG_ZMM15
	UC_X86_REG_ZMM16 UC_X86_REG_ZMM17 UC_X86_REG_ZMM18 UC_X86_REG_ZMM19 UC_X86_REG_ZMM20
	UC_X86_REG_ZMM21 UC_X86_REG_ZMM22 UC_X86_REG_ZMM23 UC_X86_REG_ZMM24 UC_X86_REG_ZMM25
	UC_X86_REG_ZMM26 UC_X86_REG_ZMM27 UC_X86_REG_ZMM28 UC_X86_REG_ZMM29 UC_X86_REG_ZMM30
	UC_X86_REG_ZMM31 UC_X86_REG_R8B UC_X86_REG_R9B UC_X86_REG_R10B UC_X86_REG_R11B
	UC_X86_REG_R12B UC_X86_REG_R13B UC_X86_REG_R14B UC_X86_REG_R15B UC_X86_REG_R8D
	UC_X86_REG_R9D UC_X86_REG_R10D UC_X86_REG_R11D UC_X86_REG_R12D UC_X86_REG_R13D
	UC_X86_REG_R14D UC_X86_REG_R15D UC_X86_REG_R8W UC_X86_REG_R9W UC_X86_REG_R10W
	UC_X86_REG_R11W UC_X86_REG_R12W UC_X86_REG_R13W UC_X86_REG_R14W UC_X86_REG_R15W
	UC_X86_REG_IDTR UC_X86_REG_GDTR UC_X86_REG_LDTR UC_X86_REG_TR UC_X86_REG_FPCW
	UC_X86_REG_FPTAG
	UC_ARM_REG_APSR
	UC_ARM_REG_APSR_NZCV
	UC_ARM_REG_CPSR
	UC_ARM_REG_FPEXC
	UC_ARM_REG_FPINST
	UC_ARM_REG_FPSCR
	UC_ARM_REG_FPSCR_NZCV
	UC_ARM_REG_FPSID
	UC_ARM_REG_ITSTATE
	UC_ARM_REG_LR
	UC_ARM_REG_PC
	UC_ARM_REG_SP
	UC_ARM_REG_SPSR
	UC_ARM_REG_D0
	UC_ARM_REG_D1
	UC_ARM_REG_D2
	UC_ARM_REG_D3
	UC_ARM_REG_D4
	UC_ARM_REG_D5
	UC_ARM_REG_D6
	UC_ARM_REG_D7
	UC_ARM_REG_D8
	UC_ARM_REG_D9
	UC_ARM_REG_D10
	UC_ARM_REG_D11
	UC_ARM_REG_D12
	UC_ARM_REG_D13
	UC_ARM_REG_D14
	UC_ARM_REG_D15
	UC_ARM_REG_D16
	UC_ARM_REG_D17
	UC_ARM_REG_D18
	UC_ARM_REG_D19
	UC_ARM_REG_D20
	UC_ARM_REG_D21
	UC_ARM_REG_D22
	UC_ARM_REG_D23
	UC_ARM_REG_D24
	UC_ARM_REG_D25
	UC_ARM_REG_D26
	UC_ARM_REG_D27
	UC_ARM_REG_D28
	UC_ARM_REG_D29
	UC_ARM_REG_D30
	UC_ARM_REG_D31
	UC_ARM_REG_FPINST2
	UC_ARM_REG_MVFR0
	UC_ARM_REG_MVFR1
	UC_ARM_REG_MVFR2
	UC_ARM_REG_Q0
	UC_ARM_REG_Q1
	UC_ARM_REG_Q2
	UC_ARM_REG_Q3
	UC_ARM_REG_Q4
	UC_ARM_REG_Q5
	UC_ARM_REG_Q6
	UC_ARM_REG_Q7
	UC_ARM_REG_Q8
	UC_ARM_REG_Q9
	UC_ARM_REG_Q10
	UC_ARM_REG_Q11
	UC_ARM_REG_Q12
	UC_ARM_REG_Q13
	UC_ARM_REG_Q14
	UC_ARM_REG_Q15
	UC_ARM_REG_R0
	UC_ARM_REG_R1
	UC_ARM_REG_R2
	UC_ARM_REG_R3
	UC_ARM_REG_R4
	UC_ARM_REG_R5
	UC_ARM_REG_R6
	UC_ARM_REG_R7
	UC_ARM_REG_R8
	UC_ARM_REG_R9
	UC_ARM_REG_R10
	UC_ARM_REG_R11
	UC_ARM_REG_R12
	UC_ARM_REG_S0
	UC_ARM_REG_S1
	UC_ARM_REG_S2
	UC_ARM_REG_S3
	UC_ARM_REG_S4
	UC_ARM_REG_S5
	UC_ARM_REG_S6
	UC_ARM_REG_S7
	UC_ARM_REG_S8
	UC_ARM_REG_S9
	UC_ARM_REG_S10
	UC_ARM_REG_S11
	UC_ARM_REG_S12
	UC_ARM_REG_S13
	UC_ARM_REG_S14
	UC_ARM_REG_S15
	UC_ARM_REG_S16
	UC_ARM_REG_S17
	UC_ARM_REG_S18
	UC_ARM_REG_S19
	UC_ARM_REG_S20
	UC_ARM_REG_S21
	UC_ARM_REG_S22
	UC_ARM_REG_S23
	UC_ARM_REG_S24
	UC_ARM_REG_S25
	UC_ARM_REG_S26
	UC_ARM_REG_S27
	UC_ARM_REG_S28
	UC_ARM_REG_S29
	UC_ARM_REG_S30
	UC_ARM_REG_S31
	UC_ARM_REG_R13
	UC_ARM_REG_R14
	UC_ARM_REG_R15
	UC_ARM_REG_SB
	UC_ARM_REG_SL
	UC_ARM_REG_FP
	UC_ARM_REG_IP
);

our $VERSION = '0.05';

sub AUTOLOAD {
    # This AUTOLOAD is used to 'autoload' constants from the constant()
    # XS function.

    my $constname;
    our $AUTOLOAD;
    ($constname = $AUTOLOAD) =~ s/.*:://;
    croak "&UnicornEngine::constant not defined" if $constname eq 'constant';
    my ($error, $val) = constant($constname);
    if ($error) { croak $error; }
    {
	no strict 'refs';
	# Fixed between 5.005_53 and 5.005_61
#XXX	if ($] >= 5.00561) {
#XXX	    *$AUTOLOAD = sub () { $val };
#XXX	}
#XXX	else {
	    *$AUTOLOAD = sub { $val };
#XXX	}
    }
    goto &$AUTOLOAD;
}

require XSLoader;
XSLoader::load('UnicornEngine', $VERSION);

# Preloaded methods go here.

sub new {
    my $cls = shift;
    my $class = ref($cls) || $cls;
    my %args = @_;
    my $self = bless({%args}, $class);
    unless ($args{arch} and $args{mode}) {
        warn "You need to specify the 'arch' and 'mode' arguments to this function";
        return undef;
    }
    my $obj = uc_perl_new($self, $args{arch}, $args{mode});
    return undef unless $obj;
    $self->{uc_perl} = $obj;
    return $self;
}

sub DESTROY {
    uc_perl_DESTROY($_[0]->{uc_perl}) if $_[0]->{uc_perl};
}

sub query {
    return uc_perl_query($_[0]->{uc_perl}, $_[1]);
}

sub errno {
    return uc_perl_errno($_[0]->{uc_perl});
}

sub reg_write {
    return uc_perl_reg_write($_[0]->{uc_perl}, $_[1], $_[2]);
}

sub reg_read {
    return uc_perl_reg_read($_[0]->{uc_perl}, $_[1]);
}

sub mem_map {
    return uc_perl_mem_map($_[0]->{uc_perl}, $_[1],
                            $_[2], $_[3] || UC_PROT_ALL());
}

sub mem_unmap {
    return uc_perl_mem_unmap($_[0]->{uc_perl}, $_[1], $_[2] - $_[1] + 1);
}

sub mem_protect {
    return uc_perl_mem_protect($_[0]->{uc_perl}, $_[1], $_[2], $_[3]);
}

sub mem_write {
    return uc_perl_mem_write($_[0]->{uc_perl}, $_[1], $_[2]);
}

sub mem_read {
    return uc_perl_mem_read($_[0]->{uc_perl}, $_[1]);
}

sub mem_regions {
    return uc_perl_mem_regions($_[0]->{uc_perl});
}

sub emu_start {
    my $self = shift;
    my %args = @_;
    unless (defined $args{begin} and defined $args{end}) {
        warn "You need to specify the 'begin' and 'end' address values to this function";
        return undef;
    }
    return uc_perl_emu_start($self->{uc_perl},
            $args{begin}, $args{end}, $args{timeout_us} || 0,
            $args{count} || 0);
}

sub emu_stop {
    return uc_perl_emu_stop($_[0]->{uc_perl});
}


# Autoload methods go after =cut, and are processed by the autosplit program.

1;
__END__
# Below is stub documentation for your module. You'd better edit it!

=head1 NAME

UnicornEngine - Perl extension for Unicorn Engine from C<http://unicorn-engine.org>

=head1 SYNOPSIS

    use UnicornEngine;

    my $uc = UnicornEngine->new(arch => UC_ARCH_X86, mode => UC_MODE_32);
    my $addr = 0x80000000;
    $uc->mem_map($addr, 2 * 1024 * 1024);
    my $code = "\x31\xc9\x90\x90"; ## xor ecx, ecx; nop; nop;
    $uc->mem_write($addr, $code);
    $uce->reg_write(UC_X86_REG_ECX, 0xdeadbeef);
    $uce->emu_start(begin => $address, end => $addr + length($code));
    $uce->reg_read(UC_X86_REG_ECX);
    my $regions = $uc->mem_regions;
    foreach (@$regions) {
        $uce->mem_unmap($_->{begin}, $_->{end});
    }
      


=head1 DESCRIPTION

Refer documentation for UnicornEngine at C<http://unicorn-engine.org>

All constants are exported for X86 and ARM. SPARC/MIPS/ARM64/M68K not supported
yet.


=head1 SEE ALSO

L<Capstone>, L<Keystone>, L<Alien::UnicornEngine>

=head1 AUTHOR

Vikas N. Kumar, E<lt>vikas@cpan.org<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2016 by Vikas N. Kumar

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.14.2 or,
at your option, any later version of Perl 5 you may have available.


=cut
