python: initial Python3 support
diff --git a/bindings/const_generator.py b/bindings/const_generator.py
index 4c00edc..bfd0538 100644
--- a/bindings/const_generator.py
+++ b/bindings/const_generator.py
@@ -1,6 +1,6 @@
 # Capstone Disassembler Engine
 # By Dang Hoang Vu, 2013
-
+from __future__ import print_function
 import sys, re
 
 INCL_DIR = '../include/'
@@ -77,7 +77,7 @@
 
                 if f[0].startswith(prefix.upper()):
                     if len(f) > 1 and f[1] not in '//=':
-                        print "Error: Unable to convert %s" % f
+                        print("Error: Unable to convert %s" % f)
                         continue
                     elif len(f) > 1 and f[1] == '=':
                         rhs = ''.join(f[2:])
@@ -105,6 +105,6 @@
 
 if __name__ == "__main__":
     if len(sys.argv) < 2:
-        print "Usage:", sys.argv[0], " <bindings: java|python>"
+        print("Usage:", sys.argv[0], " <bindings: java|python>")
         sys.exit(1)
     main()
diff --git a/bindings/python/capstone/__init__.py b/bindings/python/capstone/__init__.py
index b69633e..2ce3eb9 100644
--- a/bindings/python/capstone/__init__.py
+++ b/bindings/python/capstone/__init__.py
@@ -1 +1,802 @@
-from capstone import Cs, CsError, cs_disasm_quick, cs_disasm_lite, cs_version, cs_support, version_bind, debug, CS_API_MAJOR, CS_API_MINOR, CS_ARCH_ARM, CS_ARCH_ARM64, CS_ARCH_MIPS, CS_ARCH_X86, CS_ARCH_PPC, CS_ARCH_SPARC, CS_ARCH_SYSZ, CS_ARCH_ALL, CS_MODE_LITTLE_ENDIAN, CS_MODE_ARM, CS_MODE_THUMB, CS_OPT_SYNTAX, CS_OPT_SYNTAX_DEFAULT, CS_OPT_SYNTAX_INTEL, CS_OPT_SYNTAX_ATT, CS_OPT_SYNTAX_NOREGNAME, CS_OPT_DETAIL, CS_OPT_ON, CS_OPT_OFF, CS_MODE_16, CS_MODE_32, CS_MODE_64, CS_MODE_BIG_ENDIAN, CS_MODE_MICRO, CS_MODE_N64, CS_MODE_V9, CS_SUPPORT_DIET, CS_SUPPORT_X86_REDUCE, CS_SKIPDATA_CALLBACK
+# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
+import sys
+_python2 = sys.version_info.major < 3
+if _python2:
+    range = xrange
+from capstone import arm, arm64, mips, ppc, sparc, systemz, x86
+
+__all__ = [
+    'Cs',
+    'CsInsn',
+
+    'cs_disasm_quick',
+    'cs_version',
+    'cs_support',
+    'version_bind',
+    'debug',
+
+    'CS_API_MAJOR',
+    'CS_API_MINOR',
+
+    'CS_ARCH_ARM',
+    'CS_ARCH_ARM64',
+    'CS_ARCH_MIPS',
+    'CS_ARCH_X86',
+    'CS_ARCH_PPC',
+    'CS_ARCH_SPARC',
+    'CS_ARCH_SYSZ',
+    'CS_ARCH_ALL',
+
+    'CS_MODE_LITTLE_ENDIAN',
+    'CS_MODE_BIG_ENDIAN',
+    'CS_MODE_16',
+    'CS_MODE_32',
+    'CS_MODE_64',
+    'CS_MODE_ARM',
+    'CS_MODE_THUMB',
+    'CS_MODE_MICRO',
+    'CS_MODE_N64',
+    'CS_MODE_V9',
+
+    'CS_OPT_SYNTAX',
+    'CS_OPT_SYNTAX_DEFAULT',
+    'CS_OPT_SYNTAX_INTEL',
+    'CS_OPT_SYNTAX_ATT',
+    'CS_OPT_SYNTAX_NOREGNAME',
+
+    'CS_OPT_DETAIL',
+    'CS_OPT_MODE',
+    'CS_OPT_ON',
+    'CS_OPT_OFF',
+
+    'CS_ERR_OK',
+    'CS_ERR_MEM',
+    'CS_ERR_ARCH',
+    'CS_ERR_HANDLE',
+    'CS_ERR_CSH',
+    'CS_ERR_MODE',
+    'CS_ERR_OPTION',
+    'CS_ERR_DETAIL',
+    'CS_ERR_VERSION',
+    'CS_ERR_MEMSETUP',
+    'CS_ERR_DIET',
+    'CS_ERR_SKIPDATA',
+
+    'CS_SUPPORT_DIET',
+    'CS_SUPPORT_X86_REDUCE',
+    'CS_SKIPDATA_CALLBACK',
+
+    'CsError',
+]
+
+# Capstone C interface
+
+# API version
+CS_API_MAJOR = 2
+CS_API_MINOR = 2
+
+# architectures
+CS_ARCH_ARM = 0
+CS_ARCH_ARM64 = 1
+CS_ARCH_MIPS = 2
+CS_ARCH_X86 = 3
+CS_ARCH_PPC = 4
+CS_ARCH_SPARC = 5
+CS_ARCH_SYSZ = 6
+CS_ARCH_MAX = 7
+CS_ARCH_ALL = 0xFFFF
+
+# disasm mode
+CS_MODE_LITTLE_ENDIAN = 0      # little-endian mode (default mode)
+CS_MODE_ARM = 0                # ARM mode
+CS_MODE_16 = (1 << 1)          # 16-bit mode (for X86, Mips)
+CS_MODE_32 = (1 << 2)          # 32-bit mode (for X86, Mips)
+CS_MODE_64 = (1 << 3)          # 64-bit mode (for X86, Mips)
+CS_MODE_THUMB = (1 << 4)       # ARM's Thumb mode, including Thumb-2
+CS_MODE_MICRO = (1 << 4)       # MicroMips mode (MIPS architecture)
+CS_MODE_N64 = (1 << 5)         # Nintendo-64 mode (MIPS architecture)
+CS_MODE_V9 = (1 << 4)          # Nintendo-64 mode (MIPS architecture)
+CS_MODE_BIG_ENDIAN = (1 << 31) # big-endian mode
+
+# Capstone option type
+CS_OPT_SYNTAX = 1    # Intel X86 asm syntax (CS_ARCH_X86 arch)
+CS_OPT_DETAIL = 2    # Break down instruction structure into details
+CS_OPT_MODE = 3      # Change engine's mode at run-time
+CS_OPT_MEM = 4       # Change engine's mode at run-time
+CS_OPT_SKIPDATA = 5  # Skip data when disassembling
+CS_OPT_SKIPDATA_SETUP = 6      # Setup user-defined function for SKIPDATA option
+
+# Capstone option value
+CS_OPT_OFF = 0             # Turn OFF an option - default option of CS_OPT_DETAIL
+CS_OPT_ON = 3              # Turn ON an option (CS_OPT_DETAIL)
+
+# Capstone syntax value
+CS_OPT_SYNTAX_DEFAULT = 0    # Default assembly syntax of all platforms (CS_OPT_SYNTAX)
+CS_OPT_SYNTAX_INTEL = 1    # Intel X86 asm syntax - default syntax on X86 (CS_OPT_SYNTAX, CS_ARCH_X86)
+CS_OPT_SYNTAX_ATT = 2      # ATT asm syntax (CS_OPT_SYNTAX, CS_ARCH_X86)
+CS_OPT_SYNTAX_NOREGNAME = 3   # Asm syntax prints register name with only number - (CS_OPT_SYNTAX, CS_ARCH_PPC, CS_ARCH_ARM)
+
+# Capstone error type
+CS_ERR_OK = 0      # No error: everything was fine
+CS_ERR_MEM = 1     # Out-Of-Memory error: cs_open(), cs_disasm_ex()
+CS_ERR_ARCH = 2    # Unsupported architecture: cs_open()
+CS_ERR_HANDLE = 3  # Invalid handle: cs_op_count(), cs_op_index()
+CS_ERR_CSH = 4     # Invalid csh argument: cs_close(), cs_errno(), cs_option()
+CS_ERR_MODE = 5    # Invalid/unsupported mode: cs_open()
+CS_ERR_OPTION = 6  # Invalid/unsupported option: cs_option()
+CS_ERR_DETAIL = 7  # Invalid/unsupported option: cs_option()
+CS_ERR_MEMSETUP = 8
+CS_ERR_VERSION = 9 # Unsupported version (bindings)
+CS_ERR_DIET = 10   # Information irrelevant in diet engine
+CS_ERR_SKIPDATA = 11 # Access irrelevant data for "data" instruction in SKIPDATA mode
+
+# query id for cs_support()
+CS_SUPPORT_DIET = CS_ARCH_ALL + 1
+CS_SUPPORT_X86_REDUCE = CS_ARCH_ALL+2
+
+
+import ctypes, ctypes.util, sys
+from os.path import split, join, dirname
+import distutils.sysconfig
+
+
+import inspect
+if not hasattr(sys.modules[__name__], '__file__'):
+    __file__ = inspect.getfile(inspect.currentframe())
+
+_lib_path = split(__file__)[0]
+_all_libs = ['libcapstone.dll', 'libcapstone.so', 'libcapstone.dylib']
+_found = False
+
+for _lib in _all_libs:
+    try:
+        _lib_file = join(_lib_path, _lib)
+        # print "Trying to load:", _lib_file
+        _cs = ctypes.cdll.LoadLibrary(_lib_file)
+        _found = True
+        break
+    except OSError:
+        pass
+if _found == False:
+    # try loading from default paths
+    for _lib in _all_libs:
+        try:
+            _cs = ctypes.cdll.LoadLibrary(_lib)
+            _found = True
+            break
+        except OSError:
+            pass
+
+if _found == False:
+    # last try: loading from python lib directory
+    _lib_path = distutils.sysconfig.get_python_lib()
+    for _lib in _all_libs:
+        try:
+            _lib_file = join(_lib_path, 'capstone', _lib)
+            # print "Trying to load:", _lib_file
+            _cs = ctypes.cdll.LoadLibrary(_lib_file)
+            _found = True
+            break
+        except OSError:
+            pass
+    if _found == False:
+        raise ImportError("ERROR: fail to load the dynamic library.")
+
+
+# low-level structure for C code
+class _cs_arch(ctypes.Union):
+    _fields_ = (
+        ('arm64', arm64.CsArm64),
+        ('arm', arm.CsArm),
+        ('mips', mips.CsMips),
+        ('x86', x86.CsX86),
+        ('ppc', ppc.CsPpc),
+        ('sparc', sparc.CsSparc),
+        ('sysz', systemz.CsSysz),
+    )
+
+class _cs_detail(ctypes.Structure):
+    _fields_ = (
+        ('regs_read', ctypes.c_ubyte * 12),
+        ('regs_read_count', ctypes.c_ubyte),
+        ('regs_write', ctypes.c_ubyte * 20),
+        ('regs_write_count', ctypes.c_ubyte),
+        ('groups', ctypes.c_ubyte * 8),
+        ('groups_count', ctypes.c_ubyte),
+        ('arch', _cs_arch),
+    )
+
+class _cs_insn(ctypes.Structure):
+    _fields_ = (
+        ('id', ctypes.c_uint),
+        ('address', ctypes.c_uint64),
+        ('size', ctypes.c_uint16),
+        ('bytes', ctypes.c_ubyte * 16),
+        ('mnemonic', ctypes.c_char * 32),
+        ('op_str', ctypes.c_char * 160),
+        ('detail', ctypes.POINTER(_cs_detail)),
+    )
+
+# callback for SKIPDATA option
+CS_SKIPDATA_CALLBACK = ctypes.CFUNCTYPE(ctypes.c_size_t, ctypes.c_size_t, ctypes.c_void_p)
+
+class _cs_opt_skipdata(ctypes.Structure):
+    _fields_ = (
+        ('mnemonic', ctypes.c_char_p),
+        ('callback', CS_SKIPDATA_CALLBACK),
+        ('user_data', ctypes.c_void_p),
+    )
+
+
+# setup all the function prototype
+def _setup_prototype(lib, fname, restype, *argtypes):
+    getattr(lib, fname).restype = restype
+    getattr(lib, fname).argtypes = argtypes
+
+_setup_prototype(_cs, "cs_open", ctypes.c_int, ctypes.c_uint, ctypes.c_uint, ctypes.POINTER(ctypes.c_size_t))
+_setup_prototype(_cs, "cs_disasm_ex", ctypes.c_size_t, ctypes.c_size_t, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t, \
+        ctypes.c_uint64, ctypes.c_size_t, ctypes.POINTER(ctypes.POINTER(_cs_insn)))
+_setup_prototype(_cs, "cs_free", None, ctypes.c_void_p, ctypes.c_size_t)
+_setup_prototype(_cs, "cs_close", ctypes.c_int, ctypes.POINTER(ctypes.c_size_t))
+_setup_prototype(_cs, "cs_reg_name", ctypes.c_char_p, ctypes.c_size_t, ctypes.c_uint)
+_setup_prototype(_cs, "cs_insn_name", ctypes.c_char_p, ctypes.c_size_t, ctypes.c_uint)
+_setup_prototype(_cs, "cs_op_count", ctypes.c_int, ctypes.c_size_t, ctypes.POINTER(_cs_insn), ctypes.c_uint)
+_setup_prototype(_cs, "cs_op_index", ctypes.c_int, ctypes.c_size_t, ctypes.POINTER(_cs_insn), ctypes.c_uint, ctypes.c_uint)
+_setup_prototype(_cs, "cs_errno", ctypes.c_int, ctypes.c_size_t)
+_setup_prototype(_cs, "cs_option", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p)
+_setup_prototype(_cs, "cs_version", ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
+_setup_prototype(_cs, "cs_support", ctypes.c_bool, ctypes.c_int)
+_setup_prototype(_cs, "cs_strerror", ctypes.c_char_p, ctypes.c_int)
+
+
+# access to error code via @errno of CsError
+class CsError(Exception):
+    def __init__(self, errno):
+        self.errno = errno
+
+    def __str__(self):
+        return _cs.cs_strerror(self.errno)
+
+
+# return the core's version
+def cs_version():
+    major = ctypes.c_int()
+    minor = ctypes.c_int()
+    combined = _cs.cs_version(ctypes.byref(major), ctypes.byref(minor))
+    return (major.value, minor.value, combined)
+
+
+# return the binding's version
+def version_bind():
+    return (CS_API_MAJOR, CS_API_MINOR, (CS_API_MAJOR << 8) + CS_API_MINOR)
+
+
+def cs_support(query):
+    return _cs.cs_support(query)
+
+
+# dummy class resembling Cs class, just for cs_disasm_quick()
+# this class only need to be referenced to via 2 fields: @csh & @arch
+class _dummy_cs(object):
+    def __init__(self, csh, arch):
+        self.csh = csh
+        self.arch = arch
+
+
+# Quick & dirty Python function to disasm raw binary code
+# This function return CsInsn objects
+# NOTE: you might want to use more efficient Cs class & its methods.
+def cs_disasm_quick(arch, mode, code, offset, count=0):
+    # verify version compatibility with the core before doing anything
+    (major, minor, _combined) = cs_version()
+    if major != CS_API_MAJOR or minor != CS_API_MINOR:
+        # our binding version is different from the core's API version
+        raise CsError(CS_ERR_VERSION)
+
+    csh = ctypes.c_size_t()
+    status = _cs.cs_open(arch, mode, ctypes.byref(csh))
+    if status != CS_ERR_OK:
+        raise CsError(status)
+
+    all_insn = ctypes.POINTER(_cs_insn)()
+    res = _cs.cs_disasm_ex(csh, code, len(code), offset, count, ctypes.byref(all_insn))
+    if res > 0:
+        for i in range(res):
+            yield CsInsn(_dummy_cs(csh, arch), all_insn[i])
+
+        _cs.cs_free(all_insn, res)
+    else:
+        status = _cs.cs_errno(csh)
+        if status != CS_ERR_OK:
+            raise CsError(status)
+        return
+        yield
+
+    status = _cs.cs_close(ctypes.byref(csh))
+    if status != CS_ERR_OK:
+        raise CsError(status)
+
+
+# Another quick, but lighter function to disasm raw binary code.
+# This function is faster than cs_disasm_quick() around 20% because
+# cs_disasm_lite() only return tuples of (address, size, mnemonic, op_str),
+# rather than CsInsn objects.
+# NOTE: you might want to use more efficient Cs class & its methods.
+def cs_disasm_lite(arch, mode, code, offset, count=0):
+    # verify version compatibility with the core before doing anything
+    (major, minor, _combined) = cs_version()
+    if major != CS_API_MAJOR or minor != CS_API_MINOR:
+        # our binding version is different from the core's API version
+        raise CsError(CS_ERR_VERSION)
+
+    if cs_support(CS_SUPPORT_DIET):
+        # Diet engine cannot provide @mnemonic & @op_str
+        raise CsError(CS_ERR_DIET)
+
+    csh = ctypes.c_size_t()
+    status = _cs.cs_open(arch, mode, ctypes.byref(csh))
+    if status != CS_ERR_OK:
+        raise CsError(status)
+
+    all_insn = ctypes.POINTER(_cs_insn)()
+    res = _cs.cs_disasm_ex(csh, code, len(code), offset, count, ctypes.byref(all_insn))
+    if res > 0:
+        for i in range(res):
+            insn = all_insn[i]
+            yield (insn.address, insn.size, insn.mnemonic, insn.op_str)
+
+        _cs.cs_free(all_insn, res)
+    else:
+        status = _cs.cs_errno(csh)
+        if status != CS_ERR_OK:
+            raise CsError(status)
+        return
+        yield
+
+    status = _cs.cs_close(ctypes.byref(csh))
+    if status != CS_ERR_OK:
+        raise CsError(status)
+
+
+# Python-style class to disasm code
+class CsInsn(object):
+    def __init__(self, cs, all_info):
+        self._raw = all_info
+        self._cs = cs
+
+    # return instruction's ID.
+    @property
+    def id(self):
+        return self._raw.id
+
+    # return instruction's address.
+    @property
+    def address(self):
+        return self._raw.address
+
+    # return instruction's size.
+    @property
+    def size(self):
+        return self._raw.size
+
+    # return instruction's machine bytes (which should have @size bytes).
+    @property
+    def bytes(self):
+        return bytearray(self._raw.bytes)[:self._raw.size]
+
+    # return instruction's mnemonic.
+    @property
+    def mnemonic(self):
+        if self._cs._diet:
+            # Diet engine cannot provide @mnemonic.
+            raise CsError(CS_ERR_DIET)
+
+        return self._raw.mnemonic.decode('ascii')
+
+    # return instruction's operands (in string).
+    @property
+    def op_str(self):
+        if self._cs._diet:
+            # Diet engine cannot provide @op_str.
+            raise CsError(CS_ERR_DIET)
+
+        return self._raw.op_str.decode('ascii')
+
+    # return list of all implicit registers being read.
+    @property
+    def regs_read(self):
+        if self._raw.id == 0:
+            raise CsError(CS_ERR_SKIPDATA)
+
+        if self._cs._diet:
+            # Diet engine cannot provide @regs_read.
+            raise CsError(CS_ERR_DIET)
+
+        if self._cs._detail:
+            detail = self._raw.detail.contents
+            return detail.regs_read[:detail.regs_read_count]
+
+        raise CsError(CS_ERR_DETAIL)
+
+    # return list of all implicit registers being modified
+    @property
+    def regs_write(self):
+        if self._raw.id == 0:
+            raise CsError(CS_ERR_SKIPDATA)
+
+        if self._cs._diet:
+            # Diet engine cannot provide @regs_write
+            raise CsError(CS_ERR_DIET)
+
+        if self._cs._detail:
+            detail = self._raw.detail.contents
+            return detail.regs_write[:detail.regs_write_count]
+
+        raise CsError(CS_ERR_DETAIL)
+
+    # return list of semantic groups this instruction belongs to.
+    @property
+    def groups(self):
+        if self._raw.id == 0:
+            raise CsError(CS_ERR_SKIPDATA)
+
+        if self._cs._diet:
+            # Diet engine cannot provide @groups
+            raise CsError(CS_ERR_DIET)
+
+        if self._cs._detail:
+            detail = self._raw.detail.contents
+            return detail.groups[:detail.groups_count]
+
+        raise CsError(CS_ERR_DETAIL)
+
+    def __gen_detail(self):
+        arch = self._cs.arch
+        detail = self._raw.detail.contents
+        if arch == CS_ARCH_ARM:
+            (self.cc, self.update_flags, self.writeback, self.operands) = \
+                arm.get_arch_info(detail.arch.arm)
+        elif arch == CS_ARCH_ARM64:
+            (self.cc, self.update_flags, self.writeback, self.operands) = \
+                arm64.get_arch_info(detail.arch.arm64)
+        elif arch == CS_ARCH_X86:
+            (self.prefix, self.segment, self.opcode, self.op_size, self.addr_size, \
+                self.disp_size, self.imm_size, self.modrm, self.sib, self.disp, \
+                self.sib_index, self.sib_scale, self.sib_base, self.operands) = x86.get_arch_info(detail.arch.x86)
+        elif arch == CS_ARCH_MIPS:
+                self.operands = mips.get_arch_info(detail.arch.mips)
+        elif arch == CS_ARCH_PPC:
+            (self.bc, self.bh, self.update_cr0, self.operands) = \
+                ppc.get_arch_info(detail.arch.ppc)
+        elif arch == CS_ARCH_SPARC:
+            (self.cc, self.hint, self.operands) = sparc.get_arch_info(detail.arch.sparc)
+        elif arch == CS_ARCH_SYSZ:
+            (self.cc, self.operands) = systemz.get_arch_info(detail.arch.sysz)
+
+
+    def __getattr__(self, name):
+        if not self._cs._detail:
+            raise CsError(CS_ERR_DETAIL)
+
+        attr = object.__getattribute__
+        if not attr(self, '_cs')._detail:
+            return None
+        _dict = attr(self, '__dict__')
+        if 'operands' not in _dict:
+            self.__gen_detail()
+        if name not in _dict:
+            return None
+        return _dict[name]
+
+    # get the last error code
+    def errno(self):
+        return _cs.cs_errno(self._cs.csh)
+
+    # get the register name, given the register ID
+    def reg_name(self, reg_id):
+        if self._raw.id == 0:
+            raise CsError(CS_ERR_SKIPDATA)
+
+        if self._cs._diet:
+            # Diet engine cannot provide register name
+            raise CsError(CS_ERR_DIET)
+
+        return _cs.cs_reg_name(self._cs.csh, reg_id).decode('ascii')
+
+    # get the instruction string
+    def insn_name(self):
+        if self._cs._diet:
+            # Diet engine cannot provide instruction name
+            raise CsError(CS_ERR_DIET)
+
+        return _cs.cs_insn_name(self._cs.csh, self.id).decode('ascii')
+
+    # verify if this insn belong to group with id as @group_id
+    def group(self, group_id):
+        if self._raw.id == 0:
+            raise CsError(CS_ERR_SKIPDATA)
+
+        if self._cs._diet:
+            # Diet engine cannot provide group information
+            raise CsError(CS_ERR_DIET)
+
+        return group_id in self.groups
+
+    # verify if this instruction implicitly read register @reg_id
+    def reg_read(self, reg_id):
+        if self._raw.id == 0:
+            raise CsError(CS_ERR_SKIPDATA)
+
+        if self._cs._diet:
+            # Diet engine cannot provide regs_read information
+            raise CsError(CS_ERR_DIET)
+
+        return reg_id in self.regs_read
+
+    # verify if this instruction implicitly modified register @reg_id
+    def reg_write(self, reg_id):
+        if self._raw.id == 0:
+            raise CsError(CS_ERR_SKIPDATA)
+
+        if self._cs._diet:
+            # Diet engine cannot provide regs_write information
+            raise CsError(CS_ERR_DIET)
+
+        return reg_id in self.regs_write
+
+    # return number of operands having same operand type @op_type
+    def op_count(self, op_type):
+        if self._raw.id == 0:
+            raise CsError(CS_ERR_SKIPDATA)
+
+        c = 0
+        for op in self.operands:
+            if op.type == op_type:
+                c += 1
+        return c
+
+    # get the operand at position @position of all operands having the same type @op_type
+    def op_find(self, op_type, position):
+        if self._raw.id == 0:
+            raise CsError(CS_ERR_SKIPDATA)
+
+        c = 0
+        for op in self.operands:
+            if op.type == op_type:
+                c += 1
+            if c == position:
+                return op
+
+
+class Cs(object):
+    def __init__(self, arch, mode):
+        # verify version compatibility with the core before doing anything
+        (major, minor, _combined) = cs_version()
+        if major != CS_API_MAJOR or minor != CS_API_MINOR:
+            self.csh = None
+            # our binding version is different from the core's API version
+            raise CsError(CS_ERR_VERSION)
+
+        self.arch, self._mode = arch, mode
+        self.csh = ctypes.c_size_t()
+        status = _cs.cs_open(arch, mode, ctypes.byref(self.csh))
+        if status != CS_ERR_OK:
+            self.csh = None
+            raise CsError(status)
+
+        try:
+            import ccapstone
+            # rewire disasm to use the faster version
+            self.disasm = ccapstone.Cs(self).disasm
+        except:
+            pass
+
+        if arch == CS_ARCH_X86:
+            # Intel syntax is default for X86
+            self._syntax = CS_OPT_SYNTAX_INTEL
+        else:
+            self._syntax = None
+
+        self._detail = False  # by default, do not produce instruction details
+        self._diet = cs_support(CS_SUPPORT_DIET)
+        self._x86reduce = cs_support(CS_SUPPORT_X86_REDUCE)
+        
+        # default mnemonic for SKIPDATA
+        self._skipdata_mnem = ".byte"
+        self._skipdata = False
+
+
+
+    # destructor to be called automatically when object is destroyed.
+    def __del__(self):
+        if self.csh:
+            status = _cs.cs_close(ctypes.byref(self.csh))
+            if status != CS_ERR_OK:
+                raise CsError(status)
+
+
+    # def option(self, opt_type, opt_value):
+    #    return _cs.cs_option(self.csh, opt_type, opt_value)
+
+
+    # is this a diet engine?
+    @property
+    def diet(self):
+        return self._diet
+
+
+    # is this engine compiled with X86-reduce option?
+    @property
+    def x86_reduce(self):
+        return self._x86reduce
+
+
+    # return assembly syntax.
+    @property
+    def syntax(self):
+        return self._syntax
+
+
+    # return current skipdata status
+    @property
+    def skipdata(self):
+        return self._skipdata
+
+
+    # setter: modify skipdata status
+    @syntax.setter
+    def skipdata(self, opt):
+        if opt == False:
+            status = _cs.cs_option(self.csh, CS_OPT_SKIPDATA, CS_OPT_OFF)
+        else:
+            status = _cs.cs_option(self.csh, CS_OPT_SKIPDATA, CS_OPT_ON)
+        if status != CS_ERR_OK:
+            raise CsError(status)
+
+        # save this option
+        self._skipdata = opt
+
+
+    # setter: modify "data" instruction's mnemonic for SKIPDATA
+    @syntax.setter
+    def skipdata_setup(self, opt):
+        _skipdata_opt = _cs_opt_skipdata()
+        _mnem, _cb, _ud = opt
+        _skipdata_opt.mnemonic = _mnem.encode()
+        _skipdata_opt.callback = ctypes.cast(_cb, CS_SKIPDATA_CALLBACK)
+        _skipdata_opt.user_data = ctypes.cast(_ud, ctypes.c_void_p)
+        status = _cs.cs_option(self.csh, CS_OPT_SKIPDATA_SETUP, ctypes.cast(ctypes.byref(_skipdata_opt), ctypes.c_void_p))
+        if status != CS_ERR_OK:
+            raise CsError(status)
+
+        self._skipdata_opt = _skipdata_opt
+
+
+    # setter: modify assembly syntax.
+    @syntax.setter
+    def syntax(self, style):
+        status = _cs.cs_option(self.csh, CS_OPT_SYNTAX, style)
+        if status != CS_ERR_OK:
+            raise CsError(status)
+        # save syntax
+        self._syntax = style
+
+
+    # is detail mode enable?
+    @property
+    def detail(self):
+        return self._detail
+
+
+    # check to see if this engine supports a particular arch,
+    # or diet mode (depending on @query).
+    def support(self, query):
+        return cs_support(query)
+
+
+    # modify detail mode.
+    @detail.setter
+    def detail(self, opt):  # opt is boolean type, so must be either 'True' or 'False'
+        if opt == False:
+            status = _cs.cs_option(self.csh, CS_OPT_DETAIL, CS_OPT_OFF)
+        else:
+            status = _cs.cs_option(self.csh, CS_OPT_DETAIL, CS_OPT_ON)
+        if status != CS_ERR_OK:
+            raise CsError(status)
+        # save detail
+        self._detail = opt
+
+
+    # return disassembly mode of this engine.
+    @property
+    def mode(self):
+        return self._mode
+
+
+    # modify engine's mode at run-time.
+    @mode.setter
+    def mode(self, opt):  # opt is new disasm mode, of int type
+        status = _cs.cs_option(self.csh, CS_OPT_MODE, opt)
+        if status != CS_ERR_OK:
+            raise CsError(status)
+        # save mode
+        self._mode = opt
+
+
+    # Disassemble binary & return disassembled instructions in CsInsn objects
+    def disasm(self, code, offset, count=0):
+        all_insn = ctypes.POINTER(_cs_insn)()
+        '''if not _python2:
+            print(code)
+            code = code.encode()
+            print(code)'''
+        res = _cs.cs_disasm_ex(self.csh, code, len(code), offset, count, ctypes.byref(all_insn))
+        if res > 0:
+            for i in range(res):
+                yield CsInsn(self, all_insn[i])
+            _cs.cs_free(all_insn, res)
+        else:
+            status = _cs.cs_errno(self.csh)
+            if status != CS_ERR_OK:
+                raise CsError(status)
+            return
+            yield
+
+
+    # Light function to disassemble binary. This is about 20% faster than disasm() because
+    # unlike disasm(), disasm_lite() only return tuples of (address, size, mnemonic, op_str),
+    # rather than CsInsn objects.
+    def disasm_lite(self, code, offset, count=0):
+        if self._diet:
+            # Diet engine cannot provide @mnemonic & @op_str
+            raise CsError(CS_ERR_DIET)
+
+        all_insn = ctypes.POINTER(_cs_insn)()
+        res = _cs.cs_disasm_ex(self.csh, code, len(code), offset, count, ctypes.byref(all_insn))
+        if res > 0:
+            for i in range(res):
+                insn = all_insn[i]
+                yield (insn.address, insn.size, insn.mnemonic.decode('ascii'), insn.op_str.decode('ascii'))
+            _cs.cs_free(all_insn, res)
+        else:
+            status = _cs.cs_errno(self.csh)
+            if status != CS_ERR_OK:
+                raise CsError(status)
+            return
+            yield
+
+
+# print out debugging info
+def debug():
+    # is Cython there?
+    try:
+        import ccapstone
+        return ccapstone.debug()
+    except:
+        # no Cython, fallback to Python code below
+        pass
+
+    if cs_support(CS_SUPPORT_DIET):
+        diet = "diet"
+    else:
+        diet = "standard"
+
+    archs = { "arm": CS_ARCH_ARM, "arm64": CS_ARCH_ARM64, \
+        "mips": CS_ARCH_MIPS, "ppc": CS_ARCH_PPC, "sparc": CS_ARCH_SPARC, \
+        "sysz": CS_ARCH_SYSZ }
+
+    all_archs = ""
+    keys = archs.keys()
+    keys.sort()
+    for k in keys:
+        if cs_support(archs[k]):
+            all_archs += "-%s" % k
+
+    if cs_support(CS_ARCH_X86):
+        all_archs += "-x86"
+        if cs_support(CS_SUPPORT_X86_REDUCE):
+            all_archs += "_reduce"
+
+    (major, minor, _combined) = cs_version()
+
+    return "python-%s%s-c%u.%u-b%u.%u" % (diet, all_archs, major, minor, CS_API_MAJOR, CS_API_MINOR)
diff --git a/bindings/python/capstone/arm.py b/bindings/python/capstone/arm.py
index 6f649ff..9cc5c01 100644
--- a/bindings/python/capstone/arm.py
+++ b/bindings/python/capstone/arm.py
@@ -1,7 +1,7 @@
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
 import ctypes, copy
-from arm_const import *
+from .arm_const import *
 
 # define the API
 class ArmOpMem(ctypes.Structure):
diff --git a/bindings/python/capstone/arm64.py b/bindings/python/capstone/arm64.py
index ebb71e1..4bad042 100644
--- a/bindings/python/capstone/arm64.py
+++ b/bindings/python/capstone/arm64.py
@@ -1,7 +1,7 @@
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
 import ctypes, copy
-from arm64_const import *
+from .arm64_const import *
 
 # define the API
 class Arm64OpMem(ctypes.Structure):
diff --git a/bindings/python/capstone/mips.py b/bindings/python/capstone/mips.py
index a367150..57e3d75 100644
--- a/bindings/python/capstone/mips.py
+++ b/bindings/python/capstone/mips.py
@@ -1,7 +1,7 @@
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
 import ctypes, copy
-from mips_const import *
+from .mips_const import *
 
 # define the API
 class MipsOpMem(ctypes.Structure):
diff --git a/bindings/python/capstone/ppc.py b/bindings/python/capstone/ppc.py
index c11bd2c..ed1a64d 100644
--- a/bindings/python/capstone/ppc.py
+++ b/bindings/python/capstone/ppc.py
@@ -1,7 +1,7 @@
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
 import ctypes, copy
-from ppc_const import *
+from .ppc_const import *
 
 # define the API
 class PpcOpMem(ctypes.Structure):
diff --git a/bindings/python/capstone/sparc.py b/bindings/python/capstone/sparc.py
index af3aba6..8213ca4 100644
--- a/bindings/python/capstone/sparc.py
+++ b/bindings/python/capstone/sparc.py
@@ -1,7 +1,7 @@
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
 import ctypes, copy
-from sparc_const import *
+from .sparc_const import *
 
 # define the API
 class SparcOpMem(ctypes.Structure):
diff --git a/bindings/python/capstone/systemz.py b/bindings/python/capstone/systemz.py
index 55e9ae2..7317757 100644
--- a/bindings/python/capstone/systemz.py
+++ b/bindings/python/capstone/systemz.py
@@ -1,7 +1,7 @@
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
 import ctypes, copy
-from sysz_const import *
+from .sysz_const import *
 
 # define the API
 class SyszOpMem(ctypes.Structure):
diff --git a/bindings/python/capstone/x86.py b/bindings/python/capstone/x86.py
index a88dbdf..4adcee1 100644
--- a/bindings/python/capstone/x86.py
+++ b/bindings/python/capstone/x86.py
@@ -1,7 +1,7 @@
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
 import ctypes, copy
-from x86_const import *
+from .x86_const import *
 
 # define the API
 class X86OpMem(ctypes.Structure):
diff --git a/bindings/python/test.py b/bindings/python/test.py
index 9332eeb..f471f3f 100755
--- a/bindings/python/test.py
+++ b/bindings/python/test.py
@@ -1,24 +1,27 @@
 #!/usr/bin/env python
-
+from __future__ import print_function
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
 from capstone import *
 import binascii
+import sys
+_python3 = sys.version_info.major == 3
 
-X86_CODE16 = "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
-X86_CODE32 = "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
-X86_CODE64 = "\x55\x48\x8b\x05\xb8\x13\x00\x00"
-ARM_CODE = "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
-ARM_CODE2 = "\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3"
-THUMB_CODE = "\x70\x47\xeb\x46\x83\xb0\xc9\x68"
-THUMB_CODE2 = "\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
-MIPS_CODE = "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
-MIPS_CODE2 = "\x56\x34\x21\x34\xc2\x17\x01\x00"
-ARM64_CODE = "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9"
-PPC_CODE = "\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21"
-SPARC_CODE = "\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
-SPARCV9_CODE = "\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
-SYSZ_CODE = "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
+
+X86_CODE16 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
+X86_CODE32 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
+X86_CODE64 = b"\x55\x48\x8b\x05\xb8\x13\x00\x00"
+ARM_CODE = b"\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
+ARM_CODE2 = b"\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3"
+THUMB_CODE = b"\x70\x47\xeb\x46\x83\xb0\xc9\x68"
+THUMB_CODE2 = b"\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
+MIPS_CODE = b"\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
+MIPS_CODE2 = b"\x56\x34\x21\x34\xc2\x17\x01\x00"
+ARM64_CODE = b"\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9"
+PPC_CODE = b"\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21"
+SPARC_CODE = b"\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
+SPARCV9_CODE = b"\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
+SYSZ_CODE = b"\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
 
 all_tests = (
         (CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", 0),
@@ -30,37 +33,53 @@
         (CS_ARCH_ARM, CS_MODE_ARM, ARM_CODE2, "ARM: Cortex-A15 + NEON", 0),
         (CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE, "THUMB", 0),
         (CS_ARCH_MIPS, CS_MODE_32 + CS_MODE_BIG_ENDIAN, MIPS_CODE, "MIPS-32 (Big-endian)", 0),
-        (CS_ARCH_MIPS, CS_MODE_64+ CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)", 0),
+        (CS_ARCH_MIPS, CS_MODE_64 + CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)", 0),
         (CS_ARCH_ARM64, CS_MODE_ARM, ARM64_CODE, "ARM-64", 0),
         (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64", 0),
         (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64, print register with number only", CS_OPT_SYNTAX_NOREGNAME),
         (CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, SPARC_CODE, "Sparc", 0),
         (CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN + CS_MODE_V9, SPARCV9_CODE, "SparcV9", 0),
         (CS_ARCH_SYSZ, 0, SYSZ_CODE, "SystemZ", 0),
-        )
+)
 
 
 def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
+    if _python3:
+        return " ".join("0x{0:02x}".format(c) for c in s)  # <-- Python 3 is OK
+    else:
+        return " ".join("0x{0:02x}".format(ord(c)) for c in s)
 
+def to_x(s):
+    from struct import pack
+    if not s: return '0'
+    x = pack(">q", s)
+    while x[0] in ('0', 0): x = x[1:]
+    return x
 
-### Test cs_disasm_quick()
+def to_x_32(s):
+    from struct import pack
+    if not s: return '0'
+    x = pack(">i", s)
+    while x[0] in ('0', 0): x = x[1:]
+    return x
+
+# ## Test cs_disasm_quick()
 def test_cs_disasm_quick():
-    for (arch, mode, code, comment, syntax) in all_tests:
+    for arch, mode, code, comment, syntax in all_tests:
         print('*' * 40)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Disasm:"),
-        print to_hex(code)
+        print(to_hex(code))
         for insn in cs_disasm_quick(arch, mode, code, 0x1000):
-            print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
-        print
+            print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
+        print()
 
 
-### Test class Cs
+# ## Test class Cs
 def test_class():
-    for (arch, mode, code, comment, syntax) in all_tests:
+    for arch, mode, code, comment, syntax in all_tests:
         print('*' * 16)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Code: %s" % to_hex(code))
         print("Disasm:")
 
@@ -71,16 +90,17 @@
                 md.syntax = syntax
 
             for insn in md.disasm(code, 0x1000):
-                #bytes = binascii.hexlify(insn.bytes)
-                #print("0x%x:\t%s\t%s\t// hex-code: %s" %(insn.address, insn.mnemonic, insn.op_str, bytes))
-                print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+                # bytes = binascii.hexlify(insn.bytes)
+                # print("0x%x:\t%s\t%s\t// hex-code: %s" %(insn.address, insn.mnemonic, insn.op_str, bytes))
+                print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
 
             print("0x%x:" % (insn.address + insn.size))
-            print
+            print()
         except CsError as e:
-            print("ERROR: %s" %e)
+            print("ERROR: %s" % e)
 
 
-#test_cs_disasm_quick()
-#print "*" * 40
-test_class()
+# test_cs_disasm_quick()
+# print ("*" * 40)
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_all.py b/bindings/python/test_all.py
new file mode 100644
index 0000000..38caca5
--- /dev/null
+++ b/bindings/python/test_all.py
@@ -0,0 +1,12 @@
+#!/bin/env python
+import test, test_arm, test_arm64, test_detail, test_lite, test_mips, test_ppc, \
+    test_x86
+
+test.test_class()
+test_arm.test_class()
+test_arm64.test_class()
+test_detail.test_class()
+test_lite.test_class()
+test_mips.test_class()
+test_ppc.test_class()
+test_x86.test_class()
diff --git a/bindings/python/test_arm.py b/bindings/python/test_arm.py
index 1c5924b..afebfcf 100755
--- a/bindings/python/test_arm.py
+++ b/bindings/python/test_arm.py
@@ -1,14 +1,16 @@
 #!/usr/bin/env python
+from __future__ import print_function
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
 from capstone import *
 from capstone.arm import *
+from test import to_hex, to_x, to_x_32
 
-ARM_CODE = "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
-ARM_CODE2 = "\xd1\xe8\x00\xf0\xf0\x24\x04\x07\x1f\x3c\xf2\xc0\x00\x00\x4f\xf0\x00\x01\x46\x6c"
-THUMB_CODE2  = "\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
-THUMB_CODE  = "\x70\x47\xeb\x46\x83\xb0\xc9\x68\x1f\xb1"
+ARM_CODE = b"\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
+ARM_CODE2 = b"\xd1\xe8\x00\xf0\xf0\x24\x04\x07\x1f\x3c\xf2\xc0\x00\x00\x4f\xf0\x00\x01\x46\x6c"
+THUMB_CODE2 = b"\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
+THUMB_CODE = b"\x70\x47\xeb\x46\x83\xb0\xc9\x68\x1f\xb1"
 
 all_tests = (
         (CS_ARCH_ARM, CS_MODE_ARM, ARM_CODE, "ARM"),
@@ -17,77 +19,60 @@
         (CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE2, "Thumb-2"),
         )
 
-def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
-
-def to_x(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">q", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-def to_x_32(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">i", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-### Test class Cs
+# ## Test class Cs
 def test_class():
     def print_insn_detail(insn):
         # print address, mnemonic and operands
-        print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+        print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
 
         # "data" instruction generated by SKIPDATA option has no detail
         if insn.id == 0:
             return
 
         if len(insn.operands) > 0:
-            print("\top_count: %u" %len(insn.operands))
+            print("\top_count: %u" % len(insn.operands))
             c = 0
             for i in insn.operands:
                 if i.type == ARM_OP_REG:
-                    print("\t\toperands[%u].type: REG = %s" %(c, insn.reg_name(i.reg)))
+                    print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
                 if i.type == ARM_OP_IMM:
-                    print("\t\toperands[%u].type: IMM = 0x%s" %(c, to_x_32(i.imm)))
+                    print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x_32(i.imm)))
                 if i.type == ARM_OP_PIMM:
-                    print("\t\toperands[%u].type: P-IMM = %u" %(c, i.imm))
+                    print("\t\toperands[%u].type: P-IMM = %u" % (c, i.imm))
                 if i.type == ARM_OP_CIMM:
-                    print("\t\toperands[%u].type: C-IMM = %u" %(c, i.imm))
+                    print("\t\toperands[%u].type: C-IMM = %u" % (c, i.imm))
                 if i.type == ARM_OP_FP:
-                    print("\t\toperands[%u].type: FP = %f" %(c, i.fp))
+                    print("\t\toperands[%u].type: FP = %f" % (c, i.fp))
                 if i.type == ARM_OP_MEM:
-                    print("\t\toperands[%u].type: MEM" %c)
+                    print("\t\toperands[%u].type: MEM" % c)
                     if i.mem.base != 0:
                         print("\t\t\toperands[%u].mem.base: REG = %s" \
-                            %(c, insn.reg_name(i.mem.base)))
+                            % (c, insn.reg_name(i.mem.base)))
                     if i.mem.index != 0:
                         print("\t\t\toperands[%u].mem.index: REG = %s" \
-                            %(c, insn.reg_name(i.mem.index)))
+                            % (c, insn.reg_name(i.mem.index)))
                     if i.mem.scale != 1:
                         print("\t\t\toperands[%u].mem.scale: %u" \
-                            %(c, i.mem.scale))
+                            % (c, i.mem.scale))
                     if i.mem.disp != 0:
                         print("\t\t\toperands[%u].mem.disp: 0x%s" \
-                            %(c, to_x_32(i.mem.disp)))
+                            % (c, to_x_32(i.mem.disp)))
 
                 if i.shift.type != ARM_SFT_INVALID and i.shift.value:
