Merge branch 'feat/better_python_setup_next' of https://github.com/angr/capstone into angr-feat/better_python_setup_next
diff --git a/arch/X86/X86MappingInsn.inc b/arch/X86/X86MappingInsn.inc
index 2b8cc2e..5bb858e 100644
--- a/arch/X86/X86MappingInsn.inc
+++ b/arch/X86/X86MappingInsn.inc
@@ -15046,13 +15046,13 @@
 {
 	X86_STC, X86_INS_STC,
 #ifndef CAPSTONE_DIET
-	{ 0 }, { 0 }, { 0 }, 0, 0
+	{ 0 }, { X86_REG_EFLAGS, 0 }, { 0 }, 0, 0
 #endif
 },
 {
 	X86_STD, X86_INS_STD,
 #ifndef CAPSTONE_DIET
-	{ 0 }, { 0 }, { 0 }, 0, 0
+	{ 0 }, { X86_REG_EFLAGS, 0 }, { 0 }, 0, 0
 #endif
 },
 {
diff --git a/cstool/README b/cstool/README
index 65479cb..c5ab5c6 100644
--- a/cstool/README
+++ b/cstool/README
@@ -22,5 +22,27 @@
 	$ cstool x32 "90+91"
 	$ cstool x32 "90:91"
 
+To print out instruction details, run Cstool with -d option, like below.
+
+	$ cstool -d x32 "01 d8"
+	0  01d8                              add	eax, ebx
+	Prefix:0x00 0x00 0x00 0x00
+	Opcode:0x01 0x00 0x00 0x00
+	rex: 0x0
+	addr_size: 4
+	modrm: 0xd8
+	disp: 0x0
+	sib: 0x0
+	op_count: 2
+		operands[0].type: REG = eax
+		operands[0].size: 4
+		operands[0].access: READ | WRITE
+		operands[1].type: REG = ebx
+		operands[1].size: 4
+		operands[1].access: READ
+		Registers read: eax ebx
+	Registers modified: eflags eax
+	EFLAGS: MOD_AF MOD_CF MOD_SF MOD_ZF MOD_PF MOD_OF
+
 To see all the supported options, run ./cstool
 
diff --git a/cstool/cstool.c b/cstool/cstool.c
index 1973cd1..f9b025f 100644
--- a/cstool/cstool.c
+++ b/cstool/cstool.c
@@ -17,6 +17,7 @@
 void print_insn_detail_sparc(csh handle, cs_insn *ins);
 void print_insn_detail_sysz(csh handle, cs_insn *ins);
 void print_insn_detail_xcore(csh handle, cs_insn *ins);
+void print_insn_detail_m68k(csh handle, cs_insn *ins);
 
 void print_string_hex(char *comment, unsigned char *str, size_t len)
 {
@@ -122,6 +123,11 @@
 	if (cs_support(CS_ARCH_XCORE)) {
 		printf("        xcore:     xcore\n");
 	}
+	
+	if (cs_support(CS_ARCH_M68K)) {
+		printf("        m68k:      m68k + big endian\n");
+		printf("        m68k40:    m68k_040\n");
+	}
 
 	printf("\n");
 }
@@ -308,6 +314,17 @@
 		arch = CS_ARCH_XCORE;
 		err = cs_open(CS_ARCH_XCORE, CS_MODE_BIG_ENDIAN, &handle);
 	}
+	
+	if (!strcmp(mode,"m68k")) {
+		arch = CS_ARCH_M68K;
+		err = cs_open(CS_ARCH_M68K, CS_MODE_BIG_ENDIAN, &handle);
+	}
+	
+	if (!strcmp(mode,"m68k40")) {
+		arch = CS_ARCH_M68K;
+		err = cs_open(CS_ARCH_M68K, CS_MODE_M68K_040, &handle);
+	}
+
 
 	if (err) {
 		printf("ERROR: Failed on cs_open(), quit!\n");
@@ -372,6 +389,10 @@
 				if (arch == CS_ARCH_XCORE) {
 					print_insn_detail_xcore(handle, &insn[i]);
 				}
+				
+				if (arch == CS_ARCH_M68K) {
+					print_insn_detail_m68k(handle, &insn[i]);
+				}
 			}
 		}
 		cs_free(insn, count);
