aboutsummaryrefslogtreecommitdiffstats
path: root/capstone/suite/cstest
diff options
context:
space:
mode:
Diffstat (limited to 'capstone/suite/cstest')
-rw-r--r--capstone/suite/cstest/Makefile13
-rw-r--r--capstone/suite/cstest/README.md78
-rw-r--r--capstone/suite/cstest/build_cstest.sh9
-rwxr-xr-xcapstone/suite/cstest/cstest_report.py102
-rw-r--r--capstone/suite/cstest/include/capstone_test.h62
-rw-r--r--capstone/suite/cstest/include/factory.h27
-rw-r--r--capstone/suite/cstest/include/helper.h32
-rw-r--r--capstone/suite/cstest/issues.cs770
-rw-r--r--capstone/suite/cstest/src/arm64_detail.c138
-rw-r--r--capstone/suite/cstest/src/arm_detail.c150
-rw-r--r--capstone/suite/cstest/src/bpf_detail.c77
-rw-r--r--capstone/suite/cstest/src/capstone_test.c281
-rw-r--r--capstone/suite/cstest/src/evm_detail.c30
-rw-r--r--capstone/suite/cstest/src/helper.c267
-rw-r--r--capstone/suite/cstest/src/m680x_detail.c137
-rw-r--r--capstone/suite/cstest/src/m68k_detail.c116
-rw-r--r--capstone/suite/cstest/src/main.c454
-rw-r--r--capstone/suite/cstest/src/mips_detail.c48
-rw-r--r--capstone/suite/cstest/src/mos65xx_detail.c103
-rw-r--r--capstone/suite/cstest/src/ppc_detail.c91
-rw-r--r--capstone/suite/cstest/src/riscv_detail.c47
-rw-r--r--capstone/suite/cstest/src/sparc_detail.c55
-rw-r--r--capstone/suite/cstest/src/systemz_detail.c57
-rw-r--r--capstone/suite/cstest/src/tms320c64x_detail.c107
-rw-r--r--capstone/suite/cstest/src/x86_detail.c344
-rw-r--r--capstone/suite/cstest/src/xcore_detail.c52
26 files changed, 3647 insertions, 0 deletions
diff --git a/capstone/suite/cstest/Makefile b/capstone/suite/cstest/Makefile
new file mode 100644
index 000000000..fb4b7c294
--- /dev/null
+++ b/capstone/suite/cstest/Makefile
@@ -0,0 +1,13 @@
+SOURCE = src
+INCLUDE = include
+BUILD = build
+LIBRARY = -lcmocka -lcapstone -L../..
+
+all:
+ rm -rf $(BUILD)
+ mkdir $(BUILD)
+ $(CC) $(SOURCE)/*.c -I$(INCLUDE) -o $(BUILD)/cstest $(LIBRARY)
+cstest:
+ $(BUILD)/cstest -d ../MC
+clean:
+ rm -rf $(BUILD)
diff --git a/capstone/suite/cstest/README.md b/capstone/suite/cstest/README.md
new file mode 100644
index 000000000..a9880dadf
--- /dev/null
+++ b/capstone/suite/cstest/README.md
@@ -0,0 +1,78 @@
+# Regression testing
+This directory contains a tool for regression testing core of Capstone
+
+## Dependency
+
+- MacOS users can install cmocka with:
+
+```
+brew install cmocka
+```
+
+- Or download & build from source code [Cmocka](https://git.cryptomilk.org/projects/cmocka.git)
+
+- Build Cmocka
+
+```
+cd cmocka_dir
+mkdir build
+cd build
+cmake ..
+make
+sudo make isntall
+```
+
+## Build
+
+- Build `cstest`
+
+```
+cd suite/cstest
+make
+```
+
+## Usage
+
+- Usage: `cstest [-e] [-f <file_name.cs>] [-d <directory>]`
+ - `-e` : test all commented test
+
+- Test for all closed issues
+
+```
+cd suite/cstest
+./build/cstest -f ./issues.cs
+```
+
+- Test for some input from LLVM
+
+```
+cd suite/cstest
+./build/cstest -f ../MC/AArch64/basic-a64-instructions.s.cs
+```
+
+- Test for all cs file in a folder
+
+```
+cd suite/cstest
+./build/cstest -d ../MC
+```
+
+- Test all
+
+```
+cd suite/cstest
+make cstest
+```
+
+## Report tool
+
+- Usage `cstest_report.py [-Dc] -t <cstest_path> [-f <file_name.cs>] [-d <directory>]`
+ - `-D` : print details
+ - `-c` : auto comment out failed test
+
+- Example:
+
+```
+./cstest_report.py -t build/cstest -d ../MC/PowerPC/
+./cstest_report.py -t build/cstest -f issues.cs
+```
diff --git a/capstone/suite/cstest/build_cstest.sh b/capstone/suite/cstest/build_cstest.sh
new file mode 100644
index 000000000..5b4ba4c2b
--- /dev/null
+++ b/capstone/suite/cstest/build_cstest.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+cd cmocka && mkdir build && cd build
+if [ "$(uname)" = Darwin ]; then
+cmake -DCMAKE_INSTALL_PREFIX=/usr/local .. && make -j2 && sudo make install
+else # Linux
+cmake -DCMAKE_INSTALL_PREFIX=/usr .. && make -j2 && sudo make install
+fi
+cd ../.. && make
diff --git a/capstone/suite/cstest/cstest_report.py b/capstone/suite/cstest/cstest_report.py
new file mode 100755
index 000000000..17da3957f
--- /dev/null
+++ b/capstone/suite/cstest/cstest_report.py
@@ -0,0 +1,102 @@
+#!/usr/bin/python
+
+import re
+import sys
+import getopt
+from subprocess import Popen, PIPE
+from pprint import pprint as ppr
+import os
+
+
+def Usage(s):
+ print 'Usage: {} -t <cstest_path> [-f <file_name.cs>] [-d <directory>]'.format(s)
+ sys.exit(-1)
+
+def get_report_file(toolpath, filepath, getDetails, cmt_out):
+ cmd = [toolpath, '-f', filepath]
+ process = Popen(cmd, stdout=PIPE, stderr=PIPE)
+ stdout, stderr = process.communicate()
+
+# stdout
+ failed_tests = []
+# print '---> stdout\n', stdout
+# print '---> stderr\n', stderr
+ matches = re.finditer(r'\[\s+RUN\s+\]\s+(.*)\n\[\s+FAILED\s+\]', stdout)
+ for match in matches:
+ failed_tests.append(match.group(1))
+# stderr
+ counter = 0
+ details = []
+ for line in stderr.split('\n'):
+ if '[ PASSED ] 0 test(s).' in line:
+ break
+ elif 'LINE' in line:
+ continue
+ elif 'ERROR' in line and ' --- ' in line:
+ parts = line.split(' --- ')
+ try:
+ details.append((parts[1], failed_tests[counter], parts[2]))
+ except IndexError:
+ details.append(('', 'Unknown test', line.split(' --- ')[1]))
+ counter += 1
+ else:
+ continue
+ print '\n[-] There are/is {} failed test(s)'.format(len(details))
+ if len(details) > 0 and getDetails:
+ print '[-] Detailed report for {}:\n'.format(filepath)
+ for c, f, d in details:
+ print '\t[+] {}: {}\n\t\t{}\n'.format(f, c, d)
+ print '\n'
+ return 0
+ elif len(details) > 0:
+ for c, f, d in details:
+ if len(f) > 0 and cmt_out is True:
+ tmp_cmd = ['sed', '-E', '-i.bak', 's/({})(.*)/\/\/ \\1\\2/g'.format(c), filepath]
+ sed_proc = Popen(tmp_cmd, stdout=PIPE, stderr=PIPE)
+ sed_proc.communicate()
+ tmp_cmd2 = ['rm', '-f', filepath + '.bak']
+ rm_proc = Popen(tmp_cmd2, stdout=PIPE, stderr=PIPE)
+ rm_proc.communicate()
+
+ return 0;
+ return 1
+
+def get_report_folder(toolpath, folderpath, details, cmt_out):
+ result = 1
+ for root, dirs, files in os.walk(folderpath):
+ path = root.split(os.sep)
+ for f in files:
+ if f.split('.')[-1] == 'cs':
+ print '[-] Target:', f,
+ result *= get_report_file(toolpath, os.sep.join(x for x in path) + os.sep + f, details, cmt_out)
+
+ sys.exit(result ^ 1)
+
+if __name__ == '__main__':
+ Done = False
+ details = False
+ toolpath = ''
+ cmt_out = False
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "ct:f:d:D")
+ for opt, arg in opts:
+ if opt == '-f':
+ result = get_report_file(toolpath, arg, details, cmt_out)
+ if result == 0:
+ sys.exit(1)
+ Done = True
+ elif opt == '-d':
+ get_report_folder(toolpath, arg, details, cmt_out)
+ Done = True
+ elif opt == '-t':
+ toolpath = arg
+ elif opt == '-D':
+ details = True
+ elif opt == '-c':
+ cmt_out = True
+
+ except getopt.GetoptError:
+ Usage(sys.argv[0])
+
+ if Done is False:
+ Usage(sys.argv[0])
diff --git a/capstone/suite/cstest/include/capstone_test.h b/capstone/suite/cstest/include/capstone_test.h
new file mode 100644
index 000000000..5936678f0
--- /dev/null
+++ b/capstone/suite/cstest/include/capstone_test.h
@@ -0,0 +1,62 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#ifndef CAPSTONE_TEST_H
+#define CAPSTONE_TEST_H
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <stdlib.h>
+#include <string.h>
+#include <capstone/capstone.h>
+#include "helper.h"
+#include "factory.h"
+
+#define cs_assert_err(expect, err) \
+ do { \
+ cs_err __err = err; \
+ if (__err != expect) { \
+ fail_msg("%s",cs_strerror(__err)); \
+ } \
+ } while (0)
+
+
+#define cs_assert_success(err) cs_assert_err(CS_ERR_OK, err)
+
+
+#define cs_assert_fail(err) \
+ do { \
+ cs_err __err = err; \
+ if (__err == CS_ERR_OK) { \
+ fail_msg("%s",cs_strerror(__err)); \
+ } \
+ } while (0)
+
+#define NUMARCH 10
+#define NUMMODE 35
+#define NUMOPTION 41
+#define MAXMEM 1024
+
+typedef struct {
+ const char *str;
+ unsigned int value;
+} single_dict;
+
+typedef struct {
+ const char *str;
+ unsigned int first_value;
+ unsigned int second_value;
+} double_dict;
+
+extern char *(*function)(csh *, cs_mode, cs_insn*);
+
+int get_index(double_dict d[], unsigned size, const char *str);
+int get_value(single_dict d[], unsigned size, const char *str);
+void test_single_MC(csh *handle, int mc_mode, char *line);
+void test_single_issue(csh *handle, cs_mode mode, char *line, int detail);
+int set_function(int arch);
+
+#endif /* CAPSTONE_TEST_H */
diff --git a/capstone/suite/cstest/include/factory.h b/capstone/suite/cstest/include/factory.h
new file mode 100644
index 000000000..7df6c7838
--- /dev/null
+++ b/capstone/suite/cstest/include/factory.h
@@ -0,0 +1,27 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#ifndef FACTORY_H
+#define FACTORY_H
+
+#include <capstone/capstone.h>
+#include "helper.h"
+
+char *get_detail_evm(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_arm(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_arm64(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_m680x(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_mips(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_ppc(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_sparc(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_sysz(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_x86(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_xcore(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_riscv(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_m68k(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_mos65xx(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_tms320c64x(csh *handle, cs_mode mode, cs_insn *ins);
+char *get_detail_bpf(csh *handle, cs_mode mode, cs_insn *ins);
+
+#endif /* FACTORY_H */
diff --git a/capstone/suite/cstest/include/helper.h b/capstone/suite/cstest/include/helper.h
new file mode 100644
index 000000000..102230385
--- /dev/null
+++ b/capstone/suite/cstest/include/helper.h
@@ -0,0 +1,32 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#ifndef HELPER_H
+#define HELPER_H
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <dirent.h>
+#include "capstone_test.h"
+
+#define X86_16 0
+#define X86_32 1
+#define X86_64 2
+
+char **split(char *str, char *delim, int *size);
+void print_strs(char **list_str, int size);
+void free_strs(char **list_str, int size);
+void add_str(char **src, const char *format, ...);
+void trim_str(char *src);
+void replace_hex(char *src);
+void replace_negative(char *src, int mode);
+const char *get_filename_ext(const char *filename);
+
+char *readfile(const char *filename);
+void listdir(const char *name, char ***files, int *num_files);
+
+#endif /* HELPER_H */
diff --git a/capstone/suite/cstest/issues.cs b/capstone/suite/cstest/issues.cs
new file mode 100644
index 000000000..d8b0b7ebc
--- /dev/null
+++ b/capstone/suite/cstest/issues.cs
@@ -0,0 +1,770 @@
+!# issue 1504 movhps qword ptr
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x0f,0x16,0x08 == movhps xmm1, qword ptr [rax] ; Opcode:0x0f 0x16 0x00 0x00
+
+!# issue 1505 opcode 0f
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x0f,0xa5,0xc2 == shld edx, eax, cl ; Opcode:0x0f 0xa5 0x00 0x00
+
+!# issue 1478 tbegin.
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x7c,0x20,0x05,0x1d == tbegin. 1 ; Update-CR0: True
+
+!# issue 970 PPC bdnzt lt
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x41,0x00,0xff,0xac == bdnzt lt, 0xffffffffffffffac ; operands[0].type: REG = cr0lt
+
+!# issue 970 PPC bdnzt eq
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x41,0x02,0xff,0xac == bdnzt eq, 0xffffffffffffffac ; operands[0].type: REG = cr0eq
+
+!# issue 969 PPC bdnzflr operand 2
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x4c,0x10,0x00,0x20 == bdnzflr 4*cr4+lt ; operands[0].type: REG = cr4lt
+
+0x41,0x82,0x00,0x10 == beq 0x10 ; Groups: jump
+
+!# issue 1481 ARM64 LDR operand2
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL
+0xe9,0x03,0x40,0xf9 == ldr x9, [sp] ; operands[1].mem.base: REG = sp
+
+!# issue 968 PPC absolute branch: bdnzla
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None
+0x1000: 0x42,0x00,0x12,0x37 == bdnzla 0x1234
+
+!# issue 968 PPC absolute branch: bdzla
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None
+0x1000: 0x42,0x40,0x12,0x37 == bdzla 0x1234
+
+!# issue X86 xrelease xchg
+!# CS_ARCH_X86, CS_MODE_32, None
+0xf3,0x87,0x03 == xrelease xchg dword ptr [ebx], eax
+
+!# issue X86 xacquire xchg
+!# CS_ARCH_X86, CS_MODE_32, None
+0xf2,0x87,0x03 == xacquire xchg dword ptr [ebx], eax
+
+!# issue X86 xrelease
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0xf0,0x31,0x1f == xrelease lock xor dword ptr [rdi], ebx
+
+!# issue 1477 X86 xacquire
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf2,0xf0,0x31,0x1f == xacquire lock xor dword ptr [rdi], ebx
+
+!# issue PPC JUMP group
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x41,0x82,0x00,0x10 == beq 0x10 ; Groups: jump
+
+!# issue 1468 PPC bdnz
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None
+0x101086c: 0x42,0x00,0xff,0xf8 == bdnz 0x1010864
+
+!# issue PPC bdnzt
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None
+0x1000: 0x41,0x00,0xff,0xac == bdnzt lt, 0xfac
+
+!# issue 1469 PPC CRx
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x4c,0x02,0x39,0x82 == crxor cr0lt, cr0eq, cr1un ; operands[0].type: REG = cr0lt
+
+!# issue 1468 B target
+!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None
+0x1000: 0x4b,0xff,0xf8,0x00 == b 0x800
+
+!# issue 1456 test alt 1
+!# CS_ARCH_X86, CS_MODE_32, None
+0xf6,0x08,0x00 == test byte ptr [eax], 0
+
+!# issue 1456 test alt 2
+!# CS_ARCH_X86, CS_MODE_32, None
+0xf7,0x08,0x00,0x00,0x00,0x00 == test dword ptr [eax], 0
+
+!# issue 1472 lock sub
+!# CS_ARCH_X86, CS_MODE_32, None
+0xF0,0x2B,0x45,0x08 == lock sub eax, dword ptr [ebp + 8]
+
+!# issue 1472 lock or
+!# CS_ARCH_X86, CS_MODE_32, None
+0xF0,0x0B,0x45,0x08 == lock or eax, dword ptr [ebp + 8]
+
+!# issue 1472 lock and
+!# CS_ARCH_X86, CS_MODE_32, None
+0xF0,0x23,0x45,0x08 == lock and eax, dword ptr [ebp + 8]
+
+!# issue 1472 lock add
+!# CS_ARCH_X86, CS_MODE_32, None
+0xF0,0x03,0x45,0x08 == lock add eax, dword ptr [ebp + 8]
+
+!# issue 1456 MOV dr
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0f,0x23,0x00 == mov dr0, eax
+
+!# issue 1456 MOV dr
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0f,0x21,0x00 == mov eax, dr0
+
+!# issue 1456 MOV cr
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0f,0x22,0x00 == mov cr0, eax
+
+!# issue 1472 lock adc
+!# CS_ARCH_X86, CS_MODE_32, None
+0xf0,0x12,0x45,0x08 == lock adc al, byte ptr [ebp + 8]
+
+!# issue 1456 xmmword
+!# CS_ARCH_X86, CS_MODE_32, None
+0x66,0x0f,0x2f,0x00 == comisd xmm0, xmmword ptr [eax]
+
+!# issue 1456 ARM printPKHASRShiftImm
+!# CS_ARCH_ARM, CS_MODE_THUMB, None
+0xca,0xea,0x21,0x06 == pkhtb r6, sl, r1, asr #0x20
+
+!# issue 1456 EIZ
+!# CS_ARCH_X86, CS_MODE_32, None
+0x8d,0xb4,0x26,0x00,0x00,0x00,0x00 == lea esi, [esi]
+
+!# issue 1456 ARM POP
+!# CS_ARCH_ARM, CS_MODE_LITTLE_ENDIAN, None
+0x04,0x10,0x9d,0xe4 == pop {r1}
+
+!# issue 1456
+!# CS_ARCH_ARM, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL
+0x31,0x02,0xa0,0xe1 == lsr r0, r1, r2 ; operands[2].type: REG = r2
+
+!# issue 1456
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL
+0x0c,0x00,0x80,0x12 == mov w12, #-1 ; operands[1].type: IMM = 0xffffffffffffffff
+
+0xb8,0x00,0x00,0x00,0x00 == movl $0, %eax
+
+!# issue 1456
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_ATT
+0xb8,0x00,0x00,0x00,0x00 == movl $0, %eax
+
+0xd1,0x5e,0x48 == rcrl $1, 0x48(%esi)
+
+!# issue 1456
+!# CS_ARCH_X86, CS_MODE_32, None
+0xd1,0x5e,0x48 == rcr dword ptr [esi + 0x48], 1
+
+!# issue 1456
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_ATT
+0xd1,0x5e,0x48 == rcrl $1, 0x48(%esi)
+
+!# issue 1456
+!# CS_ARCH_X86, CS_MODE_32, None
+0x62,0x00 == bound eax, qword ptr [eax]
+
+!# issue 1454
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0xf0,0x0f,0xb1,0x1e == lock cmpxchg dword ptr [esi], ebx ; Registers read: eax esi ebx
+
+!# issue 1452
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL
+0x20,0x3c,0x0c,0x0e == mov w0, v1.s[1] ; Vector Arrangement Specifier: 0xb
+
+!# issue 1452
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL
+0x20,0x3c,0x18,0x4e == mov x0, v1.d[1] ; Vector Arrangement Specifier: 0xd
+
+!# issue 1452
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL
+0x20,0x3c,0x03,0x0e == umov w0, v1.b[1] ; Vector Arrangement Specifier: 0x4
+
+!# issue 1452
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL
+0x20,0x3c,0x06,0x0e == umov w0, v1.h[1] ; Vector Arrangement Specifier: 0x8
+
+!# issue 1211
+!# CS_ARCH_X86, CS_MODE_64, None
+0xc4,0xe1,0xf8,0x90,0xc0 == kmovq k0, k0
+
+!# issue 1211
+!# CS_ARCH_X86, CS_MODE_64, None
+0xc4,0xe1,0xfb,0x92,0xc3 == kmovq k0, rbx
+
+!# issue 1211
+!# CS_ARCH_X86, CS_MODE_64, None
+0x62,0xf1,0x7d,0x48,0x74,0x83,0x12,0x00,0x00,0x00 == vpcmpeqb k0, zmm0, zmmword ptr [rbx + 0x12]
+
+!# issue 1211
+!# CS_ARCH_X86, CS_MODE_64, None
+0x62,0xf2,0x7d,0x48,0x30,0x43,0x08 == vpmovzxbw zmm0, ymmword ptr [rbx + 0x100]
+
+!# issue x86 BND register (OSS-fuzz #13467)
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0f,0x1a,0x1a == bndldx bnd3, [edx] ; operands[0].type: REG = bnd3
+
+!# issue 1335
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0f,0x1f,0xc0 == nop eax
+
+!# issue 1335
+!# CS_ARCH_X86, CS_MODE_64, None
+0x48,0x0f,0x1f,0x00 == nop qword ptr [rax]
+
+!# issue 1259
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0f,0x0d,0x44,0x11,0x40 == prefetch byte ptr [rcx + rdx + 0x40]
+
+!# issue 1259
+!# CS_ARCH_X86, CS_MODE_64, None
+0x41,0x0f,0x0d,0x44,0x12,0x40 == prefetch byte ptr [r10 + rdx + 0x40]
+
+!# issue 1304
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x66,0x0f,0x7f,0x4c,0x24,0x40 == movdqa xmmword ptr [rsp + 0x40], xmm1 ; operands[0].access: WRITE
+
+!# issue 1304
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x66,0x0f,0x7e,0x04,0x24 == movd dword ptr [rsp], xmm0 ; operands[0].access: WRITE
+
+!# issue 1304
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0xf3,0x41,0x0f,0x7f,0x4d,0x00 == movdqu xmmword ptr [r13], xmm1 ; operands[0].access: WRITE
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x48,0x0f,0x1e,0xc8 == rdsspq rax
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x0f,0x1e,0xc8 == rdsspd eax
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x48,0x0f,0xae,0xe8 == incsspq rax
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x0f,0xae,0xe8 == incsspd eax
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x0f,0x01,0xea == saveprevssp
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x0f,0x01,0x28 == rstorssp dword ptr [rax]
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0x67,0xf3,0x0f,0x01,0x28 == rstorssp dword ptr [eax]
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0x48,0x0f,0x38,0xf6,0x00 == wrssq qword ptr [rax], rax
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0x67,0x0f,0x38,0xf6,0x00 == wrssd dword ptr [eax], eax
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x0f,0x01,0xe8 == setssbsy
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x0f,0xae,0x30 == clrssbsy dword ptr [rax]
+
+!# issue 1346
+!# CS_ARCH_X86, CS_MODE_64, None
+0x67,0xf3,0x0f,0xae,0x30 == clrssbsy dword ptr [eax]
+
+!# issue 1206
+!# CS_ARCH_X86, CS_MODE_64, None
+0xc4,0xe2,0x7d,0x5a,0x0c,0x0e == vbroadcasti128 ymm1, xmmword ptr [rsi + rcx]
+
+!# issue xchg 16bit
+!# CS_ARCH_X86, CS_MODE_16, None
+0x91 == xchg cx, ax
+
+!# issue ROL 1, ATT syntax
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT
+0x66,0x48,0xf3,0xd1,0xc0 == rolw $1, %ax
+
+!# issue 1129
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x0f,0x1e,0xfa == endbr64
+
+!# issue 1129
+!# CS_ARCH_X86, CS_MODE_32, None
+0xf3,0x0f,0x1e,0xfa == endbr64
+
+!# issue 1129
+!# CS_ARCH_X86, CS_MODE_64, None
+0xf3,0x0f,0x1e,0xfb == endbr32
+
+!# issue 1129
+!# CS_ARCH_X86, CS_MODE_32, None
+0xf3,0x0f,0x1e,0xfb == endbr32
+
+!# issue x64 jmp
+!# CS_ARCH_X86, CS_MODE_64, None
+0x1000: 0xeb,0xfe == jmp 0x1000
+
+!# issue x64att jmp
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT
+0x1000: 0xeb,0xfe == jmp 0x1000
+
+!# issue x32 jmp
+!# CS_ARCH_X86, CS_MODE_32, None
+0x1000: 0xeb,0xfe == jmp 0x1000
+
+!# issue x32att jmp
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_ATT
+0x1000: 0xeb,0xfe == jmp 0x1000
+
+!# issue 1389
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x66,0x0f,0x73,0xf9,0x01 == pslldq xmm1, 1 ; operands[1].size: 1
+
+!# issue 1389
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT | CS_OPT_DETAIL
+0x66,0x0f,0x73,0xf9,0x01 == pslldq $1, %xmm1 ; operands[0].size: 1
+
+!# issue x64 unsigned
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_UNSIGNED
+0x66,0x83,0xc0,0x80 == add ax, 0xff80
+
+!# issue x64att unsigned
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT | CS_OPT_UNSIGNED
+0x66,0x83,0xc0,0x80 == addw $0xff80, %ax
+
+!# issue 1323
+!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL
+0x0: 0x70,0x47,0x00 == bx lr ; op_count: 1 ; operands[0].type: REG = lr ; operands[0].access: READ ; Registers read: lr ; Registers modified: pc ; Groups: thumb jump
+
+!# issue 1317
+!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL
+0x0: 0xd0,0xe8,0x11,0xf0 == tbh [r0, r1, lsl #1] ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = r0 ; operands[0].mem.index: REG = r1 ; operands[0].mem.lshift: 0x1 ; operands[0].access: READ ; Shift: 2 = 1 ; Registers read: r0 r1 ; Groups: thumb2 jump
+
+!# issue 1308
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x0: 0x83,0x3d,0xa1,0x75,0x21,0x00,0x04 == cmp dword ptr [rip + 0x2175a1], 4 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x83 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x3d ; disp: 0x2175a1 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0x4 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.base: REG = rip ; operands[0].mem.disp: 0x2175a1 ; operands[0].size: 4 ; operands[0].access: READ ; operands[1].type: IMM = 0x4 ; operands[1].size: 4 ; Registers read: rip ; Registers modified: rflags ; EFLAGS: MOD_AF MOD_CF MOD_SF MOD_ZF MOD_PF MOD_OF
+
+!# issue 1262
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x0: 0x0f,0x95,0x44,0x24,0x5e == setne byte ptr [rsp + 0x5e] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x0f 0x95 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x44 ; disp: 0x5e ; sib: 0x24 ; sib_base: rsp ; sib_scale: 1 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = rsp ; operands[0].mem.disp: 0x5e ; operands[0].size: 1 ; operands[0].access: WRITE ; Registers read: rflags rsp ; EFLAGS: TEST_ZF
+
+!# issue 1262
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x0: 0x0f,0x94,0x44,0x24,0x1f == sete byte ptr [rsp + 0x1f] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x0f 0x94 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x44 ; disp: 0x1f ; sib: 0x24 ; sib_base: rsp ; sib_scale: 1 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = rsp ; operands[0].mem.disp: 0x1f ; operands[0].size: 1 ; operands[0].access: WRITE ; Registers read: rflags rsp ; EFLAGS: TEST_ZF
+
+!# issue 1263
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0x67,0x48,0x89,0x18 == mov qword ptr [eax], rbx
+
+!# issue 1263
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0x67,0x48,0x8b,0x03 == mov rax, qword ptr [ebx]
+
+!# issue 1255
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x0: 0xdb,0x7c,0x24,0x40 == fstp xword ptr [rsp + 0x40] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xdb 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x7c ; disp: 0x40 ; sib: 0x24 ; sib_base: rsp ; sib_scale: 1 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = rsp ; operands[0].mem.disp: 0x40 ; operands[0].size: 10 ; operands[0].access: WRITE ; Registers read: rsp ; Registers modified: fpsw ; FPU_FLAGS: MOD_C1 UNDEF_C0 UNDEF_C2 UNDEF_C3 ; Groups: fpu
+
+!# issue 1255
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x0: 0xdd,0xd9 == fstp st(1) ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xdd 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0xd9 ; disp: 0x0 ; sib: 0x0 ; op_count: 1 ; operands[0].type: REG = st(1) ; operands[0].size: 10 ; operands[0].access: WRITE ; Registers modified: fpsw st(1) ; EFLAGS: MOD_CF PRIOR_SF PRIOR_AF PRIOR_PF
+
+!# issue 1255
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x0: 0xdf,0x7c,0x24,0x68 == fistp qword ptr [rsp + 0x68] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xdf 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x7c ; disp: 0x68 ; sib: 0x24 ; sib_base: rsp ; sib_scale: 1 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = rsp ; operands[0].mem.disp: 0x68 ; operands[0].size: 8 ; operands[0].access: WRITE ; Registers read: rsp ; Registers modified: fpsw ; FPU_FLAGS: RESET_C1 UNDEF_C0 UNDEF_C2 UNDEF_C3 ; Groups: fpu
+
+!# issue 1221
+!# CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, None
+0x0: 0x55,0x48,0x89,0xe5 == call 0x55222794
+
+!# issue 1144
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None
+0x0: 0x00,0x00,0x02,0xb6 == tbz x0, #0x20, #0x4000
+
+!# issue 1144
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None
+0x0: 0x00,0x00,0x04,0xb6 == tbz x0, #0x20, #0xffffffffffff8000
+
+!# issue 1144
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None
+0x0: 0x00,0x00,0x02,0xb7 == tbnz x0, #0x20, #0x4000
+
+!# issue 1144
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None
+0x0: 0x00,0x00,0x04,0xb7 == tbnz x0, #0x20, #0xffffffffffff8000
+
+!# issue 826
+!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0x0b,0x00,0x00,0x0a == beq #0x34 ; op_count: 1 ; operands[0].type: IMM = 0x34 ; Code condition: 1 ; Registers read: pc ; Registers modified: pc ; Groups: branch_relative arm jump
+
+!# issue 1047
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT
+0x0: 0x48,0x83,0xe4,0xf0 == andq $0xfffffffffffffff0, %rsp
+
+!# issue 959
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xa0,0x28,0x57,0x88,0x7c == mov al, byte ptr [0x7c885728]
+
+!# issue 950
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0x66,0xa3,0x94,0x90,0x04,0x08 == mov word ptr [0x8049094], ax ; Prefix:0x00 0x00 0x66 0x00 ; Opcode:0xa3 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x8049094 ; sib: 0x0 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.disp: 0x8049094 ; operands[0].size: 2 ; operands[0].access: WRITE ; operands[1].type: REG = ax ; operands[1].size: 2 ; operands[1].access: READ ; Registers read: ax
+
+!# issue 938
+!# CS_ARCH_MIPS, CS_MODE_MIPS64+CS_MODE_LITTLE_ENDIAN, None
+0x0: 0x70,0x00,0xb2,0xff == sd $s2, 0x70($sp)
+
+!# issue 915
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0xf0,0x0f,0x1f,0x00 == lock nop dword ptr [rax]
+
+// !# issue 913
+// !# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0x04,0x10,0x9d,0xe4 == pop {r1} ; op_count: 1 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; Write-back: True ; Registers read: sp ; Registers modified: sp r1 ; Groups: arm
+
+!# issue 884
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT
+0x0: 0x64,0x48,0x03,0x04,0x25,0x00,0x00,0x00,0x00 == addq %fs:0, %rax
+
+!# issue 872
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xf2,0xeb,0x3e == bnd jmp 0x41
+
+!# issue 861
+!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0x01,0x81,0xa0,0xfc == stc2 p1, c8, [r0], #4 ; op_count: 4 ; operands[0].type: P-IMM = 1 ; operands[1].type: C-IMM = 8 ; operands[2].type: MEM ; operands[2].mem.base: REG = r0 ; operands[2].access: READ ; operands[3].type: IMM = 0x4 ; Write-back: True ; Registers read: r0 ; Registers modified: r0 ; Groups: prev8
+
+!# issue 852
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0x64,0xa3,0x00,0x00,0x00,0x00 == mov dword ptr fs:[0], eax ; Prefix:0x00 0x64 0x00 0x00 ; Opcode:0xa3 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.segment: REG = fs ; operands[0].size: 4 ; operands[0].access: WRITE ; operands[1].type: REG = eax ; operands[1].size: 4 ; operands[1].access: READ ; Registers read: fs eax
+
+!# issue 825
+!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0x0e,0xf0,0xa0,0xe1 == mov pc, lr ; op_count: 2 ; operands[0].type: REG = pc ; operands[0].access: WRITE ; operands[1].type: REG = lr ; operands[1].access: READ ; Registers read: lr ; Registers modified: pc ; Groups: arm
+
+!# issue 813
+!# CS_ARCH_ARM, CS_MODE_THUMB | CS_MODE_BIG_ENDIAN, None
+0x0: 0xF6,0xC0,0x04,0x01 == movt r4, #0x801
+
+!# issue 809
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL
+0x0: 0x0f,0x29,0x8d,0xf0,0xfd,0xff,0xff == movaps xmmword ptr [rbp - 0x210], xmm1 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x0f 0x29 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x8d ; disp: 0xfffffffffffffdf0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.base: REG = rbp ; operands[0].mem.disp: 0xfffffffffffffdf0 ; operands[0].size: 16 ; operands[0].access: WRITE ; operands[1].type: REG = xmm1 ; operands[1].size: 16 ; operands[1].access: READ ; Registers read: rbp xmm1 ; Groups: sse1
+
+!# issue 807
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0x4c,0x0f,0x00,0x80,0x16,0x76,0x8a,0xfe == sldt word ptr [rax - 0x17589ea]
+
+!# issue 806
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0x0f,0x35 == sysexit
+
+!# issue 805
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT
+0x0: 0x48,0x4c,0x0f,0xb5,0x80,0x16,0x76,0x8a,0xfe == lgs -0x17589ea(%rax), %r8
+
+!# issue 804
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT
+0x0: 0x66,0x48,0xf3,0xd1,0xc0 == rolw $1, %ax
+
+!# issue 789
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT
+0x0: 0x8e,0x1e == movw (%rsi), %ds
+
+!# issue 767
+!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL
+0x0: 0xb1,0xe8,0xfc,0x07 == ldm.w r1!, {r2, r3, r4, r5, r6, r7, r8, sb, sl} ; op_count: 10 ; operands[0].type: REG = r1 ; operands[0].access: READ | WRITE ; operands[1].type: REG = r2 ; operands[1].access: WRITE ; operands[2].type: REG = r3 ; operands[2].access: WRITE ; operands[3].type: REG = r4 ; operands[3].access: WRITE ; operands[4].type: REG = r5 ; operands[4].access: WRITE ; operands[5].type: REG = r6 ; operands[5].access: WRITE ; operands[6].type: REG = r7 ; operands[6].access: WRITE ; operands[7].type: REG = r8 ; operands[7].access: WRITE ; operands[8].type: REG = sb ; operands[8].access: WRITE ; operands[9].type: REG = sl ; operands[9].access: WRITE ; Write-back: True ; Registers read: r1 ; Registers modified: r1 r2 r3 r4 r5 r6 r7 r8 sb sl ; Groups: thumb2
+
+!# issue 760
+!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0x02,0x80,0xbd,0xe8 == pop {r1, pc} ; op_count: 2 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; operands[1].type: REG = pc ; operands[1].access: WRITE ; Registers read: sp ; Registers modified: sp r1 pc ; Groups: arm
+
+!# issue 750
+!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0x0e,0x00,0x20,0xe9 == stmdb r0!, {r1, r2, r3} ; op_count: 4 ; operands[0].type: REG = r0 ; operands[0].access: READ ; operands[1].type: REG = r1 ; operands[2].type: REG = r2 ; operands[3].type: REG = r3 ; Write-back: True ; Registers read: r0 ; Groups: arm
+
+!# issue 747
+!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0x0e,0x00,0xb0,0xe8 == ldm r0!, {r1, r2, r3} ; op_count: 4 ; operands[0].type: REG = r0 ; operands[0].access: READ | WRITE ; operands[1].type: REG = r1 ; operands[1].access: WRITE ; operands[2].type: REG = r2 ; operands[2].access: WRITE ; operands[3].type: REG = r3 ; operands[3].access: WRITE ; Write-back: True ; Registers read: r0 ; Registers modified: r0 r1 r2 r3 ; Groups: arm
+
+!# issue 747
+!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL
+0x0: 0x0e,0xc8 == ldm r0!, {r1, r2, r3} ; op_count: 4 ; operands[0].type: REG = r0 ; operands[0].access: READ | WRITE ; operands[1].type: REG = r1 ; operands[1].access: WRITE ; operands[2].type: REG = r2 ; operands[2].access: WRITE ; operands[3].type: REG = r3 ; operands[3].access: WRITE ; Write-back: True ; Registers read: r0 ; Registers modified: r0 r1 r2 r3 ; Groups: thumb thumb1only
+
+!# issue 746
+!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0x89,0x00,0x2d,0xe9 == push {r0, r3, r7} ; op_count: 3 ; operands[0].type: REG = r0 ; operands[0].access: READ ; operands[1].type: REG = r3 ; operands[1].access: READ ; operands[2].type: REG = r7 ; operands[2].access: READ ; Registers read: sp r0 r3 r7 ; Registers modified: sp ; Groups: arm
+
+!# issue 744
+!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0x02,0x80,0xbd,0xe8 == pop {r1, pc} ; op_count: 2 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; operands[1].type: REG = pc ; operands[1].access: WRITE ; Registers read: sp ; Registers modified: sp r1 pc ; Groups: arm
+
+!# issue 741
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x83,0xff,0xf7 == cmp edi, -9
+
+!# issue 717
+!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT
+0x0: 0x48,0x8b,0x04,0x25,0x00,0x00,0x00,0x00 == movq 0, %rax
+
+!# issue 711
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0xa3,0x44,0xb0,0x00,0x10 == mov dword ptr [0x1000b044], eax ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xa3 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x1000b044 ; sib: 0x0 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.disp: 0x1000b044 ; operands[0].size: 4 ; operands[0].access: WRITE ; operands[1].type: REG = eax ; operands[1].size: 4 ; operands[1].access: READ ; Registers read: eax
+
+!# issue 613
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0xd9,0x74,0x24,0xd8 == fnstenv [rsp - 0x28]
+
+!# issue 554
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xe7,0x84 == out 0x84, eax
+
+!# issue 554
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xe5,0x8c == in eax, 0x8c
+
+!# issue 545
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0x95 == xchg ebp, eax ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x95 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: REG = ebp ; operands[0].size: 4 ; operands[0].access: READ | WRITE ; operands[1].type: REG = eax ; operands[1].size: 4 ; operands[1].access: READ | WRITE ; Registers read: ebp eax ; Registers modified: ebp eax ; Groups: not64bitmode
+
+!# issue 544
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xdf,0x30 == fbstp tbyte ptr [eax]
+
+!# issue 544
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xdf,0x20 == fbld tbyte ptr [eax]
+
+!# issue 541
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0x48,0xb8,0x00,0x00,0x00,0x00,0x80,0xf8,0xff,0xff == movabs rax, 0xfffff88000000000
+
+!# issue 499
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0x48,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80 == movabs rax, 0x8000000000000000
+
+!# issue 492
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xff,0x18 == call ptr [eax]
+
+!# issue 492
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xff,0x28 == jmp ptr [eax]
+
+!# issue 492
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x0f,0xae,0x04,0x24 == fxsave [esp]
+
+!# issue 492
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x0f,0xae,0x0c,0x24 == fxrstor [esp]
+
+!# issue 470
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x0f,0x01,0x05,0xa0,0x90,0x04,0x08 == sgdt [0x80490a0]
+
+!# issue 470
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x0f,0x01,0x0d,0xa7,0x90,0x04,0x08 == sidt [0x80490a7]
+
+!# issue 470
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x0f,0x01,0x15,0xa0,0x90,0x04,0x08 == lgdt [0x80490a0]
+
+!# issue 470
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x0f,0x01,0x1d,0xa7,0x90,0x04,0x08 == lidt [0x80490a7]
+
+!# issue 459
+!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
+0x0: 0xd3,0x20,0x11,0xe1 == ldrsb r2, [r1, -r3] ; op_count: 2 ; operands[0].type: REG = r2 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = r1 ; operands[1].mem.index: REG = r3 ; operands[1].mem.scale: -1 ; Subtracted: True ; Registers read: r1 r3 ; Registers modified: r2 ; Groups: arm
+
+!# issue 456
+!# CS_ARCH_X86, CS_MODE_16, None
+0x0: 0xe8,0x35,0x64 == call 0x6438
+
+!# issue 456
+!# CS_ARCH_X86, CS_MODE_16, None
+0x0: 0xe9,0x35,0x64 == jmp 0x6438
+
+!# issue 456
+!# CS_ARCH_X86, CS_MODE_16, None
+0x0: 0x66,0xe9,0x35,0x64,0x93,0x53 == jmp 0x5393643b
+
+!# issue 456
+!# CS_ARCH_X86, CS_MODE_16, None
+0x0: 0x66,0xe8,0x35,0x64,0x93,0x53 == call 0x5393643b
+
+!# issue 456
+!# CS_ARCH_X86, CS_MODE_16, None
+0x0: 0x66,0xe9,0x35,0x64,0x93,0x53 == jmp 0x5393643b
+
+!# issue 456
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x66,0xe8,0x35,0x64 == call 0x6439
+
+!# issue 456
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xe9,0x35,0x64,0x93,0x53 == jmp 0x5393643a
+
+!# issue 456
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x66,0xe9,0x35,0x64 == jmp 0x6439
+
+!# issue 458
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0xA1,0x12,0x34,0x90,0x90 == mov eax, dword ptr [0x90903412] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xa1 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x90903412 ; sib: 0x0 ; op_count: 2 ; operands[0].type: REG = eax ; operands[0].size: 4 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.disp: 0x90903412 ; operands[1].size: 4 ; operands[1].access: READ ; Registers modified: eax
+
+!# issue 454
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xf2,0x6c == repne insb byte ptr es:[edi], dx
+
+!# issue 454
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xf2,0x6d == repne insd dword ptr es:[edi], dx
+
+!# issue 454
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xf2,0x6e == repne outsb dx, byte ptr [esi]
+
+!# issue 454
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xf2,0x6f == repne outsd dx, dword ptr [esi]
+
+!# issue 454
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xf2,0xac == repne lodsb al, byte ptr [esi]
+
+!# issue 454
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xf2,0xad == repne lodsd eax, dword ptr [esi]
+
+!# issue 450
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0xff,0x2d,0x34,0x35,0x23,0x01 == jmp ptr [0x1233534] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xff 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x2d ; disp: 0x1233534 ; sib: 0x0 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.disp: 0x1233534 ; operands[0].size: 6 ; Groups: jump
+
+!# issue 448
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0xea,0x12,0x34,0x56,0x78,0x9a,0xbc == ljmp 0xbc9a:0x78563412 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xea 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 2 ; imms[1]: 0xbc9a ; imms[2]: 0x78563412 ; op_count: 2 ; operands[0].type: IMM = 0xbc9a ; operands[0].size: 2 ; operands[1].type: IMM = 0x78563412 ; operands[1].size: 4 ; Groups: not64bitmode jump
+
+!# issue 426
+!# CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, None
+0x0: 0xbb,0x70,0x00,0x00 == popc %g0, %i5
+
+!# issue 358
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0xe8,0xe3,0xf6,0xff,0xff == call 0xfffff6e8 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xe8 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0xfffff6e8 ; op_count: 1 ; operands[0].type: IMM = 0xfffff6e8 ; operands[0].size: 4 ; Registers read: esp eip ; Registers modified: esp ; Groups: call branch_relative not64bitmode
+
+!# issue 353
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0xe6,0xa2 == out 0xa2, al ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xe6 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0xa2 ; op_count: 2 ; operands[0].type: IMM = 0xa2 ; operands[0].size: 1 ; operands[1].type: REG = al ; operands[1].size: 1 ; operands[1].access: READ ; Registers read: al
+
+!# issue 305
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x34,0x8b == xor al, 0x8b
+
+!# issue 298
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xf3,0x90 == pause
+
+!# issue 298
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0x66,0xf3,0xf2,0x0f,0x59,0xff == mulsd xmm7, xmm7
+
+// !# issue 298
+// !# CS_ARCH_X86, CS_MODE_32, None
+// 0x0: 0xf2,0x66,0x0f,0x59,0xff == mulpd xmm7, xmm7
+
+!# issue 294
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0xc1,0xe6,0x08 == shl esi, 8 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xc1 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0xe6 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0x8 ; op_count: 2 ; operands[0].type: REG = esi ; operands[0].size: 4 ; operands[0].access: READ | WRITE ; operands[1].type: IMM = 0x8 ; operands[1].size: 1 ; Registers read: esi ; Registers modified: eflags esi ; EFLAGS: MOD_CF MOD_SF MOD_ZF MOD_PF MOD_OF UNDEF_AF
+
+!# issue 285
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0x3c,0x12,0x80 == cmp al, 0x12 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x3c 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0x12 ; op_count: 2 ; operands[0].type: REG = al ; operands[0].size: 1 ; operands[0].access: READ ; operands[1].type: IMM = 0x12 ; operands[1].size: 1 ; Registers read: al ; Registers modified: eflags ; EFLAGS: MOD_AF MOD_CF MOD_SF MOD_ZF MOD_PF MOD_OF
+
+!# issue 265
+!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL
+0x0: 0x52,0xf8,0x23,0x30 == ldr.w r3, [r2, r3, lsl #2] ; op_count: 2 ; operands[0].type: REG = r3 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = r2 ; operands[1].mem.index: REG = r3 ; operands[1].access: READ ; Shift: 2 = 2 ; Registers read: r2 r3 ; Registers modified: r3 ; Groups: thumb2
+
+!# issue 264
+!# CS_ARCH_ARM, CS_MODE_THUMB, None
+0x0: 0x0c,0xbf == ite eq
+
+!# issue 264
+!# CS_ARCH_ARM, CS_MODE_THUMB, None
+0x0: 0x17,0x20 == movs r0, #0x17
+
+!# issue 264
+!# CS_ARCH_ARM, CS_MODE_THUMB, None
+0x0: 0x4f,0xf0,0xff,0x30 == mov.w r0, #-1
+
+!# issue 246
+!# CS_ARCH_ARM, CS_MODE_THUMB, None
+0x0: 0x52,0xf8,0x23,0xf0 == ldr.w pc, [r2, r3, lsl #2]
+
+!# issue 232
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0x8e,0x10 == mov ss, word ptr [eax] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x8e 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x10 ; disp: 0x0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: REG = ss ; operands[0].size: 2 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = eax ; operands[1].size: 2 ; operands[1].access: READ ; Registers read: eax ; Registers modified: ss ; Groups: privilege
+
+!# issue 231
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0x66,0x6b,0xc0,0x02 == imul ax, ax, 2 ; Prefix:0x00 0x00 0x66 0x00 ; Opcode:0x6b 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0xc0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0x2 ; op_count: 3 ; operands[0].type: REG = ax ; operands[0].size: 2 ; operands[0].access: WRITE ; operands[1].type: REG = ax ; operands[1].size: 2 ; operands[1].access: READ ; operands[2].type: IMM = 0x2 ; operands[2].size: 2 ; Registers read: ax ; Registers modified: eflags ax ; EFLAGS: MOD_CF MOD_SF MOD_OF UNDEF_ZF UNDEF_PF UNDEF_AF
+
+!# issue 230
+!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL
+0x0: 0xec == in al, dx ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xec 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: REG = al ; operands[0].size: 1 ; operands[0].access: WRITE ; operands[1].type: REG = dx ; operands[1].size: 2 ; operands[1].access: READ ; Registers read: dx ; Registers modified: al
+
+!# issue 213
+!# CS_ARCH_X86, CS_MODE_16, None
+0x0: 0xea,0xaa,0xff,0x00,0xf0 == ljmp 0xf000:0xffaa
+
+!# issue 191
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0xc5,0xe8,0xc2,0x33,0x9b == vcmpps xmm6, xmm2, xmmword ptr [rbx], 0x9b
+
+!# issue 176
+!# CS_ARCH_ARM, CS_MODE_ARM, None
+0x0: 0xfd,0xff,0xff,0x1a == bne #0xfffffffc
+
+!# issue 151
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0x4d,0x8d,0x3d,0x02,0x00,0x00,0x00 == lea r15, [rip + 2]
+
+!# issue 151
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0xeb,0xb0 == jmp 0xffffffffffffffb2
+
+!# issue 134
+!# CS_ARCH_ARM, CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x0: 0xe7,0x92,0x11,0x80 == ldr r1, [r2, r0, lsl #3] ; op_count: 2 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = r2 ; operands[1].mem.index: REG = r0 ; operands[1].access: READ ; Shift: 2 = 3 ; Registers read: r2 r0 ; Registers modified: r1 ; Groups: arm
+
+!# issue 133
+!# CS_ARCH_ARM, CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x0: 0xed,0xdf,0x2b,0x1b == vldr d18, [pc, #0x6c] ; op_count: 2 ; operands[0].type: REG = d18 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = pc ; operands[1].mem.disp: 0x6c ; operands[1].access: READ ; Registers read: pc ; Registers modified: d18 ; Groups: vfp2
+
+!# issue 132
+!# CS_ARCH_ARM, CS_MODE_THUMB | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x0: 0x49,0x19 == ldr r1, [pc, #0x64] ; op_count: 2 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = pc ; operands[1].mem.disp: 0x64 ; operands[1].access: READ ; Registers read: pc ; Registers modified: r1 ; Groups: thumb thumb1only
+
+!# issue 130
+!# CS_ARCH_ARM, CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL
+0x0: 0xe1,0xa0,0xf0,0x0e == mov pc, lr ; op_count: 2 ; operands[0].type: REG = pc ; operands[0].access: WRITE ; operands[1].type: REG = lr ; operands[1].access: READ ; Registers read: lr ; Registers modified: pc ; Groups: arm
+
+!# issue 85
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None
+0x0: 0xee,0x3f,0xbf,0x29 == stp w14, w15, [sp, #-8]!
+
+!# issue 82
+!# CS_ARCH_X86, CS_MODE_64, None
+0x0: 0xf2,0x66,0xaf == repne scasw ax, word ptr [rdi]
+
+!# issue 35
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xe8,0xc6,0x02,0x00,0x00 == call 0x2cb
+
+!# issue 8
+!# CS_ARCH_X86, CS_MODE_32, None
+0x0: 0xff,0x8c,0xf9,0xff,0xff,0x9b,0xf9 == dec dword ptr [ecx + edi*8 - 0x6640001]
+
+!# issue 29
+!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None
+0x0: 0x00,0x00,0x00,0x4c == st4 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0]
+
diff --git a/capstone/suite/cstest/src/arm64_detail.c b/capstone/suite/cstest/src/arm64_detail.c
new file mode 100644
index 000000000..e45ba4f6b
--- /dev/null
+++ b/capstone/suite/cstest/src/arm64_detail.c
@@ -0,0 +1,138 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+char *get_detail_arm64(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_arm64 *arm64;
+ int i;
+ cs_regs regs_read, regs_write;
+ uint8_t regs_read_count, regs_write_count;
+ uint8_t access;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ // detail can be NULL if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return result;
+
+ arm64 = &(ins->detail->arm64);
+ if (arm64->op_count)
+ add_str(&result, " ; op_count: %u", arm64->op_count);
+
+ for (i = 0; i < arm64->op_count; i++) {
+ cs_arm64_op *op = &(arm64->operands[i]);
+ switch(op->type) {
+ default:
+ break;
+ case ARM64_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case ARM64_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64, i, op->imm);
+ break;
+ case ARM64_OP_FP:
+#if defined(_KERNEL_MODE)
+ // Issue #681: Windows kernel does not support formatting float point
+ add_str(&result, " ; operands[%u].type: FP = <float_point_unsupported>", i);
+#else
+ add_str(&result, " ; operands[%u].type: FP = %f", i, op->fp);
+#endif
+ break;
+ case ARM64_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base != ARM64_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base));
+ if (op->mem.index != ARM64_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index));
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp);
+
+ break;
+ case ARM64_OP_CIMM:
+ add_str(&result, " ; operands[%u].type: C-IMM = %u", i, (int)op->imm);
+ break;
+ case ARM64_OP_REG_MRS:
+ add_str(&result, " ; operands[%u].type: REG_MRS = 0x%x", i, op->reg);
+ break;
+ case ARM64_OP_REG_MSR:
+ add_str(&result, " ; operands[%u].type: REG_MSR = 0x%x", i, op->reg);
+ break;
+ case ARM64_OP_PSTATE:
+ add_str(&result, " ; operands[%u].type: PSTATE = 0x%x", i, op->pstate);
+ break;
+ case ARM64_OP_SYS:
+ add_str(&result, " ; operands[%u].type: SYS = 0x%x", i, op->sys);
+ break;
+ case ARM64_OP_PREFETCH:
+ add_str(&result, " ; operands[%u].type: PREFETCH = 0x%x", i, op->prefetch);
+ break;
+ case ARM64_OP_BARRIER:
+ add_str(&result, " ; operands[%u].type: BARRIER = 0x%x", i, op->barrier);
+ break;
+ }
+
+ access = op->access;
+ switch(access) {
+ default:
+ break;
+ case CS_AC_READ:
+ add_str(&result, " ; operands[%u].access: READ", i);
+ break;
+ case CS_AC_WRITE:
+ add_str(&result, " ; operands[%u].access: WRITE", i);
+ break;
+ case CS_AC_READ | CS_AC_WRITE:
+ add_str(&result, " ; operands[%u].access: READ | WRITE", i);
+ break;
+ }
+
+ if (op->shift.type != ARM64_SFT_INVALID &&
+ op->shift.value)
+ add_str(&result, " ; Shift: type = %u, value = %u",
+ op->shift.type, op->shift.value);
+
+ if (op->ext != ARM64_EXT_INVALID)
+ add_str(&result, " ; Ext: %u", op->ext);
+
+ if (op->vas != ARM64_VAS_INVALID)
+ add_str(&result, " ; Vector Arrangement Specifier: 0x%x", op->vas);
+
+ if (op->vector_index != -1)
+ add_str(&result, " ; Vector Index: %u", op->vector_index);
+ }
+
+ if (arm64->update_flags)
+ add_str(&result, " ; Update-flags: True");
+
+ if (arm64->writeback)
+ add_str(&result, " ; Write-back: True");
+
+ if (arm64->cc)
+ add_str(&result, " ; Code-condition: %u", arm64->cc);
+
+ // Print out all registers accessed by this instruction (either implicit or explicit)
+ if (!cs_regs_access(*handle, ins,
+ regs_read, &regs_read_count,
+ regs_write, &regs_write_count)) {
+ if (regs_read_count) {
+ add_str(&result, " ; Registers read:");
+ for(i = 0; i < regs_read_count; i++) {
+ add_str(&result, " %s", cs_reg_name(*handle, regs_read[i]));
+ }
+ }
+
+ if (regs_write_count) {
+ add_str(&result, " ; Registers modified:");
+ for(i = 0; i < regs_write_count; i++) {
+ add_str(&result, " %s", cs_reg_name(*handle, regs_write[i]));
+ }
+ }
+ }
+
+ return result;
+}
diff --git a/capstone/suite/cstest/src/arm_detail.c b/capstone/suite/cstest/src/arm_detail.c
new file mode 100644
index 000000000..f1d6402a9
--- /dev/null
+++ b/capstone/suite/cstest/src/arm_detail.c
@@ -0,0 +1,150 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+char *get_detail_arm(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_arm *arm;
+ int i;
+ cs_regs regs_read, regs_write;
+ uint8_t regs_read_count, regs_write_count;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ arm = &(ins->detail->arm);
+
+ if (arm->op_count)
+ add_str(&result, " ; op_count: %u", arm->op_count);
+
+ for (i = 0; i < arm->op_count; i++) {
+ cs_arm_op *op = &(arm->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case ARM_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case ARM_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm);
+ break;
+ case ARM_OP_FP:
+#if defined(_KERNEL_MODE)
+ // Issue #681: Windows kernel does not support formatting float point
+ add_str(&result, " ; operands[%u].type: FP = <float_point_unsupported>", i);
+#else
+ add_str(&result, " ; operands[%u].type: FP = %f", i, op->fp);
+#endif
+ break;
+ case ARM_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base != ARM_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base));
+ if (op->mem.index != ARM_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index));
+ if (op->mem.scale != 1)
+ add_str(&result, " ; operands[%u].mem.scale: %d", i, op->mem.scale);
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp);
+ if (op->mem.lshift != 0)
+ add_str(&result, " ; operands[%u].mem.lshift: 0x%x", i, op->mem.lshift);
+
+ break;
+ case ARM_OP_PIMM:
+ add_str(&result, " ; operands[%u].type: P-IMM = %u", i, op->imm);
+ break;
+ case ARM_OP_CIMM:
+ add_str(&result, " ; operands[%u].type: C-IMM = %u", i, op->imm);
+ break;
+ case ARM_OP_SETEND:
+ add_str(&result, " ; operands[%u].type: SETEND = %s", i, op->setend == ARM_SETEND_BE? "be" : "le");
+ break;
+ case ARM_OP_SYSREG:
+ add_str(&result, " ; operands[%u].type: SYSREG = %u", i, op->reg);
+ break;
+ }
+
+ if (op->neon_lane != -1) {
+ add_str(&result, " ; operands[%u].neon_lane = %u", i, op->neon_lane);
+ }
+
+ switch(op->access) {
+ default:
+ break;
+ case CS_AC_READ:
+ add_str(&result, " ; operands[%u].access: READ", i);
+ break;
+ case CS_AC_WRITE:
+ add_str(&result, " ; operands[%u].access: WRITE", i);
+ break;
+ case CS_AC_READ | CS_AC_WRITE:
+ add_str(&result, " ; operands[%u].access: READ | WRITE", i);
+ break;
+ }
+
+ if (op->shift.type != ARM_SFT_INVALID && op->shift.value) {
+ if (op->shift.type < ARM_SFT_ASR_REG)
+ add_str(&result, " ; Shift: %u = %u", op->shift.type, op->shift.value);
+ else
+ add_str(&result, " ; Shift: %u = %s", op->shift.type, cs_reg_name(*handle, op->shift.value));
+ }
+
+ if (op->vector_index != -1) {
+ add_str(&result, " ; operands[%u].vector_index = %u", i, op->vector_index);
+ }
+
+ if (op->subtracted)
+ add_str(&result, " ; Subtracted: True");
+ }
+
+ if (arm->cc != ARM_CC_AL && arm->cc != ARM_CC_INVALID)
+ add_str(&result, " ; Code condition: %u", arm->cc);
+
+ if (arm->update_flags)
+ add_str(&result, " ; Update-flags: True");
+
+ if (arm->writeback)
+ add_str(&result, " ; Write-back: True");
+
+ if (arm->cps_mode)
+ add_str(&result, " ; CPSI-mode: %u", arm->cps_mode);
+
+ if (arm->cps_flag)
+ add_str(&result, " ; CPSI-flag: %u", arm->cps_flag);
+
+ if (arm->vector_data)
+ add_str(&result, " ; Vector-data: %u", arm->vector_data);
+
+ if (arm->vector_size)
+ add_str(&result, " ; Vector-size: %u", arm->vector_size);
+
+ if (arm->usermode)
+ add_str(&result, " ; User-mode: True");
+
+ if (arm->mem_barrier)
+ add_str(&result, " ; Memory-barrier: %u", arm->mem_barrier);
+
+ if (!cs_regs_access(*handle, ins, regs_read, &regs_read_count, regs_write, &regs_write_count)) {
+ if (regs_read_count) {
+ add_str(&result, " ; Registers read:");
+ for(i = 0; i < regs_read_count; i++) {
+ add_str(&result, " %s", cs_reg_name(*handle, regs_read[i]));
+ }
+ }
+
+ if (regs_write_count) {
+ add_str(&result, " ; Registers modified:");
+ for(i = 0; i < regs_write_count; i++) {
+ add_str(&result, " %s", cs_reg_name(*handle, regs_write[i]));
+ }
+ }
+ }
+
+ return result;
+}
diff --git a/capstone/suite/cstest/src/bpf_detail.c b/capstone/suite/cstest/src/bpf_detail.c
new file mode 100644
index 000000000..d72332f79
--- /dev/null
+++ b/capstone/suite/cstest/src/bpf_detail.c
@@ -0,0 +1,77 @@
+/* Capstone testing regression */
+/* By david942j <david942j@gmail.com>, 2019 */
+
+#include <capstone/platform.h>
+
+#include "factory.h"
+
+static char * ext_name[] = {
+ [BPF_EXT_LEN] = "#len",
+};
+
+char *get_detail_bpf(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_bpf *bpf;
+ unsigned int i;
+ cs_regs regs_read, regs_write;
+ uint8_t regs_read_count, regs_write_count;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+ if (ins->detail == NULL)
+ return result;
+
+ bpf = &(ins->detail->bpf);
+
+ if (bpf->op_count)
+ add_str(&result, " ; op_count: %u", bpf->op_count);
+ for (i = 0; i < bpf->op_count; i++) {
+ cs_bpf_op *op = &(bpf->operands[i]);
+ add_str(&result, " ; operands[%u].type: ", i);
+ switch (op->type) {
+ case BPF_OP_INVALID:
+ add_str(&result, "INVALID");
+ break;
+ case BPF_OP_REG:
+ add_str(&result, "REG = %s", cs_reg_name(*handle, op->reg));
+ break;
+ case BPF_OP_IMM:
+ add_str(&result, "IMM = 0x%" PRIx64, op->imm);
+ break;
+ case BPF_OP_OFF:
+ add_str(&result, "OFF = +0x%x", op->off);
+ break;
+ case BPF_OP_MEM:
+ add_str(&result, "MEM [base=%s, disp=0x%x]",
+ cs_reg_name(*handle, op->mem.base), op->mem.disp);
+ break;
+ case BPF_OP_MMEM:
+ add_str(&result, "MMEM = M[0x%x]", op->mmem);
+ break;
+ case BPF_OP_MSH:
+ add_str(&result, "MSH = 4*([0x%x]&0xf)", op->msh);
+ break;
+ case BPF_OP_EXT:
+ add_str(&result, "EXT = %s", ext_name[op->ext]);
+ break;
+ }
+ }
+
+ if (!cs_regs_access(*handle, ins,
+ regs_read, &regs_read_count,
+ regs_write, &regs_write_count)) {
+ if (regs_read_count) {
+ add_str(&result, " ; Registers read:");
+ for(i = 0; i < regs_read_count; i++)
+ add_str(&result, " %s", cs_reg_name(*handle, regs_read[i]));
+ }
+
+ if (regs_write_count) {
+ add_str(&result, " ; Registers modified:");
+ for(i = 0; i < regs_write_count; i++)
+ add_str(&result, " %s", cs_reg_name(*handle, regs_write[i]));
+ }
+ }
+ return result;
+}
diff --git a/capstone/suite/cstest/src/capstone_test.c b/capstone/suite/cstest/src/capstone_test.c
new file mode 100644
index 000000000..a534e49b3
--- /dev/null
+++ b/capstone/suite/cstest/src/capstone_test.c
@@ -0,0 +1,281 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "capstone_test.h"
+
+char *(*function)(csh *, cs_mode, cs_insn*) = NULL;
+
+void test_single_MC(csh *handle, int mc_mode, char *line)
+{
+ char **list_part, **list_byte;
+ int size_part, size_byte, size_data, size_insn;
+ int i, count, count_noreg;
+ unsigned char *code;
+ cs_insn *insn;
+ char tmp[MAXMEM], tmp_mc[MAXMEM], origin[MAXMEM], tmp_noreg[MAXMEM];
+ char **offset_opcode;
+ int size_offset_opcode;
+ unsigned long offset;
+ char *p;
+
+ list_part = split(line, " = ", &size_part);
+ offset_opcode = split(list_part[0], ": ", &size_offset_opcode);
+ if (size_offset_opcode > 1) {
+ offset = (unsigned int)strtol(offset_opcode[0], NULL, 16);
+ list_byte = split(offset_opcode[1], ",", &size_byte);
+ } else {
+ offset = 0;
+ list_byte = split(offset_opcode[0], ",", &size_byte);
+ }
+
+ code = (unsigned char *)malloc(size_byte * sizeof(char));
+ for (i = 0; i < size_byte; ++i) {
+ code[i] = (unsigned char)strtol(list_byte[i], NULL, 16);
+ }
+
+ count = cs_disasm(*handle, code, size_byte, offset, 0, &insn);
+ if (count == 0) {
+ fprintf(stderr, "[ ERROR ] --- %s --- Failed to disassemble given code!\n", list_part[0]);
+ free_strs(list_part, size_part);
+ free_strs(offset_opcode, size_offset_opcode);
+ free_strs(list_byte, size_byte);
+ free(code);
+ _fail(__FILE__, __LINE__);
+ }
+ if (count > 1) {
+ fprintf(stderr, "[ ERROR ] --- %s --- Multiple instructions(%d) disassembling doesn't support!\n", list_part[0], count);
+ free_strs(list_part, size_part);
+ free_strs(offset_opcode, size_offset_opcode);
+ free_strs(list_byte, size_byte);
+ free(code);
+ _fail(__FILE__, __LINE__);
+ }
+
+ for (p = list_part[1]; *p; ++p) *p = tolower(*p);
+ for (p = list_part[1]; *p; ++p)
+ if (*p == '\t') *p = ' ';
+ trim_str(list_part[1]);
+ strcpy(tmp_mc, list_part[1]);
+ replace_hex(tmp_mc);
+ replace_negative(tmp_mc, mc_mode);
+
+ strcpy(tmp, insn[0].mnemonic);
+ if (strlen(insn[0].op_str) > 0) {
+ tmp[strlen(insn[0].mnemonic)] = ' ';
+ strcpy(tmp + strlen(insn[0].mnemonic) + 1, insn[0].op_str);
+ }
+
+ trim_str(tmp);
+ strcpy(origin, tmp);
+ replace_hex(tmp);
+ replace_negative(tmp, mc_mode);
+
+ if (cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME) == CS_ERR_OK) {
+ count_noreg = cs_disasm(*handle, code, size_byte, offset, 0, &insn);
+ strcpy(tmp_noreg, insn[0].mnemonic);
+ if (strlen(insn[0].op_str) > 0) {
+ tmp_noreg[strlen(insn[0].mnemonic)] = ' ';
+ strcpy(tmp_noreg + strlen(insn[0].mnemonic) + 1, insn[0].op_str);
+ }
+
+ trim_str(tmp_noreg);
+ replace_hex(tmp_noreg);
+ replace_negative(tmp_noreg, mc_mode);
+
+ if (strcmp(tmp, tmp_mc) && strcmp(tmp_noreg, tmp_mc)) {
+ fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" != \"%s\" ( \"%s\" != \"%s\" and \"%s\" != \"%s\" )\n", list_part[0], origin, list_part[1], tmp, tmp_mc, tmp_noreg, tmp_mc);
+ free_strs(list_part, size_part);
+ free_strs(offset_opcode, size_offset_opcode);
+ free_strs(list_byte, size_byte);
+ free(code);
+ cs_free(insn, count);
+ _fail(__FILE__, __LINE__);
+ }
+
+ cs_option(*handle, CS_OPT_SYNTAX, 0);
+
+ } else if (strcmp(tmp, tmp_mc)) {
+ fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" != \"%s\" ( \"%s\" != \"%s\" )\n", list_part[0], origin, list_part[1], tmp, tmp_mc);
+ free_strs(list_part, size_part);
+ free_strs(offset_opcode, size_offset_opcode);
+ free_strs(list_byte, size_byte);
+ free(code);
+ cs_free(insn, count);
+ _fail(__FILE__, __LINE__);
+ }
+
+ free_strs(list_part, size_part);
+ free_strs(offset_opcode, size_offset_opcode);
+ free_strs(list_byte, size_byte);
+ free(code);
+ cs_free(insn, count);
+}
+
+int get_value(single_dict d[], unsigned int size, const char *str)
+{
+ int i;
+
+ for (i = 0; i < size; ++i)
+ if (!strcmp(d[i].str, str))
+ return d[i].value;
+ return -1;
+}
+
+int get_index(double_dict d[], unsigned int size, const char *s)
+{
+ int i;
+
+ for (i = 0; i < size; ++i) {
+ if (!strcmp(s, d[i].str))
+ return i;
+ }
+ return -1;
+}
+
+int set_function(int arch)
+{
+ switch(arch) {
+ case CS_ARCH_ARM:
+ function = get_detail_arm;
+ break;
+ case CS_ARCH_ARM64:
+ function = get_detail_arm64;
+ break;
+ case CS_ARCH_MIPS:
+ function = get_detail_mips;
+ break;
+ case CS_ARCH_PPC:
+ function = get_detail_ppc;
+ break;
+ case CS_ARCH_SPARC:
+ function = get_detail_sparc;
+ break;
+ case CS_ARCH_SYSZ:
+ function = get_detail_sysz;
+ break;
+ case CS_ARCH_X86:
+ function = get_detail_x86;
+ break;
+ case CS_ARCH_XCORE:
+ function = get_detail_xcore;
+ break;
+ case CS_ARCH_M68K:
+ function = get_detail_m68k;
+ break;
+ case CS_ARCH_M680X:
+ function = get_detail_m680x;
+ break;
+ case CS_ARCH_EVM:
+ function = get_detail_evm;
+ break;
+ case CS_ARCH_MOS65XX:
+ function = get_detail_mos65xx;
+ break;
+ case CS_ARCH_TMS320C64X:
+ function = get_detail_tms320c64x;
+ break;
+ case CS_ARCH_BPF:
+ function = get_detail_bpf;
+ break;
+ case CS_ARCH_RISCV:
+ function = get_detail_riscv;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+void test_single_issue(csh *handle, cs_mode mode, char *line, int detail)
+{
+ char **list_part, **list_byte, **list_part_cs_result, **list_part_issue_result;
+ int size_part, size_byte, size_part_cs_result, size_part_issue_result;
+ char *tmptmp;
+ int i, count, j;
+ unsigned char *code;
+ cs_insn *insn;
+ char *cs_result, *tmp, *p;
+ char **offset_opcode;
+ int size_offset_opcode;
+ unsigned long offset;
+
+ cs_result = (char *)malloc(sizeof(char));
+ cs_result[0] = '\0';
+
+ list_part = split(line, " == ", &size_part);
+
+ offset_opcode = split(list_part[0], ": ", &size_offset_opcode);
+ if (size_offset_opcode > 1) {
+ offset = (unsigned int)strtol(offset_opcode[0], NULL, 16);
+ list_byte = split(offset_opcode[1], ",", &size_byte);
+ } else {
+ offset = 0;
+ list_byte = split(offset_opcode[0], ",", &size_byte);
+ }
+
+ code = (unsigned char *)malloc(sizeof(char) * size_byte);
+ for (i = 0; i < size_byte; ++i) {
+ code[i] = (unsigned char)strtol(list_byte[i], NULL, 16);
+ }
+
+ count = cs_disasm(*handle, code, size_byte, offset, 0, &insn);
+ for (i = 0; i < count; ++i) {
+ tmp = (char *)malloc(strlen(insn[i].mnemonic) + strlen(insn[i].op_str) + 100);
+ strcpy(tmp, insn[i].mnemonic);
+ if (strlen(insn[i].op_str) > 0) {
+ tmp[strlen(insn[i].mnemonic)] = ' ';
+ strcpy(tmp + strlen(insn[i].mnemonic) + 1, insn[i].op_str);
+ }
+ add_str(&cs_result, "%s", tmp);
+ free(tmp);
+ }
+
+ if (detail == 1) {
+ tmp = (*function)(handle, mode, insn);
+ add_str(&cs_result, "%s", tmp);
+ free(tmp);
+
+ if (insn->detail->groups_count) {
+ add_str(&cs_result, " ; Groups: ");
+ for (j = 0; j < insn->detail->groups_count; j++) {
+ add_str(&cs_result, "%s ", cs_group_name(*handle, insn->detail->groups[j]));
+ }
+ }
+ }
+
+ trim_str(cs_result);
+ add_str(&cs_result, " ;");
+ // list_part_cs_result = split(cs_result, " ; ", &size_part_cs_result);
+ for (p = list_part[1]; *p; ++p) if (*p == '\t') *p = ' ';
+ list_part_issue_result = split(list_part[1], " ; ", &size_part_issue_result);
+
+ for (i = 0; i < size_part_issue_result; ++i) {
+ trim_str(list_part_issue_result[i]);
+ memset(tmptmp, MAXMEM, 0);
+
+ tmptmp = (char *)malloc(sizeof(char));
+ tmptmp[0] = '\0';
+ add_str(&tmptmp, "%s", list_part_issue_result[i]);
+ add_str(&tmptmp, " ;");
+
+ if ((strstr(cs_result, tmptmp)) == NULL) {
+ fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" not in \"%s\"\n", list_part[0], list_part_issue_result[i], cs_result);
+ cs_free(insn, count);
+ free_strs(list_part, size_part);
+ free_strs(list_byte, size_byte);
+ free(cs_result);
+ // free_strs(list_part_cs_result, size_part_cs_result);
+ free_strs(list_part_issue_result, size_part_issue_result);
+ free(tmptmp);
+ _fail(__FILE__, __LINE__);
+ }
+ }
+
+ cs_free(insn, count);
+ free_strs(list_part, size_part);
+ free_strs(list_byte, size_byte);
+ free(cs_result);
+ // free_strs(list_part_cs_result, size_part_cs_result);
+ free_strs(list_part_issue_result, size_part_issue_result);
+}
diff --git a/capstone/suite/cstest/src/evm_detail.c b/capstone/suite/cstest/src/evm_detail.c
new file mode 100644
index 000000000..635d309e3
--- /dev/null
+++ b/capstone/suite/cstest/src/evm_detail.c
@@ -0,0 +1,30 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+char *get_detail_evm(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_evm *evm;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ evm = &(ins->detail->evm);
+
+ if (evm->pop)
+ add_str(&result, " ; Pop: %u", evm->pop);
+
+ if (evm->push)
+ add_str(&result, " ; Push: %u", evm->push);
+
+ if (evm->fee)
+ add_str(&result, " ; Gas fee: %u", evm->fee);
+
+ return result;
+}
diff --git a/capstone/suite/cstest/src/helper.c b/capstone/suite/cstest/src/helper.c
new file mode 100644
index 000000000..02365510c
--- /dev/null
+++ b/capstone/suite/cstest/src/helper.c
@@ -0,0 +1,267 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "helper.h"
+
+char **split(char *str, char *delim, int *size)
+{
+ char **result;
+ char *token, *src;
+ int cnt;
+
+ cnt = 0;
+ src = str;
+ result = NULL;
+
+ while ((token = strstr(src, delim)) != NULL) {
+ result = (char **)realloc(result, sizeof(char *) * (cnt + 1));
+ result[cnt] = (char *)calloc(1, sizeof(char) * (int)(token - src + 10));
+ memcpy(result[cnt], src, token - src);
+ result[cnt][token - src] = '\0';
+ src = token + strlen(delim);
+ cnt ++;
+ }
+
+ if (strlen(src) > 0) {
+ result = (char **)realloc(result, sizeof(char *) * (cnt + 1));
+ result[cnt] = strdup(src);
+ cnt ++;
+ }
+
+ *size = cnt;
+ return result;
+}
+
+void print_strs(char **list_str, int size)
+{
+ int i;
+
+ printf("[+] Debug %d strings:\n", size);
+ for (i = 0; i < size; ++i)
+ printf("String %d'th: %s\n", i+1, list_str[i]);
+}
+
+void free_strs(char **list_str, int size)
+{
+ int i;
+ for (i = 0; i < size; ++i)
+ free(list_str[i]);
+
+ free(list_str);
+}
+
+const char *get_filename_ext(const char *filename)
+{
+ const char *dot;
+
+ dot = strrchr(filename, '.');
+ if (!dot || dot == filename)
+ return "";
+
+ return dot + 1;
+}
+
+char *readfile(const char *filename)
+{
+ char *result;
+ FILE *fp;
+ int size;
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ puts("No such file");
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ rewind(fp);
+
+ result = (char *)calloc(1, sizeof(char) * size + 1);
+ fread(result, size, 1, fp);
+ result[size] = '\0';
+
+ fclose(fp);
+ return result;
+}
+
+void add_str(char **src, const char *format, ...)
+{
+ char *tmp;
+ size_t len1, len2;
+ va_list args;
+
+ tmp = (char *)malloc(sizeof(char) * 1000);
+ va_start(args, format);
+ vsprintf(tmp, format, args);
+ va_end(args);
+
+ len1 = strlen(*src);
+ len2 = strlen(tmp);
+
+ *src = (char *)realloc(*src, sizeof(char) * (len1 + len2 + 10));
+ memcpy(*src + len1, tmp, len2 + 1);
+ free(tmp);
+}
+
+void replace_hex(char *src)
+{
+ char *tmp, *result, *found, *origin, *orig_found;
+ int i, valid;
+ unsigned long long int value;
+ char *tmp_tmp;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+ tmp = strdup(src);
+ origin = tmp;
+
+ while ((found = strstr(tmp, "0x")) != NULL) {
+ orig_found = found;
+ found += 2;
+ value = 0;
+ valid = 0;
+
+ tmp_tmp = strndup(tmp, orig_found - tmp);
+ while (*found != '\0' && isxdigit(*found)) {
+ valid = 1;
+ if (*found >= 'a' && *found <='f')
+ value = value*0x10 + (*found - 'a' + 10);
+ else
+ value = value*0x10 + (*found - '0');
+ found++;
+ }
+
+ if (valid == 1) add_str(&result, "%s%llu", tmp_tmp, value);
+ else add_str(&result, "%s0x", tmp_tmp);
+ tmp = found;
+ free(tmp_tmp);
+ }
+
+ add_str(&result, "%s", tmp);
+ if (strlen(result) >= MAXMEM) {
+ fprintf(stderr, "[ Error ] --- Buffer Overflow in replace_hex()\n");
+ free(result);
+ free(origin);
+ _fail(__FILE__, __LINE__);
+ }
+
+ strcpy(src, result);
+ free(result);
+ free(origin);
+}
+
+void replace_negative(char *src, int mode)
+{
+ char *tmp, *result, *found, *origin, *orig_found;
+ int i, cnt, valid;
+ char *value, *tmp_tmp;
+ unsigned short int tmp_short;
+ unsigned int tmp_int;
+ unsigned long int tmp_long;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+ tmp = strdup(src);
+ origin = tmp;
+
+ while ((found = strstr(tmp, "-")) != NULL) {
+ orig_found = found;
+ found ++;
+ valid = 0;
+
+ value = strdup("-");
+ cnt = 2;
+
+ while (*found != '\0' && isdigit(*found)) {
+ valid = 1;
+ value = (char *)realloc(value, cnt + 1);
+ value[cnt - 1] = *found;
+ value[cnt] = '\0';
+ cnt ++;
+ found++;
+ }
+
+ tmp_tmp = strndup(tmp, orig_found - tmp);
+ if (valid == 1) {
+ *orig_found = '\0';
+ if (mode == X86_16) {
+ sscanf(value, "%hu", &tmp_short);
+ add_str(&result, "%s%hu", tmp_tmp, tmp_short);
+ } else if (mode == X86_32) {
+ sscanf(value, "%u", &tmp_int);
+ add_str(&result, "%s%u", tmp_tmp, tmp_int);
+ } else if (mode == X86_64) {
+ sscanf(value, "%lu", &tmp_long);
+ add_str(&result, "%s%lu", tmp_tmp, tmp_long);
+ }
+ }
+ else add_str(&result, "%s-", tmp_tmp);
+
+ tmp = found;
+ free(value);
+ free(tmp_tmp);
+ }
+
+ add_str(&result, "%s", tmp);
+ if (strlen(result) >= MAXMEM) {
+ fprintf(stderr, "[ Error ] --- Buffer Overflow in replace_negative()\n");
+ free(result);
+ free(origin);
+ _fail(__FILE__, __LINE__);
+ }
+
+ strcpy(src, result);
+ free(result);
+ free(origin);
+}
+
+void listdir(const char *name, char ***files, int *num_files)
+{
+ DIR *dir;
+ struct dirent *entry;
+ int cnt;
+
+ if (!(dir = opendir(name)))
+ return;
+
+ while ((entry = readdir(dir)) != NULL) {
+ if (entry->d_type == DT_DIR) {
+ char path[1024];
+ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+ continue;
+ snprintf(path, sizeof(path), "%s/%s", name, entry->d_name);
+ listdir(path, files, num_files);
+ } else {
+ cnt = *num_files;
+ *files = (char **)realloc(*files, sizeof(char *) * (cnt + 1));
+ (*files)[cnt] = (char *)malloc(sizeof(char) * ( strlen(name) + 1 + strlen(entry->d_name) + 10));
+ sprintf((*files)[cnt], "%s/%s", name, entry->d_name);
+ cnt ++;
+ *num_files = cnt;
+ }
+ }
+
+ closedir(dir);
+}
+
+void trim_str(char *str)
+{
+ char tmp[MAXMEM];
+ int start, end, j, i;
+
+ start = 0;
+ end = strlen(str) - 1;
+ j = 0;
+ while (start < strlen(str) && isspace(str[start])) start++;
+ while (end >= 0 && isspace(str[end])) end--;
+
+ for (i = start; i <= end; ++i)
+ tmp[j++] = str[i];
+
+ tmp[j] = '\0';
+ strcpy(str, tmp);
+
+ return;
+}
diff --git a/capstone/suite/cstest/src/m680x_detail.c b/capstone/suite/cstest/src/m680x_detail.c
new file mode 100644
index 000000000..62c429812
--- /dev/null
+++ b/capstone/suite/cstest/src/m680x_detail.c
@@ -0,0 +1,137 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+static const char *s_access[] = {
+ "UNCHANGED", "READ", "WRITE", "READ ; WRITE",
+};
+
+static void print_read_write_regs(char *result, csh *handle, cs_detail *detail)
+{
+ int i;
+
+ if (detail->regs_read_count > 0) {
+ add_str(&result, "\treading from regs: ");
+
+ for (i = 0; i < detail->regs_read_count; ++i) {
+ if (i > 0)
+ add_str(&result, ", ");
+
+ add_str(&result, "%s", cs_reg_name(*handle, detail->regs_read[i]));
+ }
+ }
+
+ if (detail->regs_write_count > 0) {
+ add_str(&result, "\twriting to regs: ");
+
+ for (i = 0; i < detail->regs_write_count; ++i) {
+ if (i > 0)
+ add_str(&result, ", ");
+
+ add_str(&result, "%s", cs_reg_name(*handle, detail->regs_write[i]));
+ }
+ }
+}
+
+char *get_detail_m680x(csh *handle, cs_mode mode, cs_insn *insn)
+{
+ cs_detail *detail = insn->detail;
+ cs_m680x *m680x = NULL;
+ int i;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (detail == NULL)
+ return result;
+
+ m680x = &detail->m680x;
+
+ if (m680x->op_count)
+ add_str(&result, " ; op_count: %u", m680x->op_count);
+
+ for (i = 0; i < m680x->op_count; i++) {
+ cs_m680x_op *op = &(m680x->operands[i]);
+ const char *comment;
+
+ switch ((int)op->type) {
+ default:
+ break;
+
+ case M680X_OP_REGISTER:
+ comment = "";
+
+ if ((i == 0 && m680x->flags & M680X_FIRST_OP_IN_MNEM) ||
+ (i == 1 && m680x->flags &
+ M680X_SECOND_OP_IN_MNEM))
+ comment = " (in mnemonic)";
+
+ add_str(&result, " ; operands[%u].type: REGISTER = %s%s", i, cs_reg_name(*handle, op->reg), comment);
+ break;
+
+ case M680X_OP_CONSTANT:
+ add_str(&result, " ; operands[%u].type: CONSTANT = %u", i, op->const_val);
+ break;
+
+ case M680X_OP_IMMEDIATE:
+ add_str(&result, " ; operands[%u].type: IMMEDIATE = #%d", i, op->imm);
+ break;
+
+ case M680X_OP_DIRECT:
+ add_str(&result, " ; operands[%u].type: DIRECT = 0x%02x", i, op->direct_addr);
+ break;
+
+ case M680X_OP_EXTENDED:
+ add_str(&result, " ; operands[%u].type: EXTENDED %s = 0x%04x", i, op->ext.indirect ? "INDIRECT" : "", op->ext.address);
+ break;
+
+ case M680X_OP_RELATIVE:
+ add_str(&result, " ; operands[%u].type: RELATIVE = 0x%04x", i, op->rel.address);
+ break;
+
+ case M680X_OP_INDEXED:
+ add_str(&result, " ; operands[%u].type: INDEXED%s", i, (op->idx.flags & M680X_IDX_INDIRECT) ? " INDIRECT" : "");
+
+ if (op->idx.base_reg != M680X_REG_INVALID)
+ add_str(&result, " ; base register: %s", cs_reg_name(*handle, op->idx.base_reg));
+
+ if (op->idx.offset_reg != M680X_REG_INVALID)
+ add_str(&result, " ; offset register: %s", cs_reg_name(*handle, op->idx.offset_reg));
+
+ if ((op->idx.offset_bits != 0) &&
+ (op->idx.offset_reg == M680X_REG_INVALID) &&
+ !op->idx.inc_dec) {
+ add_str(&result, " ; offset: %d", op->idx.offset);
+
+ if (op->idx.base_reg == M680X_REG_PC)
+ add_str(&result, " ; offset address: 0x%x", op->idx.offset_addr);
+
+ add_str(&result, " ; offset bits: %u", op->idx.offset_bits);
+ }
+
+ if (op->idx.inc_dec) {
+ const char *post_pre = op->idx.flags &
+ M680X_IDX_POST_INC_DEC ? "post" : "pre";
+ const char *inc_dec = (op->idx.inc_dec > 0) ?
+ "increment" : "decrement";
+
+ add_str(&result, " ; %s %s: %d", post_pre, inc_dec, abs(op->idx.inc_dec));
+ }
+
+ break;
+ }
+
+ if (op->size != 0)
+ add_str(&result, " ; size: %u", op->size);
+
+ if (op->access != CS_AC_INVALID)
+ add_str(&result, " ; access: %s", s_access[op->access]);
+ }
+
+ print_read_write_regs(result, handle, detail);
+
+ return result;
+}
diff --git a/capstone/suite/cstest/src/m68k_detail.c b/capstone/suite/cstest/src/m68k_detail.c
new file mode 100644
index 000000000..a3dfc7491
--- /dev/null
+++ b/capstone/suite/cstest/src/m68k_detail.c
@@ -0,0 +1,116 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+static const char* s_addressing_modes[] = {
+ "<invalid mode>",
+
+ "Register Direct - Data",
+ "Register Direct - Address",
+
+ "Register Indirect - Address",
+ "Register Indirect - Address with Postincrement",
+ "Register Indirect - Address with Predecrement",
+ "Register Indirect - Address with Displacement",
+
+ "Address Register Indirect With Index - 8-bit displacement",
+ "Address Register Indirect With Index - Base displacement",
+
+ "Memory indirect - Postindex",
+ "Memory indirect - Preindex",
+
+ "Program Counter Indirect - with Displacement",
+
+ "Program Counter Indirect with Index - with 8-Bit Displacement",
+ "Program Counter Indirect with Index - with Base Displacement",
+
+ "Program Counter Memory Indirect - Postindexed",
+ "Program Counter Memory Indirect - Preindexed",
+
+ "Absolute Data Addressing - Short",
+ "Absolute Data Addressing - Long",
+ "Immediate value",
+};
+
+static void print_read_write_regs(char *result, cs_detail* detail, csh *handle)
+{
+ int i;
+
+ for (i = 0; i < detail->regs_read_count; ++i) {
+ uint16_t reg_id = detail->regs_read[i];
+ const char* reg_name = cs_reg_name(*handle, reg_id);
+ add_str(&result, " ; reading from reg: %s", reg_name);
+ }
+
+ for (i = 0; i < detail->regs_write_count; ++i) {
+ uint16_t reg_id = detail->regs_write[i];
+ const char* reg_name = cs_reg_name(*handle, reg_id);
+ add_str(&result, " ; writing to reg: %s", reg_name);
+ }
+}
+
+char *get_detail_m68k(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_m68k* m68k;
+ cs_detail* detail;
+ int i;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+
+ detail = ins->detail;
+ m68k = &detail->m68k;
+ if (m68k->op_count)
+ add_str(&result, " ; op_count: %u", m68k->op_count);
+
+ print_read_write_regs(result, detail, handle);
+
+ add_str(&result, " ; groups_count: %u", detail->groups_count);
+
+ for (i = 0; i < m68k->op_count; i++) {
+ cs_m68k_op* op = &(m68k->operands[i]);
+
+ switch((int)op->type) {
+ default:
+ break;
+ case M68K_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case M68K_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, (int)op->imm);
+ break;
+ case M68K_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base_reg != M68K_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base_reg));
+ if (op->mem.index_reg != M68K_REG_INVALID) {
+ add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index_reg));
+ add_str(&result, " ; operands[%u].mem.index: size = %c", i, op->mem.index_size ? 'l' : 'w');
+ }
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp);
+ if (op->mem.scale != 0)
+ add_str(&result, " ; operands[%u].mem.scale: %d", i, op->mem.scale);
+
+ add_str(&result, " ; address mode: %s", s_addressing_modes[op->address_mode]);
+ break;
+ case M68K_OP_FP_SINGLE:
+ add_str(&result, " ; operands[%u].type: FP_SINGLE", i);
+ add_str(&result, " ; operands[%u].simm: %f", i, op->simm);
+ break;
+ case M68K_OP_FP_DOUBLE:
+ add_str(&result, " ; operands[%u].type: FP_DOUBLE", i);
+ add_str(&result, " ; operands[%u].dimm: %lf", i, op->dimm);
+ break;
+ }
+ }
+
+ return result;
+}
diff --git a/capstone/suite/cstest/src/main.c b/capstone/suite/cstest/src/main.c
new file mode 100644
index 000000000..55619e987
--- /dev/null
+++ b/capstone/suite/cstest/src/main.c
@@ -0,0 +1,454 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "helper.h"
+#include "capstone_test.h"
+#include <unistd.h>
+
+#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
+
+static single_dict arches[] = {
+ {"CS_ARCH_ARM", CS_ARCH_ARM},
+ {"CS_ARCH_ARM64", CS_ARCH_ARM64},
+ {"CS_ARCH_MIPS", CS_ARCH_MIPS},
+ {"CS_ARCH_PPC", CS_ARCH_PPC},
+ {"CS_ARCH_SPARC", CS_ARCH_SPARC},
+ {"CS_ARCH_SYSZ", CS_ARCH_SYSZ},
+ {"CS_ARCH_X86", CS_ARCH_X86},
+ {"CS_ARCH_XCORE", CS_ARCH_XCORE},
+ {"CS_ARCH_M68K", CS_ARCH_M68K},
+ {"CS_ARCH_BPF", CS_ARCH_BPF},
+ {"CS_ARCH_RISCV", CS_ARCH_RISCV},
+};
+
+ static single_dict modes[] = {
+ {"CS_MODE_LITTLE_ENDIAN", CS_MODE_LITTLE_ENDIAN},
+ {"CS_MODE_ARM", CS_MODE_ARM},
+ {"CS_MODE_16", CS_MODE_16},
+ {"CS_MODE_32", CS_MODE_32},
+ {"CS_MODE_64", CS_MODE_64},
+ {"CS_MODE_THUMB", CS_MODE_THUMB},
+ {"CS_MODE_MCLASS", CS_MODE_MCLASS},
+ {"CS_MODE_V8", CS_MODE_V8},
+ {"CS_MODE_MICRO", CS_MODE_MICRO},
+ {"CS_MODE_MIPS3", CS_MODE_MIPS3},
+ {"CS_MODE_MIPS32R6", CS_MODE_MIPS32R6},
+ {"CS_MODE_MIPS2", CS_MODE_MIPS2},
+ {"CS_MODE_V9", CS_MODE_V9},
+ {"CS_MODE_QPX", CS_MODE_QPX},
+ {"CS_MODE_M68K_000", CS_MODE_M68K_000},
+ {"CS_MODE_M68K_010", CS_MODE_M68K_010},
+ {"CS_MODE_M68K_020", CS_MODE_M68K_020},
+ {"CS_MODE_M68K_030", CS_MODE_M68K_030},
+ {"CS_MODE_M68K_040", CS_MODE_M68K_040},
+ {"CS_MODE_M68K_060", CS_MODE_M68K_060},
+ {"CS_MODE_BIG_ENDIAN", CS_MODE_BIG_ENDIAN},
+ {"CS_MODE_MIPS32", CS_MODE_MIPS32},
+ {"CS_MODE_MIPS64", CS_MODE_MIPS64},
+ {"CS_MODE_M680X_6301", CS_MODE_M680X_6301},
+ {"CS_MODE_M680X_6309", CS_MODE_M680X_6309},
+ {"CS_MODE_M680X_6800", CS_MODE_M680X_6800},
+ {"CS_MODE_M680X_6801", CS_MODE_M680X_6801},
+ {"CS_MODE_M680X_6805", CS_MODE_M680X_6805},
+ {"CS_MODE_M680X_6808", CS_MODE_M680X_6808},
+ {"CS_MODE_M680X_6809", CS_MODE_M680X_6809},
+ {"CS_MODE_M680X_6811", CS_MODE_M680X_6811},
+ {"CS_MODE_M680X_CPU12", CS_MODE_M680X_CPU12},
+ {"CS_MODE_M680X_HCS08", CS_MODE_M680X_HCS08},
+ {"CS_MODE_BPF_CLASSIC", CS_MODE_BPF_CLASSIC},
+ {"CS_MODE_BPF_EXTENDED", CS_MODE_BPF_EXTENDED},
+ {"CS_MODE_RISCV32", CS_MODE_RISCV32},
+ {"CS_MODE_RISCV64", CS_MODE_RISCV64},
+};
+
+ static double_dict options[] = {
+ {"CS_OPT_DETAIL", CS_OPT_DETAIL, CS_OPT_ON},
+ {"CS_OPT_SKIPDATA", CS_OPT_SKIPDATA, CS_OPT_ON},
+ {"CS_OPT_SYNTAX_DEFAULT", CS_OPT_SYNTAX, CS_OPT_SYNTAX_DEFAULT},
+ {"CS_OPT_SYNTAX_INTEL", CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL},
+ {"CS_OPT_SYNTAX_ATT", CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT},
+ {"CS_OPT_SYNTAX_NOREGNAME", CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME},
+ {"CS_OPT_SYNTAX_MASM", CS_OPT_SYNTAX, CS_OPT_SYNTAX_MASM},
+ {"CS_MODE_LITTLE_ENDIAN", CS_OPT_MODE, CS_MODE_LITTLE_ENDIAN},
+ {"CS_MODE_ARM", CS_OPT_MODE, CS_MODE_ARM},
+ {"CS_MODE_16", CS_OPT_MODE, CS_MODE_16},
+ {"CS_MODE_32", CS_OPT_MODE, CS_MODE_32},
+ {"CS_MODE_64", CS_OPT_MODE, CS_MODE_64},
+ {"CS_MODE_THUMB", CS_OPT_MODE, CS_MODE_THUMB},
+ {"CS_MODE_MCLASS", CS_OPT_MODE, CS_MODE_MCLASS},
+ {"CS_MODE_V8", CS_OPT_MODE, CS_MODE_V8},
+ {"CS_MODE_MICRO", CS_OPT_MODE, CS_MODE_MICRO},
+ {"CS_MODE_MIPS3", CS_OPT_MODE, CS_MODE_MIPS3},
+ {"CS_MODE_MIPS32R6", CS_OPT_MODE, CS_MODE_MIPS32R6},
+ {"CS_MODE_MIPS2", CS_OPT_MODE, CS_MODE_MIPS2},
+ {"CS_MODE_V9", CS_OPT_MODE, CS_MODE_V9},
+ {"CS_MODE_QPX", CS_OPT_MODE, CS_MODE_QPX},
+ {"CS_MODE_M68K_000", CS_OPT_MODE, CS_MODE_M68K_000},
+ {"CS_MODE_M68K_010", CS_OPT_MODE, CS_MODE_M68K_010},
+ {"CS_MODE_M68K_020", CS_OPT_MODE, CS_MODE_M68K_020},
+ {"CS_MODE_M68K_030", CS_OPT_MODE, CS_MODE_M68K_030},
+ {"CS_MODE_M68K_040", CS_OPT_MODE, CS_MODE_M68K_040},
+ {"CS_MODE_M68K_060", CS_OPT_MODE, CS_MODE_M68K_060},
+ {"CS_MODE_BIG_ENDIAN", CS_OPT_MODE, CS_MODE_BIG_ENDIAN},
+ {"CS_MODE_MIPS32", CS_OPT_MODE, CS_MODE_MIPS32},
+ {"CS_MODE_MIPS64", CS_OPT_MODE, CS_MODE_MIPS64},
+ {"CS_MODE_M680X_6301", CS_OPT_MODE, CS_MODE_M680X_6301},
+ {"CS_MODE_M680X_6309", CS_OPT_MODE, CS_MODE_M680X_6309},
+ {"CS_MODE_M680X_6800", CS_OPT_MODE, CS_MODE_M680X_6800},
+ {"CS_MODE_M680X_6801", CS_OPT_MODE, CS_MODE_M680X_6801},
+ {"CS_MODE_M680X_6805", CS_OPT_MODE, CS_MODE_M680X_6805},
+ {"CS_MODE_M680X_6808", CS_OPT_MODE, CS_MODE_M680X_6808},
+ {"CS_MODE_M680X_6809", CS_OPT_MODE, CS_MODE_M680X_6809},
+ {"CS_MODE_M680X_6811", CS_OPT_MODE, CS_MODE_M680X_6811},
+ {"CS_MODE_M680X_CPU12", CS_OPT_MODE, CS_MODE_M680X_CPU12},
+ {"CS_MODE_M680X_HCS08", CS_OPT_MODE, CS_MODE_M680X_HCS08},
+ {"CS_MODE_RISCV32", CS_OPT_MODE, CS_MODE_RISCV32},
+ {"CS_MODE_RISCV64", CS_OPT_MODE, CS_MODE_RISCV64},
+ {"CS_OPT_UNSIGNED", CS_OPT_UNSIGNED, CS_OPT_ON},
+};
+
+static int counter;
+static char **list_lines;
+static int failed_setup;
+static int size_lines;
+static cs_mode issue_mode;
+static int getDetail;
+static int mc_mode;
+static int e_flag;
+
+static int setup_MC(void **state)
+{
+ csh *handle;
+ char **list_params;
+ int size_params;
+ int arch, mode;
+ int i, index, tmp_counter;
+
+ if (failed_setup) {
+ fprintf(stderr, "[ ERROR ] --- Invalid file to setup\n");
+ return -1;
+ }
+
+ tmp_counter = 0;
+ while (tmp_counter < size_lines && list_lines[tmp_counter][0] != '#')
+ tmp_counter++;
+
+ list_params = split(list_lines[tmp_counter] + 2, ", ", &size_params);
+ if (size_params != 3) {
+ fprintf(stderr, "[ ERROR ] --- Invalid options ( arch, mode, option )\n");
+ failed_setup = 1;
+ return -1;
+ }
+
+ arch = get_value(arches, ARR_SIZE(arches), list_params[0]);
+ if (!strcmp(list_params[0], "CS_ARCH_ARM64"))
+ mc_mode = 2;
+ else
+ mc_mode = 1;
+
+ mode = 0;
+ for (i = 0; i < ARR_SIZE(modes); ++i) {
+ if (strstr(list_params[1], modes[i].str)) {
+ mode += modes[i].value;
+ switch (modes[i].value) {
+ case CS_MODE_16:
+ mc_mode = 0;
+ break;
+ case CS_MODE_64:
+ mc_mode = 2;
+ break;
+ case CS_MODE_THUMB:
+ mc_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (arch == -1) {
+ fprintf(stderr, "[ ERROR ] --- Arch is not supported!\n");
+ failed_setup = 1;
+ return -1;
+ }
+
+ handle = (csh *)malloc(sizeof(csh));
+ if(cs_open(arch, mode, handle) != CS_ERR_OK) {
+ fprintf(stderr, "[ ERROR ] --- Cannot initialize capstone\n");
+ failed_setup = 1;
+ return -1;
+ }
+
+ for (i = 0; i < ARR_SIZE(options); ++i) {
+ if (strstr(list_params[2], options[i].str)) {
+ if (cs_option(*handle, options[i].first_value, options[i].second_value) != CS_ERR_OK) {
+ fprintf(stderr, "[ ERROR ] --- Option is not supported for this arch/mode\n");
+ failed_setup = 1;
+ return -1;
+ }
+ }
+ }
+
+ *state = (void *)handle;
+ counter++;
+ if (e_flag == 0)
+ while (counter < size_lines && strncmp(list_lines[counter], "0x", 2))
+ counter++;
+ else
+ while (counter < size_lines && strncmp(list_lines[counter], "// 0x", 5))
+ counter++;
+
+ free_strs(list_params, size_params);
+ return 0;
+}
+
+static void test_MC(void **state)
+{
+ if (e_flag == 1)
+ test_single_MC((csh *)*state, mc_mode, list_lines[counter] + 3);
+ else
+ test_single_MC((csh *)*state, mc_mode, list_lines[counter]);
+}
+
+static int teardown_MC(void **state)
+{
+ cs_close(*state);
+ free(*state);
+ return 0;
+}
+
+static int setup_issue(void **state)
+{
+ csh *handle;
+ char **list_params;
+ int size_params;
+ int arch, mode;
+ int i, index, result;
+ char *(*function)(csh *, cs_mode, cs_insn*);
+
+ getDetail = 0;
+ failed_setup = 0;
+
+ if (e_flag == 0)
+ while (counter < size_lines && strncmp(list_lines[counter], "!# ", 3))
+ counter++; // get issue line
+ else
+ while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6))
+ counter++;
+
+ counter++;
+ if (e_flag == 0)
+ while (counter < size_lines && strncmp(list_lines[counter], "!#", 2))
+ counter++; // get arch line
+ else
+ while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6))
+ counter++;
+
+ if (e_flag == 0)
+ list_params = split(list_lines[counter] + 3, ", ", &size_params);
+ else
+ list_params = split(list_lines[counter] + 6, ", ", &size_params);
+
+ arch = get_value(arches, ARR_SIZE(arches), list_params[0]);
+
+ if (!strcmp(list_params[0], "CS_ARCH_ARM64"))
+ mc_mode = 2;
+ else
+ mc_mode = 1;
+
+ mode = 0;
+ for (i = 0; i < ARR_SIZE(modes); ++i) {
+ if (strstr(list_params[1], modes[i].str)) {
+ mode += modes[i].value;
+ switch (modes[i].value) {
+ case CS_MODE_16:
+ mc_mode = 0;
+ break;
+ case CS_MODE_64:
+ mc_mode = 2;
+ break;
+ case CS_MODE_THUMB:
+ mc_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (arch == -1) {
+ fprintf(stderr, "[ ERROR ] --- Arch is not supported!\n");
+ failed_setup = 1;
+ return -1;
+ }
+
+ handle = (csh *)calloc(1, sizeof(csh));
+ if(cs_open(arch, mode, handle) != CS_ERR_OK) {
+ fprintf(stderr, "[ ERROR ] --- Cannot initialize capstone\n");
+ failed_setup = 1;
+ return -1;
+ }
+
+ for (i = 0; i < ARR_SIZE(options); ++i) {
+ if (strstr(list_params[2], options[i].str)) {
+ if (cs_option(*handle, options[i].first_value, options[i].second_value) != CS_ERR_OK) {
+ fprintf(stderr, "[ ERROR ] --- Option is not supported for this arch/mode\n");
+ failed_setup = 1;
+ return -1;
+ }
+
+ if (i == 0) {
+ result = set_function(arch);
+ if (result == -1) {
+ fprintf(stderr, "[ ERROR ] --- Cannot get details\n");
+ failed_setup = 1;
+ return -1;
+ }
+
+ getDetail = 1;
+ }
+ }
+ }
+
+ *state = (void *)handle;
+ issue_mode = mode;
+
+ if (e_flag == 0)
+ while (counter < size_lines && strncmp(list_lines[counter], "0x", 2))
+ counter++;
+ else
+ while (counter < size_lines && strncmp(list_lines[counter], "// 0x", 5))
+ counter++;
+
+ free_strs(list_params, size_params);
+ return 0;
+}
+
+static void test_issue(void **state)
+{
+ if (e_flag == 0)
+ test_single_issue((csh *)*state, issue_mode, list_lines[counter], getDetail);
+ else
+ test_single_issue((csh *)*state, issue_mode, list_lines[counter] + 3, getDetail);
+
+ return;
+}
+
+static int teardown_issue(void **state)
+{
+ if (e_flag == 0)
+ while (counter < size_lines && strncmp(list_lines[counter], "!# ", 3))
+ counter++;
+ else
+ while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6))
+ counter++;
+
+ cs_close(*state);
+ free(*state);
+ function = NULL;
+ return 0;
+}
+
+static void test_file(const char *filename)
+{
+ int size, i;
+ char **list_str;
+ char *content, *tmp;
+ struct CMUnitTest *tests;
+ int issue_num, number_of_tests;
+
+ printf("[+] TARGET: %s\n", filename);
+ content = readfile(filename);
+ counter = 0;
+ failed_setup = 0;
+ function = NULL;
+
+ if (strstr(filename, "issue")) {
+ number_of_tests = 0;
+ list_lines = split(content, "\n", &size_lines);
+ tests = NULL;
+ for (i = 0; i < size_lines; ++i) {
+ if ((!strncmp(list_lines[i], "// !# issue", 11) && e_flag == 1) ||
+ (!strncmp(list_lines[i], "!# issue", 8) && e_flag == 0)) {
+ tests = (struct CMUnitTest *)realloc(tests, sizeof(struct CMUnitTest) * (number_of_tests + 1));
+ tests[number_of_tests] = (struct CMUnitTest)cmocka_unit_test_setup_teardown(test_issue, setup_issue, teardown_issue);
+ tests[number_of_tests].name = strdup(list_lines[i]);
+ number_of_tests ++;
+ }
+ }
+
+ _cmocka_run_group_tests("Testing issues", tests, number_of_tests, NULL, NULL);
+ } else {
+ list_lines = split(content, "\n", &size_lines);
+ number_of_tests = 0;
+
+ tests = NULL;
+ for (i = 1; i < size_lines; ++i) {
+ if ((!strncmp(list_lines[i], "// 0x", 5) && e_flag == 1) || (!strncmp(list_lines[i], "0x", 2) && e_flag == 0)) {
+ tmp = (char *)malloc(sizeof(char) * 100);
+ sprintf(tmp, "Line %d", i+1);
+ tests = (struct CMUnitTest *)realloc(tests, sizeof(struct CMUnitTest) * (number_of_tests + 1));
+ tests[number_of_tests] = (struct CMUnitTest)cmocka_unit_test_setup_teardown(test_MC, setup_MC, teardown_MC);
+ tests[number_of_tests].name = tmp;
+ number_of_tests ++;
+ }
+ }
+
+ _cmocka_run_group_tests("Testing MC", tests, number_of_tests, NULL, NULL);
+ }
+
+ printf("[+] DONE: %s\n", filename);
+ printf("[!] Noted:\n[ ERROR ] --- \"<capstone result>\" != \"<user result>\"\n");
+ printf("\n\n");
+ free_strs(list_lines, size_lines);
+}
+
+static void test_folder(const char *folder)
+{
+ char **files;
+ int num_files, i;
+
+ files = NULL;
+ num_files = 0;
+ listdir(folder, &files, &num_files);
+ for (i = 0; i < num_files; ++i) {
+ if (strcmp("cs", get_filename_ext(files[i])))
+ continue;
+ test_file(files[i]);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int opt, flag;
+
+ flag = 0;
+ e_flag = 0;
+
+ while ((opt = getopt(argc, argv, "ef:d:")) > 0) {
+ switch (opt) {
+ case 'f':
+ test_file(optarg);
+ flag = 1;
+ break;
+ case 'd':
+ test_folder(optarg);
+ flag = 1;
+ break;
+ case 'e':
+ e_flag = 1;
+ break;
+ default:
+ printf("Usage: %s [-e] [-f <file_name.cs>] [-d <directory>]\n", argv[0]);
+ exit(-1);
+ }
+ }
+
+ if (flag == 0) {
+ printf("Usage: %s [-e] [-f <file_name.cs>] [-d <directory>]\n", argv[0]);
+ exit(-1);
+ }
+
+ return 0;
+}
diff --git a/capstone/suite/cstest/src/mips_detail.c b/capstone/suite/cstest/src/mips_detail.c
new file mode 100644
index 000000000..c859ab6d7
--- /dev/null
+++ b/capstone/suite/cstest/src/mips_detail.c
@@ -0,0 +1,48 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+char *get_detail_mips(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ int i;
+ cs_mips *mips;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ mips = &(ins->detail->mips);
+ if (mips->op_count)
+ add_str(&result, " ; op_count: %u", mips->op_count);
+
+ for (i = 0; i < mips->op_count; i++) {
+ cs_mips_op *op = &(mips->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case MIPS_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case MIPS_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64 "", i, op->imm);
+ break;
+ case MIPS_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base != MIPS_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base));
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%" PRIx64 "", i, op->mem.disp);
+
+ break;
+ }
+
+ }
+
+ return result;
+}
+
diff --git a/capstone/suite/cstest/src/mos65xx_detail.c b/capstone/suite/cstest/src/mos65xx_detail.c
new file mode 100644
index 000000000..b039f2e76
--- /dev/null
+++ b/capstone/suite/cstest/src/mos65xx_detail.c
@@ -0,0 +1,103 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+static const char *get_am_name(mos65xx_address_mode mode)
+{
+ switch(mode) {
+ default:
+ case MOS65XX_AM_NONE:
+ return "No address mode";
+ case MOS65XX_AM_IMP:
+ return "implied";
+ case MOS65XX_AM_ACC:
+ return "accumulator";
+ case MOS65XX_AM_IMM:
+ return "immediate value";
+ case MOS65XX_AM_REL:
+ return "relative";
+ case MOS65XX_AM_INT:
+ return "interrupt signature";
+ case MOS65XX_AM_BLOCK:
+ return "block move";
+ case MOS65XX_AM_ZP:
+ return "zero page";
+ case MOS65XX_AM_ZP_X:
+ return "zero page indexed with x";
+ case MOS65XX_AM_ZP_Y:
+ return "zero page indexed with y";
+ case MOS65XX_AM_ZP_REL:
+ return "relative bit branch";
+ case MOS65XX_AM_ZP_IND:
+ return "zero page indirect";
+ case MOS65XX_AM_ZP_X_IND:
+ return "zero page indexed with x indirect";
+ case MOS65XX_AM_ZP_IND_Y:
+ return "zero page indirect indexed with y";
+ case MOS65XX_AM_ZP_IND_LONG:
+ return "zero page indirect long";
+ case MOS65XX_AM_ZP_IND_LONG_Y:
+ return "zero page indirect long indexed with y";
+ case MOS65XX_AM_ABS:
+ return "absolute";
+ case MOS65XX_AM_ABS_X:
+ return "absolute indexed with x";
+ case MOS65XX_AM_ABS_Y:
+ return "absolute indexed with y";
+ case MOS65XX_AM_ABS_IND:
+ return "absolute indirect";
+ case MOS65XX_AM_ABS_X_IND:
+ return "absolute indexed with x indirect";
+ case MOS65XX_AM_ABS_IND_LONG:
+ return "absolute indirect long";
+ case MOS65XX_AM_ABS_LONG:
+ return "absolute long";
+ case MOS65XX_AM_ABS_LONG_X:
+ return "absolute long indexed with x";
+ case MOS65XX_AM_SR:
+ return "stack relative";
+ case MOS65XX_AM_SR_IND_Y:
+ return "stack relative indirect indexed with y";
+ }
+}
+
+
+char *get_detail_mos65xx(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ int i;
+ cs_mos65xx *mos65xx;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ mos65xx = &(ins->detail->mos65xx);
+ add_str(&result, " ; address mode: %s", get_am_name(mos65xx->am));
+ add_str(&result, " ; modifies flags: %s", mos65xx->modifies_flags ? "true": "false");
+
+ if (mos65xx->op_count)
+ add_str(&result, " ; op_count: %u", mos65xx->op_count);
+
+ for (i = 0; i < mos65xx->op_count; i++) {
+ cs_mos65xx_op *op = &(mos65xx->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case MOS65XX_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case MOS65XX_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm);
+ break;
+ case MOS65XX_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM = 0x%x", i, op->mem);
+ break;
+ }
+ }
+ return result;
+}
diff --git a/capstone/suite/cstest/src/ppc_detail.c b/capstone/suite/cstest/src/ppc_detail.c
new file mode 100644
index 000000000..7a2ab8856
--- /dev/null
+++ b/capstone/suite/cstest/src/ppc_detail.c
@@ -0,0 +1,91 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+static const char* get_bc_name(int bc)
+{
+ switch(bc) {
+ default:
+ case PPC_BC_INVALID:
+ return ("invalid");
+ case PPC_BC_LT:
+ return ("lt");
+ case PPC_BC_LE:
+ return ("le");
+ case PPC_BC_EQ:
+ return ("eq");
+ case PPC_BC_GE:
+ return ("ge");
+ case PPC_BC_GT:
+ return ("gt");
+ case PPC_BC_NE:
+ return ("ne");
+ case PPC_BC_UN:
+ return ("un");
+ case PPC_BC_NU:
+ return ("nu");
+ case PPC_BC_SO:
+ return ("so");
+ case PPC_BC_NS:
+ return ("ns");
+ }
+}
+
+char *get_detail_ppc(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_ppc *ppc;
+ int i;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ ppc = &(ins->detail->ppc);
+ if (ppc->op_count)
+ add_str(&result, " ; op_count: %u", ppc->op_count);
+
+ for (i = 0; i < ppc->op_count; i++) {
+ cs_ppc_op *op = &(ppc->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case PPC_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case PPC_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%"PRIx64"", i, op->imm);
+ break;
+ case PPC_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base != PPC_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base));
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp);
+
+ break;
+ case PPC_OP_CRX:
+ add_str(&result, " ; operands[%u].type: CRX", i);
+ add_str(&result, " ; operands[%u].crx.scale: %d", i, op->crx.scale);
+ add_str(&result, " ; operands[%u].crx.reg: %s", i, cs_reg_name(*handle, op->crx.reg));
+ add_str(&result, " ; operands[%u].crx.cond: %s", i, get_bc_name(op->crx.cond));
+ break;
+ }
+ }
+
+ if (ppc->bc != 0)
+ add_str(&result, " ; Branch code: %u", ppc->bc);
+
+ if (ppc->bh != 0)
+ add_str(&result, " ; Branch hint: %u", ppc->bh);
+
+ if (ppc->update_cr0)
+ add_str(&result, " ; Update-CR0: True");
+
+ return result;
+}
+
diff --git a/capstone/suite/cstest/src/riscv_detail.c b/capstone/suite/cstest/src/riscv_detail.c
new file mode 100644
index 000000000..70cc770e2
--- /dev/null
+++ b/capstone/suite/cstest/src/riscv_detail.c
@@ -0,0 +1,47 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+char *get_detail_riscv(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_riscv *riscv;
+ int i;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ riscv = &(ins->detail->riscv);
+ if (riscv->op_count)
+ add_str(&result, " ; op_count: %u", riscv->op_count);
+
+ for (i = 0; i < riscv->op_count; i++) {
+ cs_riscv_op *op = &(riscv->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case RISCV_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case RISCV_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm);
+ break;
+ case RISCV_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base != RISCV_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s",
+ i, cs_reg_name(*handle, op->mem.base));
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp);
+ break;
+ }
+ }
+
+ return result;
+}
+
diff --git a/capstone/suite/cstest/src/sparc_detail.c b/capstone/suite/cstest/src/sparc_detail.c
new file mode 100644
index 000000000..54c6bb483
--- /dev/null
+++ b/capstone/suite/cstest/src/sparc_detail.c
@@ -0,0 +1,55 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+char *get_detail_sparc(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_sparc *sparc;
+ int i;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ sparc = &(ins->detail->sparc);
+ if (sparc->op_count)
+ add_str(&result, " ; op_count: %u", sparc->op_count);
+
+ for (i = 0; i < sparc->op_count; i++) {
+ cs_sparc_op *op = &(sparc->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case SPARC_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case SPARC_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64 "", i, op->imm);
+ break;
+ case SPARC_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base != X86_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base));
+ if (op->mem.index != X86_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index));
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp);
+
+ break;
+ }
+ }
+
+ if (sparc->cc != 0)
+ add_str(&result, " ; Code condition: %u", sparc->cc);
+
+ if (sparc->hint != 0)
+ add_str(&result, " ; Hint code: %u", sparc->hint);
+
+ return result;
+}
+
diff --git a/capstone/suite/cstest/src/systemz_detail.c b/capstone/suite/cstest/src/systemz_detail.c
new file mode 100644
index 000000000..b9d24a055
--- /dev/null
+++ b/capstone/suite/cstest/src/systemz_detail.c
@@ -0,0 +1,57 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+char *get_detail_sysz(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_sysz *sysz;
+ int i;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ sysz = &(ins->detail->sysz);
+ if (sysz->op_count)
+ add_str(&result, " ; op_count: %u", sysz->op_count);
+
+ for (i = 0; i < sysz->op_count; i++) {
+ cs_sysz_op *op = &(sysz->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case SYSZ_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case SYSZ_OP_ACREG:
+ add_str(&result, " ; operands[%u].type: ACREG = %u", i, op->reg);
+ break;
+ case SYSZ_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64 "", i, op->imm);
+ break;
+ case SYSZ_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base != SYSZ_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base));
+ if (op->mem.index != SYSZ_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index));
+ if (op->mem.length != 0)
+ add_str(&result, " ; operands[%u].mem.length: 0x%" PRIx64 "", i, op->mem.length);
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%" PRIx64 "", i, op->mem.disp);
+
+ break;
+ }
+ }
+
+ if (sysz->cc != 0)
+ add_str(&result, " ; Code condition: %u", sysz->cc);
+
+ return result;
+}
+
diff --git a/capstone/suite/cstest/src/tms320c64x_detail.c b/capstone/suite/cstest/src/tms320c64x_detail.c
new file mode 100644
index 000000000..f6b0b9185
--- /dev/null
+++ b/capstone/suite/cstest/src/tms320c64x_detail.c
@@ -0,0 +1,107 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+char *get_detail_tms320c64x(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_tms320c64x *tms320c64x;
+ int i;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ tms320c64x = &(ins->detail->tms320c64x);
+ if (tms320c64x->op_count)
+ add_str(&result, " ; op_count: %u", tms320c64x->op_count);
+
+ for (i = 0; i < tms320c64x->op_count; i++) {
+ cs_tms320c64x_op *op = &(tms320c64x->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case TMS320C64X_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case TMS320C64X_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm);
+ break;
+ case TMS320C64X_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base != TMS320C64X_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base));
+ add_str(&result, " ; operands[%u].mem.disptype: ", i);
+ if (op->mem.disptype == TMS320C64X_MEM_DISP_INVALID) {
+ add_str(&result, "Invalid");
+ add_str(&result, " ; operands[%u].mem.disp: %u", i, op->mem.disp);
+ }
+ if (op->mem.disptype == TMS320C64X_MEM_DISP_CONSTANT) {
+ add_str(&result, "Constant");
+ add_str(&result, " ; operands[%u].mem.disp: %u", i, op->mem.disp);
+ }
+ if (op->mem.disptype == TMS320C64X_MEM_DISP_REGISTER) {
+ add_str(&result, "Register");
+ add_str(&result, " ; operands[%u].mem.disp: %s", i, cs_reg_name(*handle, op->mem.disp));
+ }
+ add_str(&result, " ; operands[%u].mem.unit: %u", i, op->mem.unit);
+ add_str(&result, " ; operands[%u].mem.direction: ", i);
+ if (op->mem.direction == TMS320C64X_MEM_DIR_INVALID)
+ add_str(&result, "Invalid");
+ if (op->mem.direction == TMS320C64X_MEM_DIR_FW)
+ add_str(&result, "Forward");
+ if (op->mem.direction == TMS320C64X_MEM_DIR_BW)
+ add_str(&result, "Backward");
+ add_str(&result, " ; operands[%u].mem.modify: ", i);
+ if (op->mem.modify == TMS320C64X_MEM_MOD_INVALID)
+ add_str(&result, "Invalid");
+ if (op->mem.modify == TMS320C64X_MEM_MOD_NO)
+ add_str(&result, "No");
+ if (op->mem.modify == TMS320C64X_MEM_MOD_PRE)
+ add_str(&result, "Pre");
+ if (op->mem.modify == TMS320C64X_MEM_MOD_POST)
+ add_str(&result, "Post");
+ add_str(&result, " ; operands[%u].mem.scaled: %u", i, op->mem.scaled);
+
+ break;
+ case TMS320C64X_OP_REGPAIR:
+ add_str(&result, " ; operands[%u].type: REGPAIR = %s:%s", i, cs_reg_name(*handle, op->reg + 1), cs_reg_name(*handle, op->reg));
+ break;
+ }
+ }
+
+ add_str(&result, " ; Functional unit: ");
+ switch(tms320c64x->funit.unit) {
+ case TMS320C64X_FUNIT_D:
+ add_str(&result, "D%u", tms320c64x->funit.side);
+ break;
+ case TMS320C64X_FUNIT_L:
+ add_str(&result, "L%u", tms320c64x->funit.side);
+ break;
+ case TMS320C64X_FUNIT_M:
+ add_str(&result, "M%u", tms320c64x->funit.side);
+ break;
+ case TMS320C64X_FUNIT_S:
+ add_str(&result, "S%u", tms320c64x->funit.side);
+ break;
+ case TMS320C64X_FUNIT_NO:
+ add_str(&result, "No Functional Unit");
+ break;
+ default:
+ add_str(&result, "Unknown (Unit %u, Side %u)", tms320c64x->funit.unit, tms320c64x->funit.side);
+ break;
+ }
+ if (tms320c64x->funit.crosspath == 1)
+ add_str(&result, " ; Crosspath: 1");
+
+ if (tms320c64x->condition.reg != TMS320C64X_REG_INVALID)
+ add_str(&result, " ; Condition: [%c%s]", (tms320c64x->condition.zero == 1) ? '!' : ' ', cs_reg_name(*handle, tms320c64x->condition.reg));
+ add_str(&result, " ; Parallel: %s", (tms320c64x->parallel == 1) ? "true" : "false");
+
+ return result;
+}
+
diff --git a/capstone/suite/cstest/src/x86_detail.c b/capstone/suite/cstest/src/x86_detail.c
new file mode 100644
index 000000000..f5456877c
--- /dev/null
+++ b/capstone/suite/cstest/src/x86_detail.c
@@ -0,0 +1,344 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+static void print_string_hex(char **result, const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ add_str(result, "%s", comment);
+ for (c = str; c < str + len; c++) {
+ add_str(result, "0x%02x", *c & 0xff);
+ if (c < str + len - 1)
+ add_str(result, " ");
+ }
+
+}
+
+static const char *get_eflag_name(uint64_t flag)
+{
+ switch(flag) {
+ default:
+ return NULL;
+ case X86_EFLAGS_UNDEFINED_OF:
+ return "UNDEF_OF";
+ case X86_EFLAGS_UNDEFINED_SF:
+ return "UNDEF_SF";
+ case X86_EFLAGS_UNDEFINED_ZF:
+ return "UNDEF_ZF";
+ case X86_EFLAGS_MODIFY_AF:
+ return "MOD_AF";
+ case X86_EFLAGS_UNDEFINED_PF:
+ return "UNDEF_PF";
+ case X86_EFLAGS_MODIFY_CF:
+ return "MOD_CF";
+ case X86_EFLAGS_MODIFY_SF:
+ return "MOD_SF";
+ case X86_EFLAGS_MODIFY_ZF:
+ return "MOD_ZF";
+ case X86_EFLAGS_UNDEFINED_AF:
+ return "UNDEF_AF";
+ case X86_EFLAGS_MODIFY_PF:
+ return "MOD_PF";
+ case X86_EFLAGS_UNDEFINED_CF:
+ return "UNDEF_CF";
+ case X86_EFLAGS_MODIFY_OF:
+ return "MOD_OF";
+ case X86_EFLAGS_RESET_OF:
+ return "RESET_OF";
+ case X86_EFLAGS_RESET_CF:
+ return "RESET_CF";
+ case X86_EFLAGS_RESET_DF:
+ return "RESET_DF";
+ case X86_EFLAGS_RESET_IF:
+ return "RESET_IF";
+ case X86_EFLAGS_RESET_ZF:
+ return "RESET_ZF";
+ case X86_EFLAGS_TEST_OF:
+ return "TEST_OF";
+ case X86_EFLAGS_TEST_SF:
+ return "TEST_SF";
+ case X86_EFLAGS_TEST_ZF:
+ return "TEST_ZF";
+ case X86_EFLAGS_TEST_PF:
+ return "TEST_PF";
+ case X86_EFLAGS_TEST_CF:
+ return "TEST_CF";
+ case X86_EFLAGS_RESET_SF:
+ return "RESET_SF";
+ case X86_EFLAGS_RESET_AF:
+ return "RESET_AF";
+ case X86_EFLAGS_RESET_TF:
+ return "RESET_TF";
+ case X86_EFLAGS_RESET_NT:
+ return "RESET_NT";
+ case X86_EFLAGS_PRIOR_OF:
+ return "PRIOR_OF";
+ case X86_EFLAGS_PRIOR_SF:
+ return "PRIOR_SF";
+ case X86_EFLAGS_PRIOR_ZF:
+ return "PRIOR_ZF";
+ case X86_EFLAGS_PRIOR_AF:
+ return "PRIOR_AF";
+ case X86_EFLAGS_PRIOR_PF:
+ return "PRIOR_PF";
+ case X86_EFLAGS_PRIOR_CF:
+ return "PRIOR_CF";
+ case X86_EFLAGS_PRIOR_TF:
+ return "PRIOR_TF";
+ case X86_EFLAGS_PRIOR_IF:
+ return "PRIOR_IF";
+ case X86_EFLAGS_PRIOR_DF:
+ return "PRIOR_DF";
+ case X86_EFLAGS_TEST_NT:
+ return "TEST_NT";
+ case X86_EFLAGS_TEST_DF:
+ return "TEST_DF";
+ case X86_EFLAGS_RESET_PF:
+ return "RESET_PF";
+ case X86_EFLAGS_PRIOR_NT:
+ return "PRIOR_NT";
+ case X86_EFLAGS_MODIFY_TF:
+ return "MOD_TF";
+ case X86_EFLAGS_MODIFY_IF:
+ return "MOD_IF";
+ case X86_EFLAGS_MODIFY_DF:
+ return "MOD_DF";
+ case X86_EFLAGS_MODIFY_NT:
+ return "MOD_NT";
+ case X86_EFLAGS_MODIFY_RF:
+ return "MOD_RF";
+ case X86_EFLAGS_SET_CF:
+ return "SET_CF";
+ case X86_EFLAGS_SET_DF:
+ return "SET_DF";
+ case X86_EFLAGS_SET_IF:
+ return "SET_IF";
+ case X86_EFLAGS_SET_OF:
+ return "SET_OF";
+ case X86_EFLAGS_SET_SF:
+ return "SET_SF";
+ case X86_EFLAGS_SET_ZF:
+ return "SET_ZF";
+ case X86_EFLAGS_SET_AF:
+ return "SET_AF";
+ case X86_EFLAGS_SET_PF:
+ return "SET_PF";
+ case X86_EFLAGS_TEST_AF:
+ return "TEST_AF";
+ case X86_EFLAGS_TEST_TF:
+ return "TEST_TF";
+ case X86_EFLAGS_TEST_RF:
+ return "TEST_RF";
+ case X86_EFLAGS_RESET_0F:
+ return "RESET_0F";
+ case X86_EFLAGS_RESET_AC:
+ return "RESET_AC";
+ }
+}
+
+static const char *get_fpu_flag_name(uint64_t flag)
+{
+ switch (flag) {
+ default:
+ return NULL;
+ case X86_FPU_FLAGS_MODIFY_C0:
+ return "MOD_C0";
+ case X86_FPU_FLAGS_MODIFY_C1:
+ return "MOD_C1";
+ case X86_FPU_FLAGS_MODIFY_C2:
+ return "MOD_C2";
+ case X86_FPU_FLAGS_MODIFY_C3:
+ return "MOD_C3";
+ case X86_FPU_FLAGS_RESET_C0:
+ return "RESET_C0";
+ case X86_FPU_FLAGS_RESET_C1:
+ return "RESET_C1";
+ case X86_FPU_FLAGS_RESET_C2:
+ return "RESET_C2";
+ case X86_FPU_FLAGS_RESET_C3:
+ return "RESET_C3";
+ case X86_FPU_FLAGS_SET_C0:
+ return "SET_C0";
+ case X86_FPU_FLAGS_SET_C1:
+ return "SET_C1";
+ case X86_FPU_FLAGS_SET_C2:
+ return "SET_C2";
+ case X86_FPU_FLAGS_SET_C3:
+ return "SET_C3";
+ case X86_FPU_FLAGS_UNDEFINED_C0:
+ return "UNDEF_C0";
+ case X86_FPU_FLAGS_UNDEFINED_C1:
+ return "UNDEF_C1";
+ case X86_FPU_FLAGS_UNDEFINED_C2:
+ return "UNDEF_C2";
+ case X86_FPU_FLAGS_UNDEFINED_C3:
+ return "UNDEF_C3";
+ case X86_FPU_FLAGS_TEST_C0:
+ return "TEST_C0";
+ case X86_FPU_FLAGS_TEST_C1:
+ return "TEST_C1";
+ case X86_FPU_FLAGS_TEST_C2:
+ return "TEST_C2";
+ case X86_FPU_FLAGS_TEST_C3:
+ return "TEST_C3";
+ }
+}
+
+char *get_detail_x86(csh *ud, cs_mode mode, cs_insn *ins)
+{
+ int count, i;
+ cs_x86 *x86;
+ cs_regs regs_read, regs_write;
+ uint8_t regs_read_count, regs_write_count;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ x86 = &(ins->detail->x86);
+
+ print_string_hex(&result, " ; Prefix:", x86->prefix, 4);
+ print_string_hex(&result, " ; Opcode:", x86->opcode, 4);
+ add_str(&result, " ; rex: 0x%x", x86->rex);
+ add_str(&result, " ; addr_size: %u", x86->addr_size);
+ add_str(&result, " ; modrm: 0x%x", x86->modrm);
+ add_str(&result, " ; disp: 0x%" PRIx64 "", x86->disp);
+
+ if ((mode & CS_MODE_16) == 0) {
+ add_str(&result, " ; sib: 0x%x", x86->sib);
+ if (x86->sib_base != X86_REG_INVALID)
+ add_str(&result, " ; sib_base: %s", cs_reg_name(*ud, x86->sib_base));
+ if (x86->sib_index != X86_REG_INVALID)
+ add_str(&result, " ; sib_index: %s", cs_reg_name(*ud, x86->sib_index));
+ if (x86->sib_scale != 0)
+ add_str(&result, " ; sib_scale: %d", x86->sib_scale);
+ }
+
+ if (x86->xop_cc != X86_XOP_CC_INVALID) {
+ add_str(&result, " ; xop_cc: %u", x86->xop_cc);
+ }
+
+ if (x86->sse_cc != X86_SSE_CC_INVALID) {
+ add_str(&result, " ; sse_cc: %u", x86->sse_cc);
+ }
+
+ if (x86->avx_cc != X86_AVX_CC_INVALID) {
+ add_str(&result, " ; avx_cc: %u", x86->avx_cc);
+ }
+
+ if (x86->avx_sae) {
+ add_str(&result, " ; avx_sae: %u", x86->avx_sae);
+ }
+
+ if (x86->avx_rm != X86_AVX_RM_INVALID) {
+ add_str(&result, " ; avx_rm: %u", x86->avx_rm);
+ }
+
+ count = cs_op_count(*ud, ins, X86_OP_IMM);
+ if (count > 0) {
+ add_str(&result, " ; imm_count: %u", count);
+ for (i = 1; i < count + 1; i++) {
+ int index = cs_op_index(*ud, ins, X86_OP_IMM, i);
+ add_str(&result, " ; imms[%u]: 0x%" PRIx64 "", i, x86->operands[index].imm);
+ }
+ }
+
+ if (x86->op_count)
+ add_str(&result, " ; op_count: %u", x86->op_count);
+
+ for (i = 0; i < x86->op_count; i++) {
+ cs_x86_op *op = &(x86->operands[i]);
+
+ switch((int)op->type) {
+ case X86_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*ud, op->reg));
+ break;
+ case X86_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64 "", i, op->imm);
+ break;
+ case X86_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.segment != X86_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.segment: REG = %s", i, cs_reg_name(*ud, op->mem.segment));
+ if (op->mem.base != X86_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*ud, op->mem.base));
+ if (op->mem.index != X86_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*ud, op->mem.index));
+ if (op->mem.scale != 1)
+ add_str(&result, " ; operands[%u].mem.scale: %u", i, op->mem.scale);
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%" PRIx64 "", i, op->mem.disp);
+ break;
+ default:
+ break;
+ }
+
+ if (op->avx_bcast != X86_AVX_BCAST_INVALID)
+ add_str(&result, " ; operands[%u].avx_bcast: %u", i, op->avx_bcast);
+
+ if (op->avx_zero_opmask != false)
+ add_str(&result, " ; operands[%u].avx_zero_opmask: TRUE", i);
+
+ add_str(&result, " ; operands[%u].size: %u", i, op->size);
+
+ switch(op->access) {
+ default:
+ break;
+ case CS_AC_READ:
+ add_str(&result, " ; operands[%u].access: READ", i);
+ break;
+ case CS_AC_WRITE:
+ add_str(&result, " ; operands[%u].access: WRITE", i);
+ break;
+ case CS_AC_READ | CS_AC_WRITE:
+ add_str(&result, " ; operands[%u].access: READ | WRITE", i);
+ break;
+ }
+ }
+
+ if (!cs_regs_access(*ud, ins, regs_read, &regs_read_count, regs_write, &regs_write_count)) {
+ if (regs_read_count) {
+ add_str(&result, " ; Registers read:");
+ for(i = 0; i < regs_read_count; i++) {
+ add_str(&result, " %s", cs_reg_name(*ud, regs_read[i]));
+ }
+ }
+
+ if (regs_write_count) {
+ add_str(&result, " ; Registers modified:");
+ for(i = 0; i < regs_write_count; i++) {
+ add_str(&result, " %s", cs_reg_name(*ud, regs_write[i]));
+ }
+ }
+ }
+
+ if (x86->eflags || x86->fpu_flags) {
+ for(i = 0; i < ins->detail->groups_count; i++) {
+ if (ins->detail->groups[i] == X86_GRP_FPU) {
+ add_str(&result, " ; FPU_FLAGS:");
+ for(i = 0; i <= 63; i++)
+ if (x86->fpu_flags & ((uint64_t)1 << i)) {
+ add_str(&result, " %s", get_fpu_flag_name((uint64_t)1 << i));
+ }
+ break;
+ }
+ }
+
+ if (i == ins->detail->groups_count) {
+ add_str(&result, " ; EFLAGS:");
+ for(i = 0; i <= 63; i++)
+ if (x86->eflags & ((uint64_t)1 << i)) {
+ add_str(&result, " %s", get_eflag_name((uint64_t)1 << i));
+ }
+ }
+ }
+
+ return result;
+}
+
diff --git a/capstone/suite/cstest/src/xcore_detail.c b/capstone/suite/cstest/src/xcore_detail.c
new file mode 100644
index 000000000..d4f51f818
--- /dev/null
+++ b/capstone/suite/cstest/src/xcore_detail.c
@@ -0,0 +1,52 @@
+/* Capstone testing regression */
+/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
+
+
+#include "factory.h"
+
+char *get_detail_xcore(csh *handle, cs_mode mode, cs_insn *ins)
+{
+ cs_xcore *xcore;
+ int i;
+ char *result;
+
+ result = (char *)malloc(sizeof(char));
+ result[0] = '\0';
+
+ if (ins->detail == NULL)
+ return result;
+
+ xcore = &(ins->detail->xcore);
+ if (xcore->op_count)
+ add_str(&result, " ; op_count: %u", xcore->op_count);
+
+ for (i = 0; i < xcore->op_count; i++) {
+ cs_xcore_op *op = &(xcore->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case XCORE_OP_REG:
+ add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg));
+ break;
+ case XCORE_OP_IMM:
+ add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm);
+ break;
+ case XCORE_OP_MEM:
+ add_str(&result, " ; operands[%u].type: MEM", i);
+ if (op->mem.base != XCORE_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base));
+ if (op->mem.index != XCORE_REG_INVALID)
+ add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index));
+ if (op->mem.disp != 0)
+ add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp);
+ if (op->mem.direct != 1)
+ add_str(&result, " ; operands[%u].mem.direct: -1", i);
+
+
+ break;
+ }
+ }
+
+ return result;
+}
+