-		            print("\t\t\tShift: type = %u, value = %u\n" \
-                        %(i.shift.type, i.shift.value))
-                c+=1
+                    print("\t\t\tShift: type = %u, value = %u\n" \
+                        % (i.shift.type, i.shift.value))
+                c += 1
 
         if insn.update_flags:
             print("\tUpdate-flags: True")
         if insn.writeback:
             print("\tWrite-back: True")
         if not insn.cc in [ARM_CC_AL, ARM_CC_INVALID]:
-            print("\tCode condition: %u" %insn.cc)
+            print("\tCode condition: %u" % insn.cc)
 
     for (arch, mode, code, comment) in all_tests:
         print("*" * 16)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Code: %s" % to_hex(code))
         print("Disasm:")
 
@@ -97,9 +82,9 @@
             for insn in md.disasm(code, 0x1000):
                 print_insn_detail(insn)
                 print
-            print "0x%x:\n" % (insn.address + insn.size)
+            print ("0x%x:\n" % (insn.address + insn.size))
         except CsError as e:
-            print("ERROR: %s" %e)
+            print("ERROR: %s" % e)
 
-
-test_class()
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_arm64.py b/bindings/python/test_arm64.py
index a11c5df..651055b 100755
--- a/bindings/python/test_arm64.py
+++ b/bindings/python/test_arm64.py
@@ -1,78 +1,67 @@
 #!/usr/bin/env python
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
-
+from __future__ import print_function
 from capstone import *
 from capstone.arm64 import *