diff --git a/cstool/cstool_arm.c b/cstool/cstool_arm.c
index 65f281f..a393daa 100644
--- a/cstool/cstool_arm.c
+++ b/cstool/cstool_arm.c
@@ -9,6 +9,8 @@
 {
 	cs_arm *arm;
 	int i;
+	cs_regs regs_read, regs_write;
+	uint8_t regs_read_count, regs_write_count;
 
 	// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
 	if (ins->detail == NULL)
@@ -40,16 +42,18 @@
 				break;
 			case ARM_OP_MEM:
 				printf("\t\toperands[%u].type: MEM\n", i);
-				if (op->mem.base != X86_REG_INVALID)
+				if (op->mem.base != ARM_REG_INVALID)
 					printf("\t\t\toperands[%u].mem.base: REG = %s\n",
 							i, cs_reg_name(handle, op->mem.base));
-				if (op->mem.index != X86_REG_INVALID)
+				if (op->mem.index != ARM_REG_INVALID)
 					printf("\t\t\toperands[%u].mem.index: REG = %s\n",
 							i, cs_reg_name(handle, op->mem.index));
 				if (op->mem.scale != 1)
 					printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale);
 				if (op->mem.disp != 0)
 					printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
+				if (op->mem.lshift != 0)
+					printf("\t\t\toperands[%u].mem.lshift: 0x%x\n", i, op->mem.lshift);
 
 				break;
 			case ARM_OP_PIMM:
@@ -66,6 +70,24 @@
 				break;
 		}
 
+		if (op->neon_lane != -1) {
+			printf("\t\toperands[%u].neon_lane = %u\n", i, op->neon_lane);
+		}
+
+		switch(op->access) {
+			default:
+				break;
+			case CS_AC_READ:
+				printf("\t\toperands[%u].access: READ\n", i);
+				break;
+			case CS_AC_WRITE:
+				printf("\t\toperands[%u].access: WRITE\n", i);
+				break;
+			case CS_AC_READ | CS_AC_WRITE:
+				printf("\t\toperands[%u].access: READ | WRITE\n", i);
+				break;
+		}
+
 		if (op->shift.type != ARM_SFT_INVALID && op->shift.value) {
 			if (op->shift.type < ARM_SFT_ASR_REG)
 				// shift with constant value
@@ -111,5 +133,26 @@
 	if (arm->mem_barrier)
 		printf("\tMemory-barrier: %u\n", arm->mem_barrier);
 
+	// 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) {
+			printf("\tRegisters read:");
+			for(i = 0; i < regs_read_count; i++) {
+				printf(" %s", cs_reg_name(handle, regs_read[i]));
+			}
+			printf("\n");
+		}
+
+		if (regs_write_count) {
+			printf("\tRegisters modified:");
+			for(i = 0; i < regs_write_count; i++) {
+				printf(" %s", cs_reg_name(handle, regs_write[i]));
+			}
+			printf("\n");
+		}
+	}
+
 	printf("\n");
 }
diff --git a/cstool/cstool_arm64.c b/cstool/cstool_arm64.c
index e91b6a9..e196f03 100644
--- a/cstool/cstool_arm64.c
+++ b/cstool/cstool_arm64.c
@@ -12,7 +12,9 @@
 {
 	cs_arm64 *arm64;
 	int i;
-
+	cs_regs regs_read, regs_write;
+	uint8_t regs_read_count, regs_write_count;
+	
 	// detail can be NULL if SKIPDATA option is turned ON
 	if (ins->detail == NULL)
 		return;
@@ -72,11 +74,26 @@
 				printf("\t\toperands[%u].type: BARRIER = 0x%x\n", i, op->barrier);
 				break;
 		}
-
+		
+		uint8_t access = op->access;
+		switch(access) {
+			default:
+				break;
+			case CS_AC_READ:
+				printf("\t\toperands[%u].access: READ\n", i);
+				break;
+			case CS_AC_WRITE:
+				printf("\t\toperands[%u].access: WRITE\n", i);
+				break;
+			case CS_AC_READ | CS_AC_WRITE:
+				printf("\t\toperands[%u].access: READ | WRITE\n", i);
+				break;
+		}
+		
 		if (op->shift.type != ARM64_SFT_INVALID &&
-				op->shift.value)
+			op->shift.value)
 			printf("\t\t\tShift: type = %u, value = %u\n",
-					op->shift.type, op->shift.value);
+				   op->shift.type, op->shift.value);
 
 		if (op->ext != ARM64_EXT_INVALID)
 			printf("\t\t\tExt: %u\n", op->ext);