-
-ARM64_CODE = "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b"
+from test import to_hex, to_x
+ARM64_CODE = b"\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b"
 
 all_tests = (
         (CS_ARCH_ARM64, CS_MODE_ARM, ARM64_CODE, "ARM-64"),
         )
 
-def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
-
-def to_x(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">q", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-### Test class Cs
+# ## Test class Cs
 def test_class():
     def print_insn_detail(insn):
         # print address, mnemonic and operands
-        print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+        print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
 
         # "data" instruction generated by SKIPDATA option has no detail
         if insn.id == 0:
             return
 
         if len(insn.operands) > 0:
-            print("\top_count: %u" %len(insn.operands))
+            print("\top_count: %u" % len(insn.operands))
             c = -1
             for i in insn.operands:
                 c += 1
                 if i.type == ARM64_OP_REG:
-                    print("\t\toperands[%u].type: REG = %s" %(c, insn.reg_name(i.reg)))
+                    print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
                 if i.type == ARM64_OP_IMM:
-                    print("\t\toperands[%u].type: IMM = 0x%s" %(c, to_x(i.imm)))
+                    print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
                 if i.type == ARM64_OP_CIMM:
-                    print("\t\toperands[%u].type: C-IMM = %u" %(c, i.imm))
+                    print("\t\toperands[%u].type: C-IMM = %u" % (c, i.imm))
                 if i.type == ARM64_OP_FP:
-                    print("\t\toperands[%u].type: FP = %f" %(c, i.fp))
+                    print("\t\toperands[%u].type: FP = %f" % (c, i.fp))
                 if i.type == ARM64_OP_MEM:
-                    print("\t\toperands[%u].type: MEM" %c)
+                    print("\t\toperands[%u].type: MEM" % c)
                     if i.mem.base != 0:
                         print("\t\t\toperands[%u].mem.base: REG = %s" \
-                            %(c, insn.reg_name(i.mem.base)))
+                            % (c, insn.reg_name(i.mem.base)))
                     if i.mem.index != 0:
                         print("\t\t\toperands[%u].mem.index: REG = %s" \
-                            %(c, insn.reg_name(i.mem.index)))
+                            % (c, insn.reg_name(i.mem.index)))
                     if i.mem.disp != 0:
                         print("\t\t\toperands[%u].mem.disp: 0x%s" \
-                            %(c, to_x(i.mem.disp)))
+                            % (c, to_x(i.mem.disp)))
 
                 if i.shift.type != ARM64_SFT_INVALID and i.shift.value:
-		            print("\t\t\tShift: type = %u, value = %u" \
-                        %(i.shift.type, i.shift.value))
+                    print("\t\t\tShift: type = %u, value = %u" % (i.shift.type, i.shift.value))
 
                 if i.ext != ARM64_EXT_INVALID:
-		            print("\t\t\tExt: %u" %i.ext)
+                    print("\t\t\tExt: %u" % i.ext)
 
         if insn.writeback:
             print("\tWrite-back: True")
         if not insn.cc in [ARM64_CC_AL, ARM64_CC_INVALID]:
-            print("\tCode condition: %u" %insn.cc)
+            print("\tCode condition: %u" % insn.cc)
         if insn.update_flags:
             print("\tUpdate-flags: True")
 
     for (arch, mode, code, comment) in all_tests:
         print("*" * 16)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Code: %s" % to_hex(code))
         print("Disasm:")
 
@@ -82,9 +71,9 @@
             for insn in md.disasm(code, 0x2c):
                 print_insn_detail(insn)
                 print
-            print "0x%x:\n" % (insn.address + insn.size)
+            print("0x%x:\n" % (insn.address + insn.size))
         except CsError as e:
-            print("ERROR: %s" %e)
+            print("ERROR: %s" % e)
 
-
-test_class()
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_detail.py b/bindings/python/test_detail.py
index 4380fdf..04b8e73 100755
--- a/bindings/python/test_detail.py
+++ b/bindings/python/test_detail.py
@@ -1,23 +1,23 @@
 #!/usr/bin/env python
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
-
+from __future__ import print_function
 from capstone import *
 