@@ -100,5 +117,26 @@
 	if (arm64->cc)
 		printf("\tCode-condition: %u\n", 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) {
+			printf("\tRegisters read:");
+			for(i = 0; i < regs_read_count; i++) {
+				printf(" %s", cs_reg_name(handle, regs_read[i]));
+			}
+			printf("\n");
+		}
+		
+		if (regs_write_count) {
+			printf("\tRegisters modified:");
+			for(i = 0; i < regs_write_count; i++) {
+				printf(" %s", cs_reg_name(handle, regs_write[i]));
+			}
+			printf("\n");
+		}
+	}
+	
 	printf("\n");
 }
diff --git a/cstool/cstool_m68k.c b/cstool/cstool_m68k.c
new file mode 100644
index 0000000..ea09754
--- /dev/null
+++ b/cstool/cstool_m68k.c
@@ -0,0 +1,123 @@
+//
+//  cstool_m68k.c
+//  
+//
+//  Created by YUHANG TANG on 26/10/16.
+//
+//
+
+#include <stdio.h>
+#include <capstone/capstone.h>
+
+void print_string_hex(char *comment, unsigned char *str, size_t len);
+
+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(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);
+		printf("\treading from reg: %s\n", 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);
+		printf("\twriting to reg:   %s\n", reg_name);
+	}
+}
+
+void print_insn_detail_m68k(csh handle, cs_insn *ins)
+{
+	cs_m68k* m68k;
+	cs_detail* detail;
+	int i;
+
+	// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+	if (ins->detail == NULL)
+		return;
+
+	detail = ins->detail;
+	m68k = &detail->m68k;
+	if (m68k->op_count)
+		printf("\top_count: %u\n", m68k->op_count);
+
+	print_read_write_regs(detail, handle);
+
+	printf("\tgroups_count: %u\n", 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:
+				printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+				break;
+			case M68K_OP_IMM:
+				printf("\t\toperands[%u].type: IMM = 0x%x\n", i, (int)op->imm);
+				break;
+			case M68K_OP_MEM:
+				printf("\t\toperands[%u].type: MEM\n", i);
+				if (op->mem.base_reg != M68K_REG_INVALID)
+					printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+							i, cs_reg_name(handle, op->mem.base_reg));
+				if (op->mem.index_reg != M68K_REG_INVALID) {
+					printf("\t\t\toperands[%u].mem.index: REG = %s\n",
+							i, cs_reg_name(handle, op->mem.index_reg));
+					printf("\t\t\toperands[%u].mem.index: size = %c\n",
+							i, op->mem.index_size ? 'l' : 'w');
+				}
+				if (op->mem.disp != 0)
+					printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
+				if (op->mem.scale != 0)
+					printf("\t\t\toperands[%u].mem.scale: %d\n", i, op->mem.scale);
+
+				printf("\t\taddress mode: %s\n", s_addressing_modes[op->address_mode]);
+				break;
+			case M68K_OP_FP_SINGLE:
+				printf("\t\toperands[%u].type: FP_SINGLE\n", i);
+				printf("\t\t\toperands[%u].simm: %f\n", i, op->simm);
+				break;
+			case M68K_OP_FP_DOUBLE:
+				printf("\t\toperands[%u].type: FP_DOUBLE\n", i);
+				printf("\t\t\toperands[%u].dimm: %lf\n", i, op->dimm);
+				break;
+		}
+	}
+
+	printf("\n");
+}
+
diff --git a/cstool/cstool_mips.c b/cstool/cstool_mips.c
index 8e5d139..9706640 100644
--- a/cstool/cstool_mips.c
+++ b/cstool/cstool_mips.c
@@ -34,9 +34,9 @@
 				break;
 			case MIPS_OP_MEM:
 				printf("\t\toperands[%u].type: MEM\n", i);