-X86_CODE16 = "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
-X86_CODE32 = "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
-X86_CODE64 = "\x55\x48\x8b\x05\xb8\x13\x00\x00"
-ARM_CODE = "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
-ARM_CODE2 = "\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3"
-THUMB_CODE = "\x70\x47\xeb\x46\x83\xb0\xc9\x68"
-THUMB_CODE2 = "\x4f\xf0\x00\x01\xbd\xe8\x00\x88"
-MIPS_CODE = "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
-MIPS_CODE2 = "\x56\x34\x21\x34\xc2\x17\x01\x00"
-ARM64_CODE = "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9"
-PPC_CODE = "\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21"
-SPARC_CODE = "\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
-SPARCV9_CODE = "\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
-SYSZ_CODE = "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
+X86_CODE16 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
+X86_CODE32 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
+X86_CODE64 = b"\x55\x48\x8b\x05\xb8\x13\x00\x00"
+ARM_CODE = b"\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
+ARM_CODE2 = b"\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3"
+THUMB_CODE = b"\x70\x47\xeb\x46\x83\xb0\xc9\x68"
+THUMB_CODE2 = b"\x4f\xf0\x00\x01\xbd\xe8\x00\x88"
+MIPS_CODE = b"\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
+MIPS_CODE2 = b"\x56\x34\x21\x34\xc2\x17\x01\x00"
+ARM64_CODE = b"\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9"
+PPC_CODE = b"\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21"
+SPARC_CODE = b"\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
+SPARCV9_CODE = b"\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
+SYSZ_CODE = b"\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
 
 all_tests = (
         (CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", 0),
@@ -30,15 +30,15 @@
         (CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE2, "THUMB-2", 0),
         (CS_ARCH_ARM64, CS_MODE_ARM, ARM64_CODE, "ARM-64", 0),
         (CS_ARCH_MIPS, CS_MODE_32 + CS_MODE_BIG_ENDIAN, MIPS_CODE, "MIPS-32 (Big-endian)", 0),
-        (CS_ARCH_MIPS, CS_MODE_64+ CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)", 0),
+        (CS_ARCH_MIPS, CS_MODE_64 + CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)", 0),
         (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64", 0),
         (CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, SPARC_CODE, "Sparc", 0),
         (CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN + CS_MODE_V9, SPARCV9_CODE, "SparcV9", 0),
         (CS_ARCH_SYSZ, 0, SYSZ_CODE, "SystemZ", 0),
-        )
+)
 
 
-### Test class Cs
+# ## Test class Cs
 def test_class():
     def print_detail(insn):
         # "data" instruction generated by SKIPDATA option has no detail
@@ -46,29 +46,29 @@
             return
 
         if len(insn.regs_read) > 0:
-            print("\tImplicit registers read: "),
+            print("\tImplicit registers read: ", end=''),
             for m in insn.regs_read:
-                print("%s " %insn.reg_name(m)),
-            print
+                print("%s " % insn.reg_name(m), end=''),
+            print()
 
         if len(insn.regs_write) > 0:
-            print("\tImplicit registers modified: "),
+            print("\tImplicit registers modified: ", end=''),
             for m in insn.regs_write:
-                print("%s " %insn.reg_name(m)),
-            print
+                print("%s " % insn.reg_name(m), end=''),
+            print()
 
         if len(insn.groups) > 0:
-            print("\tThis instruction belongs to groups:"),
+            print("\tThis instruction belongs to groups:", end=''),
             for m in insn.groups:
-                print("%u" %m),
-            print
+                print("%u" % m, end=''),
+            print()
 
 
     for (arch, mode, code, comment, syntax) in all_tests:
         print('*' * 40)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Disasm:")
-    
+
         try:
             md = Cs(arch, mode)
             md.detail = True
@@ -78,13 +78,13 @@
 
             for insn in md.disasm(code, 0x1000):
                 print("0x%x:\t%s\t%s  // insn-ID: %u, insn-mnem: %s" \
-                    %(insn.address, insn.mnemonic, insn.op_str, insn.id, \
+                    % (insn.address, insn.mnemonic, insn.op_str, insn.id, \
                     insn.insn_name()))
                 print_detail(insn)
 
-            print
+            print()
         except CsError as e:
-            print("ERROR: %s" %e)
+            print("ERROR: %s" % e)
 
-
-test_class()
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_lite.py b/bindings/python/test_lite.py
index 7d08c2a..490f775 100755
--- a/bindings/python/test_lite.py
+++ b/bindings/python/test_lite.py
@@ -1,21 +1,22 @@
 #!/usr/bin/env python
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
-
+from __future__ import print_function
 from capstone import *
 import binascii
+from test import to_hex
 
-X86_CODE16 = "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
-X86_CODE32 = "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
-X86_CODE64 = "\x55\x48\x8b\x05\xb8\x13\x00\x00"
-ARM_CODE = "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
-ARM_CODE2 = "\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3"
-THUMB_CODE = "\x70\x47\xeb\x46\x83\xb0\xc9\x68"
-THUMB_CODE2 = "\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
-MIPS_CODE = "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
-MIPS_CODE2 = "\x56\x34\x21\x34\xc2\x17\x01\x00"
-ARM64_CODE = "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9"
-PPC_CODE = "\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21"
+X86_CODE16 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
+X86_CODE32 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
+X86_CODE64 = b"\x55\x48\x8b\x05\xb8\x13\x00\x00"
+ARM_CODE = b"\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
+ARM_CODE2 = b"\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3"
+THUMB_CODE = b"\x70\x47\xeb\x46\x83\xb0\xc9\x68"
+THUMB_CODE2 = b"\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
+MIPS_CODE = b"\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
+MIPS_CODE2 = b"\x56\x34\x21\x34\xc2\x17\x01\x00"
+ARM64_CODE = b"\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9"
+PPC_CODE = b"\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21"
 
 all_tests = (
         (CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", 0),
@@ -27,34 +28,30 @@
         (CS_ARCH_ARM, CS_MODE_ARM, ARM_CODE2, "ARM: Cortex-A15 + NEON", 0),
         (CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE, "THUMB", 0),
         (CS_ARCH_MIPS, CS_MODE_32 + CS_MODE_BIG_ENDIAN, MIPS_CODE, "MIPS-32 (Big-endian)", 0),
-        (CS_ARCH_MIPS, CS_MODE_64+ CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)", 0),
+        (CS_ARCH_MIPS, CS_MODE_64 + CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)", 0),
         (CS_ARCH_ARM64, CS_MODE_ARM, ARM64_CODE, "ARM-64", 0),
         (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64", 0),
         (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64, print register with number only", CS_OPT_SYNTAX_NOREGNAME),
         )
 
 
-def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
-
-
-### Test cs_disasm_quick()
+# ## Test cs_disasm_quick()
 def test_cs_disasm_quick():
     for (arch, mode, code, comment, syntax) in all_tests:
         print('*' * 40)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Disasm:"),
-        print to_hex(code)
+        print(to_hex(code))
         for (addr, size, mnemonic, op_str) in cs_disasm_lite(arch, mode, code, 0x1000):
-            print("0x%x:\t%s\t%s" %(addr, mnemonic, op_str))
-        print
+            print("0x%x:\t%s\t%s" % (addr, mnemonic, op_str))
+        print()
 
 
-### Test class Cs
+# ## Test class Cs
 def test_class():
     for (arch, mode, code, comment, syntax) in all_tests:
         print('*' * 16)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Code: %s" % to_hex(code))
         print("Disasm:")
 
@@ -65,14 +62,15 @@
                 md.syntax = syntax
 
             for (addr, size, mnemonic, op_str) in md.disasm_lite(code, 0x1000):
-                print("0x%x:\t%s\t%s" %(addr, mnemonic, op_str))
+                print("0x%x:\t%s\t%s" % (addr, mnemonic, op_str))
 
             print("0x%x:" % (addr + size))
-            print
+            print()
         except CsError as e:
-            print("ERROR: %s" %e)
+            print("ERROR: %s" % e)
 
 
-#test_cs_disasm_quick()
-#print "*" * 40
-test_class()
+# test_cs_disasm_quick()
+# print "*" * 40
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_mips.py b/bindings/python/test_mips.py
index 0e40a21..ec1f1a3 100755
--- a/bindings/python/test_mips.py
+++ b/bindings/python/test_mips.py
@@ -1,60 +1,51 @@
 #!/usr/bin/env python
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
-
+from __future__ import print_function
 from capstone import *
 from capstone.mips import *
+from test import to_hex, to_x
 
-MIPS_CODE  = "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
-MIPS_CODE2 = "\x56\x34\x21\x34\xc2\x17\x01\x00"
+MIPS_CODE = b"\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
+MIPS_CODE2 = b"\x56\x34\x21\x34\xc2\x17\x01\x00"
 
 all_tests = (
         (CS_ARCH_MIPS, CS_MODE_32 + CS_MODE_BIG_ENDIAN, MIPS_CODE, "MIPS-32 (Big-endian)"),
         (CS_ARCH_MIPS, CS_MODE_64 + CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)"),
 )
 
-def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
-
-def to_x(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">q", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-### Test class Cs
+# ## Test class Cs
 def test_class():
     def print_insn_detail(insn):
         # print address, mnemonic and operands
-        print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+        print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
 
         # "data" instruction generated by SKIPDATA option has no detail
         if insn.id == 0:
             return
 
         if len(insn.operands) > 0:
-            print("\top_count: %u" %len(insn.operands))
+            print("\top_count: %u" % len(insn.operands))
             c = -1
             for i in insn.operands:
                 c += 1
                 if i.type == MIPS_OP_REG:
-                    print("\t\toperands[%u].type: REG = %s" %(c, insn.reg_name(i.reg)))
+                    print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
                 if i.type == MIPS_OP_IMM:
-                    print("\t\toperands[%u].type: IMM = 0x%s" %(c, to_x(i.imm)))
+                    print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
                 if i.type == MIPS_OP_MEM:
-                    print("\t\toperands[%u].type: MEM" %c)
+                    print("\t\toperands[%u].type: MEM" % c)
                     if i.mem.base != 0:
                         print("\t\t\toperands[%u].mem.base: REG = %s" \
-                            %(c, insn.reg_name(i.mem.base)))
+                            % (c, insn.reg_name(i.mem.base)))
                     if i.mem.disp != 0:
                         print("\t\t\toperands[%u].mem.disp: 0x%s" \
-                            %(c, to_x(i.mem.disp)))
+                            % (c, to_x(i.mem.disp)))
 
 
     for (arch, mode, code, comment) in all_tests:
         print("*" * 16)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Code: %s" % to_hex(code))
         print("Disasm:")
 
@@ -63,11 +54,12 @@
             md.detail = True
             for insn in md.disasm(code, 0x1000):
                 print_insn_detail(insn)
-                print
+                print()
 
-            print "0x%x:\n" %(insn.address + insn.size)
+            print("0x%x:\n" % (insn.address + insn.size))
         except CsError as e:
-            print("ERROR: %s" %e)
+            print("ERROR: %s" % e)
 
 
-test_class()
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_ppc.py b/bindings/python/test_ppc.py
index 9642c7c..cb005b8 100755
--- a/bindings/python/test_ppc.py
+++ b/bindings/python/test_ppc.py
@@ -1,71 +1,54 @@
 #!/usr/bin/env python
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
-
+from __future__ import print_function
 from capstone import *
 from capstone.ppc import *
-
-PPC_CODE = "\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21"
+from test import to_x, to_hex, to_x_32
+PPC_CODE = b"\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21"
 
 all_tests = (
         (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64"),
         )
 
-def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
-
-def to_x(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">q", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-def to_x_32(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">i", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-### Test class Cs
+# ## Test class Cs
 def test_class():
     def print_insn_detail(insn):
         # print address, mnemonic and operands
-        print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+        print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
 
         # "data" instruction generated by SKIPDATA option has no detail
         if insn.id == 0:
             return
 
         if len(insn.operands) > 0:
-            print("\top_count: %u" %len(insn.operands))
+            print("\top_count: %u" % len(insn.operands))
             c = 0
             for i in insn.operands:
                 if i.type == PPC_OP_REG:
-                    print("\t\toperands[%u].type: REG = %s" %(c, insn.reg_name(i.reg)))
+                    print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
                 if i.type == PPC_OP_IMM:
-                    print("\t\toperands[%u].type: IMM = 0x%s" %(c, to_x_32(i.imm)))
+                    print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x_32(i.imm)))
                 if i.type == PPC_OP_MEM:
-                    print("\t\toperands[%u].type: MEM" %c)
+                    print("\t\toperands[%u].type: MEM" % c)
                     if i.mem.base != 0:
                         print("\t\t\toperands[%u].mem.base: REG = %s" \
-                            %(c, insn.reg_name(i.mem.base)))
+                            % (c, insn.reg_name(i.mem.base)))
                     if i.mem.disp != 0:
                         print("\t\t\toperands[%u].mem.disp: 0x%s" \
-                            %(c, to_x_32(i.mem.disp)))
+                            % (c, to_x_32(i.mem.disp)))
                 c += 1
 
         if insn.bc:
-            print("\tBranch code: %u" %insn.bc)
+            print("\tBranch code: %u" % insn.bc)
         if insn.bh:
-            print("\tBranch hint: %u" %insn.bh)
+            print("\tBranch hint: %u" % insn.bh)
         if insn.update_cr0:
             print("\tUpdate-CR0: True")
 
     for (arch, mode, code, comment) in all_tests:
         print("*" * 16)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Code: %s" % to_hex(code))
         print("Disasm:")
 
@@ -75,9 +58,10 @@
             for insn in md.disasm(code, 0x1000):
                 print_insn_detail(insn)
                 print
-            print "0x%x:\n" % (insn.address + insn.size)
+            print("0x%x:\n" % (insn.address + insn.size))
         except CsError as e:
-            print("ERROR: %s" %e)
+            print("ERROR: %s" % e)
 
 
-test_class()
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_skipdata.py b/bindings/python/test_skipdata.py
index 3e6c2b1..9f23678 100755
--- a/bindings/python/test_skipdata.py
+++ b/bindings/python/test_skipdata.py
@@ -2,31 +2,30 @@
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
+from __future__ import print_function
 from capstone import *
 import binascii
 
-X86_CODE32 = "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x00\x91\x92"
-RANDOM_CODE = "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
+from test import to_x, to_hex, to_x_32
+
+X86_CODE32 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x00\x91\x92"
+RANDOM_CODE = b"\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
 
 all_tests = (
         (CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32 (Intel syntax)", 0),
         (CS_ARCH_ARM, CS_MODE_ARM, RANDOM_CODE, "Arm", 0),
-        )
+)
 
 
-def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
-
-
-### Test cs_disasm_quick()
+# ## Test cs_disasm_quick()
 def test_cs_disasm_quick():
     for (arch, mode, code, comment, syntax) in all_tests:
         print('*' * 40)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Disasm:"),
-        print to_hex(code)
+        print(to_hex(code))
         for insn in cs_disasm_quick(arch, mode, code, 0x1000):
-            print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+            print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
         print
 
 
@@ -36,7 +35,7 @@
     return 2
 
 
-### Test class Cs
+# ## Test class Cs
 def test_class():
     for (arch, mode, code, comment, syntax) in all_tests:
         print('*' * 16)
@@ -63,12 +62,13 @@
             for insn in md.disasm(code, 0x1000):
                 #bytes = binascii.hexlify(insn.bytes)
                 #print("0x%x:\t%s\t%s\t// hex-code: %s" %(insn.address, insn.mnemonic, insn.op_str, bytes))
-                print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+                print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
 
             print("0x%x:" % (insn.address + insn.size))
             print
         except CsError as e:
-            print("ERROR: %s" %e)
+            print("ERROR: %s" % e)
 
 
-test_class()
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_sparc.py b/bindings/python/test_sparc.py
index ba8b022..5788916 100755
--- a/bindings/python/test_sparc.py
+++ b/bindings/python/test_sparc.py
@@ -2,63 +2,56 @@
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
+from __future__ import print_function
 from capstone import *
 from capstone.sparc import *
 
-SPARC_CODE = "\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
-SPARCV9_CODE = "\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
+from test import to_x, to_hex, to_x_32
+
+SPARC_CODE = b"\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
+SPARCV9_CODE = b"\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
 
 all_tests = (
         (CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, SPARC_CODE, "Sparc"),
         (CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN+CS_MODE_V9, SPARCV9_CODE, "SparcV9"),
-        )
+)
 
-def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
-
-def to_x_32(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">i", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-### Test class Cs
+# ## Test class Cs
 def test_class():
     def print_insn_detail(insn):
         # print address, mnemonic and operands
-        print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+        print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
 
         # "data" instruction generated by SKIPDATA option has no detail
         if insn.id == 0:
             return
 
         if len(insn.operands) > 0:
-            print("\top_count: %u" %len(insn.operands))
+            print("\top_count: %u" % len(insn.operands))
             c = 0
             for i in insn.operands:
                 if i.type == SPARC_OP_REG:
-                    print("\t\toperands[%u].type: REG = %s" %(c, insn.reg_name(i.reg)))
+                    print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
                 if i.type == SPARC_OP_IMM:
-                    print("\t\toperands[%u].type: IMM = 0x%s" %(c, to_x_32(i.imm)))
+                    print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x_32(i.imm)))
                 if i.type == SPARC_OP_MEM:
-                    print("\t\toperands[%u].type: MEM" %c)
+                    print("\t\toperands[%u].type: MEM" % c)
                     if i.mem.base != 0:
                         print("\t\t\toperands[%u].mem.base: REG = %s" \
-                            %(c, insn.reg_name(i.mem.base)))
+                            % (c, insn.reg_name(i.mem.base)))
                     if i.mem.disp != 0:
                         print("\t\t\toperands[%u].mem.disp: 0x%s" \
-                            %(c, to_x_32(i.mem.disp)))
+                            % (c, to_x_32(i.mem.disp)))
                 c += 1
 
         if insn.cc:
-            print("\tConditional code: %u" %insn.cc)
+            print("\tConditional code: %u" % insn.cc)
         if insn.hint:
-            print("\tBranch hint: %u" %insn.hint)
+            print("\tBranch hint: %u" % insn.hint)
 
     for (arch, mode, code, comment) in all_tests:
         print("*" * 16)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Code: %s" % to_hex(code))
         print("Disasm:")
 
@@ -68,9 +61,10 @@
             for insn in md.disasm(code, 0x1000):
                 print_insn_detail(insn)
                 print
-            print "0x%x:\n" % (insn.address + insn.size)
+            print("0x%x:\n" % (insn.address + insn.size))
         except CsError as e:
             print("ERROR: %s" %e)
 
 
-test_class()
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_systemz.py b/bindings/python/test_systemz.py
index f32f138..0715880 100755
--- a/bindings/python/test_systemz.py
+++ b/bindings/python/test_systemz.py
@@ -2,63 +2,56 @@
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
 
+from __future__ import print_function
 from capstone import *
 from capstone.systemz import *
 
-SYSZ_CODE = "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
+from test import to_x, to_hex, to_x_32
+
+SYSZ_CODE = b"\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
+
 all_tests = (
         (CS_ARCH_SYSZ, 0, SYSZ_CODE, "SystemZ"),
-        )
+)
 