-				if (op->mem.base != X86_REG_INVALID)
+				if (op->mem.base != MIPS_REG_INVALID)
 					printf("\t\t\toperands[%u].mem.base: REG = %s\n",
-							i, cs_reg_name(handle, op->mem.base));
+						   i, cs_reg_name(handle, op->mem.base));
 				if (op->mem.disp != 0)
 					printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp);
 
diff --git a/cstool/cstool_x86.c b/cstool/cstool_x86.c
index 36c1756..b22a8c6 100644
--- a/cstool/cstool_x86.c
+++ b/cstool/cstool_x86.c
@@ -1,4 +1,3 @@
-/* Second-Best Disassembler Engine */
 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
 
 #include <stdio.h>
@@ -8,11 +7,113 @@
 
 void print_string_hex(char *comment, unsigned char *str, size_t len);
 
+static 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_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";
+	}
+}
+
 void print_insn_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;
+	
 	// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
 	if (ins->detail == NULL)
 		return;
@@ -20,11 +121,8 @@
 	x86 = &(ins->detail->x86);
 
 	print_string_hex("\tPrefix:", x86->prefix, 4);
-
 	print_string_hex("\tOpcode:", x86->opcode, 4);
-
 	printf("\trex: 0x%x\n", x86->rex);
-
 	printf("\taddr_size: %u\n", x86->addr_size);
 	printf("\tmodrm: 0x%x\n", x86->modrm);
 	printf("\tdisp: 0x%x\n", x86->disp);
@@ -40,6 +138,11 @@
 			printf("\t\tsib_scale: %d\n", x86->sib_scale);
 	}
 
+	// XOP code condition
+	if (x86->xop_cc != X86_XOP_CC_INVALID) {
+		printf("\txop_cc: %u\n", x86->xop_cc);
+	}
+
 	// SSE code condition
 	if (x86->sse_cc != X86_SSE_CC_INVALID) {
 		printf("\tsse_cc: %u\n", x86->sse_cc);
@@ -60,6 +163,7 @@
 		printf("\tavx_rm: %u\n", x86->avx_rm);
 	}
 
+	// Print out all immediate operands
 	count = cs_op_count(ud, ins, X86_OP_IMM);
 	if (count) {
 		printf("\timm_count: %u\n", count);
@@ -71,6 +175,8 @@
 
 	if (x86->op_count)
 		printf("\top_count: %u\n", x86->op_count);
+
+	// Print out all operands
 	for (i = 0; i < x86->op_count; i++) {
 		cs_x86_op *op = &(x86->operands[i]);
 
@@ -107,6 +213,50 @@
 			printf("\t\toperands[%u].avx_zero_opmask: TRUE\n", i);
 
 		printf("\t\toperands[%u].size: %u\n", i, op->size);
+
+		switch(op->access) {
+			default:
+				break;
+			case CS_AC_READ:
+				printf("\t\toperands[%u].access: READ\n", i);
+				break;
+			case CS_AC_WRITE:
+				printf("\t\toperands[%u].access: WRITE\n", i);
+				break;
+			case CS_AC_READ | CS_AC_WRITE:
+				printf("\t\toperands[%u].access: READ | WRITE\n", i);
+				break;
+		}
+	}
+
+	// Print out all registers accessed by this instruction (either implicit or explicit)
+	if (!cs_regs_access(ud, ins,
+						regs_read, &regs_read_count,
+						regs_write, &regs_write_count)) {
+		if (regs_read_count) {
+			printf("\tRegisters read:");
+			for(i = 0; i < regs_read_count; i++) {
+				printf(" %s", cs_reg_name(ud, regs_read[i]));
+			}
+			printf("\n");
+		}
+
+		if (regs_write_count) {
+			printf("\tRegisters modified:");
+			for(i = 0; i < regs_write_count; i++) {
+				printf(" %s", cs_reg_name(ud, regs_write[i]));
+			}
+			printf("\n");
+		}
+	}
+
+	if (x86->eflags) {
+		printf("\tEFLAGS:");
+		for(i = 0; i <= 45; i++)
+			if (x86->eflags & ((uint64_t)1 << i)) {
+				printf(" %s", get_eflag_name((uint64_t)1 << i));
+			}
+		printf("\n");
 	}
 
 	printf("\n");