-def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
-
-def to_x(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">q", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-
-### Test class Cs
+# ## Test class Cs
 def test_class():
     def print_insn_detail(insn):
         # print address, mnemonic and operands
-        print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+        print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
 
         # "data" instruction generated by SKIPDATA option has no detail
         if insn.id == 0:
             return
 
         if len(insn.operands) > 0:
-            print("\top_count: %u" %len(insn.operands))
+            print("\top_count: %u" % len(insn.operands))
             c = 0
             for i in insn.operands:
                 if i.type == SYSZ_OP_REG:
-                    print("\t\toperands[%u].type: REG = %s" %(c, insn.reg_name(i.reg)))
+                    print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
                 if i.type == SYSZ_OP_ACREG:
-                    print("\t\toperands[%u].type: ACREG = %u" %(c, i.reg))
+                    print("\t\toperands[%u].type: ACREG = %u" % (c, i.reg))
                 if i.type == SYSZ_OP_IMM:
-                    print("\t\toperands[%u].type: IMM = 0x%s" %(c, to_x(i.imm)))
+                    print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
                 if i.type == SYSZ_OP_MEM:
-                    print("\t\toperands[%u].type: MEM" %c)
+                    print("\t\toperands[%u].type: MEM" % c)
                     if i.mem.base != 0:
                         print("\t\t\toperands[%u].mem.base: REG = %s" \
-                            %(c, insn.reg_name(i.mem.base)))
+                            % (c, insn.reg_name(i.mem.base)))
                     if i.mem.index != 0:
                         print("\t\t\toperands[%u].mem.index: REG = %s" \
-                            %(c, insn.reg_name(i.mem.index)))
+                            % (c, insn.reg_name(i.mem.index)))
                     if i.mem.length != 0:
                         print("\t\t\toperands[%u].mem.length: 0x%s" \
-                            %(c, to_x(i.mem.length)))
+                            % (c, to_x(i.mem.length)))
                     if i.mem.disp != 0:
                         print("\t\t\toperands[%u].mem.disp: 0x%s" \
-                            %(c, to_x(i.mem.disp)))
+                            % (c, to_x(i.mem.disp)))
                 c += 1
 
         if insn.cc:
-            print("\tConditional code: %u" %insn.cc)
+            print("\tConditional code: %u" % insn.cc)
 
     for (arch, mode, code, comment) in all_tests:
         print("*" * 16)
@@ -72,9 +65,10 @@
             for insn in md.disasm(code, 0x1000):
                 print_insn_detail(insn)
                 print
-            print "0x%x:\n" % (insn.address + insn.size)
+            print("0x%x:\n" % (insn.address + insn.size))
         except CsError as e:
             print("ERROR: %s" %e)
 
 
-test_class()
+if __name__ == '__main__':
+    test_class()
diff --git a/bindings/python/test_x86.py b/bindings/python/test_x86.py
index 78dc172..5e0f663 100755
--- a/bindings/python/test_x86.py
+++ b/bindings/python/test_x86.py
@@ -1,13 +1,14 @@
 #!/usr/bin/env python
 
 # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
-
+from __future__ import print_function
 from capstone import *
 from capstone.x86 import *
+from test import to_hex, to_x, to_x_32
 
-X86_CODE64 = "\x55\x48\x8b\x05\xb8\x13\x00\x00"
-X86_CODE16 = "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6"
-X86_CODE32 = "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6"
+X86_CODE64 = b"\x55\x48\x8b\x05\xb8\x13\x00\x00"
+X86_CODE16 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6"
+X86_CODE32 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6"
 
 all_tests = (
         (CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", 0),
@@ -16,34 +17,17 @@
         (CS_ARCH_X86, CS_MODE_64, X86_CODE64, "X86 64 (Intel syntax)", 0),
         )
 
-def to_hex(s):
-    return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK
-
-def to_x(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">q", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-def to_x_32(s):
-    from struct import pack
-    if not s: return '0'
-    x = pack(">i", s).encode('hex')
-    while x[0] == '0': x = x[1:]
-    return x
-
-### Test class Cs
+# ## Test class Cs
 def test_class():
     def print_string_hex(comment, str):
-        print(comment),
+        print(comment, end=' '),
         for c in str:
-            print("0x%02x" %c),
-        print
+            print("0x%02x" % c, end=''),
+        print()
 
     def print_insn_detail(mode, insn):
         # print address, mnemonic and operands
-        print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
+        print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
 
         # "data" instruction generated by SKIPDATA option has no detail
         if insn.id == 0:
@@ -54,61 +38,61 @@
 
         # print segment override (if applicable)
         if insn.segment != X86_REG_INVALID:
-            print("\tSegment override: %s" %insn.reg_name(insn.segment))
+            print("\tSegment override: %s" % insn.reg_name(insn.segment))
 
         # print instruction's opcode
         print_string_hex("\tOpcode:", insn.opcode)
 
         # print operand's size, address size, displacement size & immediate size
         print("\top_size: %u, addr_size: %u, disp_size: %u, imm_size: %u" \
-            %(insn.op_size, insn.addr_size, insn.disp_size, insn.imm_size))
+            % (insn.op_size, insn.addr_size, insn.disp_size, insn.imm_size))
 
         # print modRM byte
-        print("\tmodrm: 0x%x" %(insn.modrm))
+        print("\tmodrm: 0x%x" % (insn.modrm))
 
         # print displacement value
-        print("\tdisp: 0x%s" %to_x_32(insn.disp))
+        print("\tdisp: 0x%s" % to_x_32(insn.disp))
 
         # SIB is not available in 16-bit mode
         if (mode & CS_MODE_16 == 0):
             # print SIB byte
-            print("\tsib: 0x%x" %(insn.sib))
+            print("\tsib: 0x%x" % (insn.sib))
             if (insn.sib):
                 print("\tsib_index: %s, sib_scale: %d, sib_base: %s" % (insn.reg_name(insn.sib_index), insn.sib_scale, insn.reg_name(insn.sib_base)))
 
         count = insn.op_count(X86_OP_IMM)
         if count > 0:
-            print("\timm_count: %u" %count)
-            for i in xrange(count):
+            print("\timm_count: %u" % count)
+            for i in range(count):
                 op = insn.op_find(X86_OP_IMM, i + 1)
-                print("\t\timms[%u]: 0x%s" %(i+1, to_x(op.imm)))
+                print("\t\timms[%u]: 0x%s" % (i + 1, to_x(op.imm)))
 
         if len(insn.operands) > 0:
-            print("\top_count: %u" %len(insn.operands))
+            print("\top_count: %u" % len(insn.operands))
             c = -1
             for i in insn.operands:
                 c += 1
                 if i.type == X86_OP_REG:
-                    print("\t\toperands[%u].type: REG = %s" %(c, insn.reg_name(i.reg)))
+                    print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
                 if i.type == X86_OP_IMM:
-                    print("\t\toperands[%u].type: IMM = 0x%s" %(c, to_x(i.imm)))
+                    print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
                 if i.type == X86_OP_FP:
-                    print("\t\toperands[%u].type: FP = %f" %(c, i.fp))
+                    print("\t\toperands[%u].type: FP = %f" % (c, i.fp))
                 if i.type == X86_OP_MEM:
-                    print("\t\toperands[%u].type: MEM" %c)
+                    print("\t\toperands[%u].type: MEM" % c)
                     if i.mem.base != 0:
-                        print("\t\t\toperands[%u].mem.base: REG = %s" %(c, insn.reg_name(i.mem.base)))
+                        print("\t\t\toperands[%u].mem.base: REG = %s" % (c, insn.reg_name(i.mem.base)))
                     if i.mem.index != 0:
-                        print("\t\t\toperands[%u].mem.index: REG = %s" %(c, insn.reg_name(i.mem.index)))
+                        print("\t\t\toperands[%u].mem.index: REG = %s" % (c, insn.reg_name(i.mem.index)))
                     if i.mem.scale != 1:
-                        print("\t\t\toperands[%u].mem.scale: %u" %(c, i.mem.scale))
+                        print("\t\t\toperands[%u].mem.scale: %u" % (c, i.mem.scale))
                     if i.mem.disp != 0:
-                        print("\t\t\toperands[%u].mem.disp: 0x%s" %(c, to_x(i.mem.disp)))
+                        print("\t\t\toperands[%u].mem.disp: 0x%s" % (c, to_x(i.mem.disp)))
 
 
     for (arch, mode, code, comment, syntax) in all_tests:
         print("*" * 16)
-        print("Platform: %s" %comment)
+        print("Platform: %s" % comment)
         print("Code: %s" % to_hex(code))
         print("Disasm:")
 
@@ -124,7 +108,8 @@
                 print
             print ("0x%x:\n" % (insn.address + insn.size))
         except CsError as e:
-            print("ERROR: %s" %e)
+            print("ERROR: %s" % e)
 
 
-test_class()
+if __name__ == '__main__':
+    test_class()