Merge branch 'master' of https://github.com/danghvu/capstone into autogen
diff --git a/Makefile b/Makefile
index b8088df..7740893 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@
 
 LIBNAME = capstone
 LIBOBJ =
-LIBOBJ += cs.o asprintf.o utils.o SStream.o MCInstrDesc.o MCRegisterInfo.o
+LIBOBJ += cs.o utils.o SStream.o MCInstrDesc.o MCRegisterInfo.o
 LIBOBJ += arch/ARM/ARMDisassembler.o arch/ARM/ARMInstPrinter.o arch/ARM/mapping.o
 LIBOBJ += arch/X86/X86DisassemblerDecoder.o arch/X86/X86Disassembler.o arch/X86/X86IntelInstPrinter.o arch/X86/X86ATTInstPrinter.o arch/X86/mapping.o
 LIBOBJ += arch/Mips/MipsDisassembler.o arch/Mips/MipsInstPrinter.o arch/Mips/mapping.o
diff --git a/arch/AArch64/AArch64BaseInfo.c b/arch/AArch64/AArch64BaseInfo.c
index bbed5a8..1b9ead0 100644
--- a/arch/AArch64/AArch64BaseInfo.c
+++ b/arch/AArch64/AArch64BaseInfo.c
@@ -14,9 +14,9 @@
 /* Capstone Disassembler Engine */
 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
 
-#include "../../asprintf.h"
 #include "../../utils.h"
 
+#include <stdio.h>
 #include <stdlib.h>
 
 #include "AArch64BaseInfo.h"
@@ -568,21 +568,23 @@
 	{"ich_lr15_el2", A64SysReg_ICH_LR15_EL2}
 };
 
-// NOTE: caller must free() the result itself
-char *SysRegMapper_toString(SysRegMapper *S, uint32_t Bits, bool *Valid)
+// result must be a big enough buffer: 128 bytes is more than enough
+void SysRegMapper_toString(SysRegMapper *S, uint32_t Bits, bool *Valid, char *result)
 {
 	unsigned i;
 	for (i = 0; i < ARR_SIZE(SysRegPairs); ++i) {
 		if (SysRegPairs[i].Value == Bits) {
 			*Valid = true;
-			return strdup(SysRegPairs[i].Name);
+			strcpy(result, SysRegPairs[i].Name);
+			return;
 		}
 	}
 
 	for (i = 0; i < S->NumInstPairs; ++i) {
 		if (S->InstPairs[i].Value == Bits) {
 			*Valid = true;
-			return strdup(S->InstPairs[i].Name);
+			strcpy(result, S->InstPairs[i].Name);
+			return;
 		}
 	}
 
@@ -596,31 +598,27 @@
 	// name.
 	if (Op0 != 3 || (CRn != 11 && CRn != 15)) {
 		*Valid = false;
-		return NULL;
+		return;
 	}
 
 	//assert(Op0 == 3 && (CRn == 11 || CRn == 15) && "Invalid generic sysreg");
 
 	*Valid = true;
 
-	//return "s3_" + utostr(Op1) + "_c" + utostr(CRn) + "_c" + utostr(CRm) + "_" + utostr(Op2);
-
 	char *Op1S, *CRnS, *CRmS, *Op2S;
 	Op1S = utostr(Op1, false);
 	CRnS = utostr(CRn, false);
 	CRmS = utostr(CRm, false);
 	Op2S = utostr(Op2, false);
 
-	char *result;
-	int dummy = asprintf(&result, "s3_%s_c%s_c%s_%s", Op1S, CRnS, CRmS, Op2S);
+	//printf("Op1S: %s, CRnS: %s, CRmS: %s, Op2S: %s\n", Op1S, CRnS, CRmS, Op2S);
+	int dummy = sprintf(result, "s3_%s_c%s_c%s_%s", Op1S, CRnS, CRmS, Op2S);
 	(void)dummy;
 
 	free(Op1S);
 	free(CRnS);
 	free(CRmS);
 	free(Op2S);
-
-	return result;
 }
 
 static NamedImmMapper_Mapping TLBIPairs[] = {
diff --git a/arch/AArch64/AArch64BaseInfo.h b/arch/AArch64/AArch64BaseInfo.h
index d7a4504..5f527d0 100644
--- a/arch/AArch64/AArch64BaseInfo.h
+++ b/arch/AArch64/AArch64BaseInfo.h
@@ -858,6 +858,6 @@
 
 bool NamedImmMapper_validImm(NamedImmMapper *N, uint32_t Value);
 
-char *SysRegMapper_toString(SysRegMapper *S, uint32_t Bits, bool *Valid);
+void SysRegMapper_toString(SysRegMapper *S, uint32_t Bits, bool *Valid, char *result);
 
 #endif
diff --git a/arch/AArch64/AArch64Disassembler.c b/arch/AArch64/AArch64Disassembler.c
index e9e883d..e849050 100644
--- a/arch/AArch64/AArch64Disassembler.c
+++ b/arch/AArch64/AArch64Disassembler.c
@@ -772,8 +772,8 @@
 		void *Decoder)
 {
 	bool ValidNamed;
-	char *str = SysRegMapper_toString(Mapper, Val, &ValidNamed);
-	free(str);
+	char result[128];
+	SysRegMapper_toString(Mapper, Val, &ValidNamed, result);
 
 	MCInst_addOperand(Inst, MCOperand_CreateImm(Val));
 
diff --git a/arch/AArch64/AArch64GenAsmWriter.inc b/arch/AArch64/AArch64GenAsmWriter.inc
index 8987188..df707f8 100644
--- a/arch/AArch64/AArch64GenAsmWriter.inc
+++ b/arch/AArch64/AArch64GenAsmWriter.inc
@@ -3729,7 +3729,7 @@
   uint64_t Bits1 = OpInfo[MCInst_getOpcode(MI)];
   uint64_t Bits2 = OpInfo2[MCInst_getOpcode(MI)];
   uint64_t Bits = (Bits2 << 32) | Bits1;
-  SStream_concat(O, AsmStrs+(Bits & 4095)-1);
+  SStream_concat(O, "%s",AsmStrs+(Bits & 4095)-1);
 
   // printf("Frag-0 : %lu\n", (Bits >> 12) & 15);
   // Fragment 0 encoded into 4 bits for 15 unique commands.
diff --git a/arch/AArch64/AArch64InstPrinter.c b/arch/AArch64/AArch64InstPrinter.c
index 1bdc14d..dca077a 100644
--- a/arch/AArch64/AArch64InstPrinter.c
+++ b/arch/AArch64/AArch64InstPrinter.c
@@ -372,14 +372,15 @@
 static void printSysRegOperand(SysRegMapper *Mapper,
 		MCInst *MI, unsigned OpNum, SStream *O)
 {
+	bool ValidName;
+	char Name[128];
+
 	MCOperand *MO = MCInst_getOperand(MI, OpNum);
 
-	bool ValidName;
-	char *Name = SysRegMapper_toString(Mapper, MCOperand_getImm(MO), &ValidName);
+	SysRegMapper_toString(Mapper, MCOperand_getImm(MO), &ValidName, Name);
 	if (ValidName) {
 		SStream_concat(O, Name);
 	}
-	free(Name);
 }
 
 #define GET_REGINFO_ENUM
diff --git a/arch/AArch64/mapping.c b/arch/AArch64/mapping.c
index 895d2a2..e956044 100644
--- a/arch/AArch64/mapping.c
+++ b/arch/AArch64/mapping.c
@@ -1884,6 +1884,17 @@
 		// call cs_reg_write() with handle = 1 to pass handle check
 		// we only need to find if this insn modifies ARM64_REG_NZCV
 		insn->arm64.update_flags = cs_reg_write(1, insn, ARM64_REG_NZCV);
+
+		if (insns[i].branch || insns[i].indirect_branch) {
+			// this insn also belongs to JUMP group
+			int j;
+			for (j = 0; j < ARR_SIZE(insns[i].groups); j++) {
+				if (insn->groups[j] == 0) {
+					insn->groups[j] = ARM64_GRP_JUMP;
+					break;
+				}
+			}
+		}
 	}
 }
 
diff --git a/arch/ARM/ARMDisassembler.c b/arch/ARM/ARMDisassembler.c
index a008a47..22500a8 100644
--- a/arch/ARM/ARMDisassembler.c
+++ b/arch/ARM/ARMDisassembler.c
@@ -22,6 +22,7 @@
 #include "../../MCRegisterInfo.h"
 #include "../../LEB128.h"
 #include "../../MCDisassembler.h"
+#include "../../cs_priv.h"
 
 #include "ARMDisassembler.h"
 
@@ -40,13 +41,7 @@
 #define GET_INSTRINFO_ENUM
 #include "ARMGenInstrInfo.inc"
 
-typedef struct ITStatus {
-	//std_vector<unsigned char> ITStates;
-	unsigned char ITStates[128];	// FIXME
-	unsigned int size;
-} ITStatus;
-
-static bool ITStatus_push_back(ITStatus *it, char v)
+static bool ITStatus_push_back(ARM_ITStatus *it, char v)
 {
 	it->ITStates[it->size] = v;
 	it->size++;
@@ -55,14 +50,14 @@
 }
 
 // Returns true if the current instruction is in an IT block
-static bool ITStatus_instrInITBlock(ITStatus *it)
+static bool ITStatus_instrInITBlock(ARM_ITStatus *it)
 {
 	//return !ITStates.empty();
 	return (it->size > 0);
 }
 
 // Returns true if current instruction is the last instruction in an IT block
-static bool ITStatus_instrLastInITBlock(ITStatus *it)
+static bool ITStatus_instrLastInITBlock(ARM_ITStatus *it)
 {
 	return (it->size == 1);
 }
@@ -70,7 +65,7 @@
 // Handles the condition code status of instructions in IT blocks
 
 // Returns the condition code for instruction in IT block
-static unsigned ITStatus_getITCC(ITStatus *it)
+static unsigned ITStatus_getITCC(ARM_ITStatus *it)
 {
 	unsigned CC = ARMCC_AL;
 	if (ITStatus_instrInITBlock(it))
@@ -80,7 +75,7 @@
 }
 
 // Advances the IT block state to the next T or E
-static void ITStatus_advanceITState(ITStatus *it)
+static void ITStatus_advanceITState(ARM_ITStatus *it)
 {
 	//ITStates.pop_back();
 	it->size--;
@@ -89,7 +84,7 @@
 // Called when decoding an IT instruction. Sets the IT state for the following
 // instructions that for the IT block. Firstcond and Mask correspond to the 
 // fields in the IT instruction encoding.
-static void ITStatus_setITState(ITStatus *it, char Firstcond, char Mask)
+static void ITStatus_setITState(ARM_ITStatus *it, char Firstcond, char Mask)
 {
 	// (3 - the number of trailing zeros) is the number of then / else.
 	unsigned CondBit0 = Firstcond & 1;
@@ -110,9 +105,6 @@
 
 /// ThumbDisassembler - Thumb disassembler for all Thumb platforms.
 
-// FIXME: make this ITBlock private for each Disassembler handle
-static ITStatus ITBlock;
-
 static bool Check(DecodeStatus *Out, DecodeStatus In)
 {
 	switch (In) {
@@ -423,12 +415,12 @@
 			0);
 }
 
-static DecodeStatus _ARM_getInstruction(MCInst *MI, unsigned char *code, size_t code_len,
+static DecodeStatus _ARM_getInstruction(cs_struct *ud, MCInst *MI, unsigned char *code, size_t code_len,
 		uint16_t *Size, size_t Address)
 {
 	uint8_t bytes[4];
 
-	ITBlock.size = 0;
+	ud->ITBlock.size = 0;
 
 	//assert(!(STI.getFeatureBits() & ARM_ModeThumb) &&
 	//       "Asked to disassemble an ARM instruction but Subtarget is in Thumb mode!");
@@ -547,7 +539,7 @@
 // encoding, but rather get their predicates from IT context.  We need
 // to fix up the predicate operands using this context information as a
 // post-pass.
-static DecodeStatus AddThumbPredicate(MCInst *MI)
+static DecodeStatus AddThumbPredicate(cs_struct *ud, MCInst *MI)
 {
 	DecodeStatus S = MCDisassembler_Success;
 
@@ -566,7 +558,7 @@
 		case ARM_tSETEND:
 			// Some instructions (mostly conditional branches) are not
 			// allowed in IT blocks.
-			if (ITStatus_instrInITBlock(&ITBlock))
+			if (ITStatus_instrInITBlock(&(ud->ITBlock)))
 				S = MCDisassembler_SoftFail;
 			else
 				return MCDisassembler_Success;
@@ -578,7 +570,7 @@
 			// Some instructions (mostly unconditional branches) can
 			// only appears at the end of, or outside of, an IT.
 			//if (ITBlock.instrInITBlock() && !ITBlock.instrLastInITBlock())
-			if (ITStatus_instrInITBlock(&ITBlock) && !ITStatus_instrLastInITBlock(&ITBlock))
+			if (ITStatus_instrInITBlock(&(ud->ITBlock)) && !ITStatus_instrLastInITBlock(&(ud->ITBlock)))
 				S = MCDisassembler_SoftFail;
 			break;
 		default:
@@ -588,11 +580,11 @@
 	// If we're in an IT block, base the predicate on that.  Otherwise,
 	// assume a predicate of AL.
 	unsigned CC;
-	CC = ITStatus_getITCC(&ITBlock);
+	CC = ITStatus_getITCC(&(ud->ITBlock));
 	if (CC == 0xF) 
 		CC = ARMCC_AL;
-	if (ITStatus_instrInITBlock(&ITBlock))
-		ITStatus_advanceITState(&ITBlock);
+	if (ITStatus_instrInITBlock(&(ud->ITBlock)))
+		ITStatus_advanceITState(&(ud->ITBlock));
 
 	MCOperandInfo *OpInfo = ARMInsts[MCInst_getOpcode(MI)].OpInfo;
 	unsigned short NumOps = ARMInsts[MCInst_getOpcode(MI)].NumOperands;
@@ -623,12 +615,12 @@
 // mode, the auto-generated decoder will give them an (incorrect)
 // predicate operand.  We need to rewrite these operands based on the IT
 // context as a post-pass.
-static void UpdateThumbVFPPredicate(MCInst *MI)
+static void UpdateThumbVFPPredicate(cs_struct *ud, MCInst *MI)
 {
 	unsigned CC;
-	CC = ITStatus_getITCC(&ITBlock);
-	if (ITStatus_instrInITBlock(&ITBlock))
-		ITStatus_advanceITState(&ITBlock);
+	CC = ITStatus_getITCC(&(ud->ITBlock));
+	if (ITStatus_instrInITBlock(&(ud->ITBlock)))
+		ITStatus_advanceITState(&(ud->ITBlock));
 
 	MCOperandInfo *OpInfo = ARMInsts[MCInst_getOpcode(MI)].OpInfo;
 	unsigned short NumOps = ARMInsts[MCInst_getOpcode(MI)].NumOperands;
@@ -645,12 +637,12 @@
 	}
 }
 
-static DecodeStatus _Thumb_getInstruction(MCInst *MI, unsigned char *code, size_t code_len,
+static DecodeStatus _Thumb_getInstruction(cs_struct *ud, MCInst *MI, unsigned char *code, size_t code_len,
 		uint16_t *Size, size_t Address)
 {
 	uint8_t bytes[4];
 
-	ITBlock.size = 0;
+	ud->ITBlock.size = 0;
 
 	//assert((STI.getFeatureBits() & ARM_ModeThumb) &&
 	//       "Asked to disassemble in Thumb mode but Subtarget is in ARM mode!");
@@ -665,7 +657,7 @@
 	DecodeStatus result = decodeInstruction_2(DecoderTableThumb16, MI, insn16, Address, 2);
 	if (result != MCDisassembler_Fail) {
 		*Size = 2;
-		Check(&result, AddThumbPredicate(MI));
+		Check(&result, AddThumbPredicate(ud, MI));
 		return result;
 	}
 
@@ -673,8 +665,8 @@
 	result = decodeInstruction_2(DecoderTableThumbSBit16, MI, insn16, Address, 2);
 	if (result) {
 		*Size = 2;
-		bool InITBlock = ITStatus_instrInITBlock(&ITBlock);
-		Check(&result, AddThumbPredicate(MI));
+		bool InITBlock = ITStatus_instrInITBlock(&(ud->ITBlock));
+		Check(&result, AddThumbPredicate(ud, MI));
 		AddThumb1SBit(MI, InITBlock);
 		return result;
 	}
@@ -686,10 +678,10 @@
 
 		// Nested IT blocks are UNPREDICTABLE.  Must be checked before we add
 		// the Thumb predicate.
-		if (MCInst_getOpcode(MI) == ARM_t2IT && ITStatus_instrInITBlock(&ITBlock))
+		if (MCInst_getOpcode(MI) == ARM_t2IT && ITStatus_instrInITBlock(&(ud->ITBlock)))
 			result = MCDisassembler_SoftFail;
 
-		Check(&result, AddThumbPredicate(MI));
+		Check(&result, AddThumbPredicate(ud, MI));
 
 		// If we find an IT instruction, we need to parse its condition
 		// code and mask operands so that we can apply them correctly
@@ -698,7 +690,7 @@
 
 			unsigned Firstcond = MCOperand_getImm(MCInst_getOperand(MI, 0));
 			unsigned Mask = MCOperand_getImm(MCInst_getOperand(MI, 1));
-			ITStatus_setITState(&ITBlock, Firstcond, Mask);
+			ITStatus_setITState(&(ud->ITBlock), Firstcond, Mask);
 		}
 
 		return result;
@@ -720,8 +712,8 @@
 	result = decodeInstruction_4(DecoderTableThumb32, MI, insn32, Address, 2);
 	if (result != MCDisassembler_Fail) {
 		*Size = 4;
-		bool InITBlock = ITStatus_instrInITBlock(&ITBlock);
-		Check(&result, AddThumbPredicate(MI));
+		bool InITBlock = ITStatus_instrInITBlock(&(ud->ITBlock));
+		Check(&result, AddThumbPredicate(ud, MI));
 		AddThumb1SBit(MI, InITBlock);
 		return result;
 	}
@@ -730,7 +722,7 @@
 	result = decodeInstruction_4(DecoderTableThumb232, MI, insn32, Address, 2);
 	if (result != MCDisassembler_Fail) {
 		*Size = 4;
-		Check(&result, AddThumbPredicate(MI));
+		Check(&result, AddThumbPredicate(ud, MI));
 		return result;
 	}
 
@@ -738,7 +730,7 @@
 	result = decodeInstruction_4(DecoderTableVFP32, MI, insn32, Address, 2);
 	if (result != MCDisassembler_Fail) {
 		*Size = 4;
-		UpdateThumbVFPPredicate(MI);
+		UpdateThumbVFPPredicate(ud, MI);
 		return result;
 	}
 
@@ -747,7 +739,7 @@
 		result = decodeInstruction_4(DecoderTableVFP32, MI, insn32, Address, 2);
 		if (result != MCDisassembler_Fail) {
 			*Size = 4;
-			UpdateThumbVFPPredicate(MI);
+			UpdateThumbVFPPredicate(ud, MI);
 			return result;
 		}
 	}
@@ -764,7 +756,7 @@
 		result = decodeInstruction_4(DecoderTableNEONDup32, MI, insn32, Address, 2);
 		if (result != MCDisassembler_Fail) {
 			*Size = 4;
-			Check(&result, AddThumbPredicate(MI));
+			Check(&result, AddThumbPredicate(ud, MI));
 			return result;
 		}
 	}
@@ -777,7 +769,7 @@
 		result = decodeInstruction_4(DecoderTableNEONLoadStore32, MI, NEONLdStInsn, Address, 2);
 		if (result != MCDisassembler_Fail) {
 			*Size = 4;
-			Check(&result, AddThumbPredicate(MI));
+			Check(&result, AddThumbPredicate(ud, MI));
 			return result;
 		}
 	}
@@ -791,7 +783,7 @@
 		result = decodeInstruction_4(DecoderTableNEONData32, MI, NEONDataInsn, Address, 2);
 		if (result != MCDisassembler_Fail) {
 			*Size = 4;
-			Check(&result, AddThumbPredicate(MI));
+			Check(&result, AddThumbPredicate(ud, MI));
 			return result;
 		}
 	}
@@ -825,7 +817,7 @@
 bool Thumb_getInstruction(csh ud, unsigned char *code, size_t code_len, MCInst *instr,
 		uint16_t *size, size_t address, void *info)
 {
-	DecodeStatus status = _Thumb_getInstruction(instr, code, code_len, size, address);
+	DecodeStatus status = _Thumb_getInstruction((cs_struct *)ud, instr, code, code_len, size, address);
 
 	//return status == MCDisassembler_Success;
 	return status != MCDisassembler_Fail;
@@ -834,7 +826,7 @@
 bool ARM_getInstruction(csh ud, unsigned char *code, size_t code_len, MCInst *instr,
 		uint16_t *size, size_t address, void *info)
 {
-	DecodeStatus status = _ARM_getInstruction(instr, code, code_len, size, address);
+	DecodeStatus status = _ARM_getInstruction((cs_struct *)ud, instr, code, code_len, size, address);
 
 	//return status == MCDisassembler_Success;
 	return status != MCDisassembler_Fail;
diff --git a/arch/ARM/ARMGenAsmWriter.inc b/arch/ARM/ARMGenAsmWriter.inc
index 3e28452..2bfb39d 100644
--- a/arch/ARM/ARMGenAsmWriter.inc
+++ b/arch/ARM/ARMGenAsmWriter.inc
@@ -6114,7 +6114,7 @@
   uint64_t Bits2 = OpInfo2[MCInst_getOpcode(MI)];
   uint64_t Bits = (Bits2 << 32) | Bits1;
   //assert(Bits != 0 && "Cannot print this instruction.");
-  SStream_concat(O, AsmStrs+(Bits & 4095)-1);
+  SStream_concat(O, "%s", AsmStrs+(Bits & 4095)-1);
 
   //printf("Frag-0: %lu\n", (Bits >> 12) & 31);
   // Fragment 0 encoded into 5 bits for 29 unique commands.
diff --git a/arch/ARM/mapping.c b/arch/ARM/mapping.c
index 1641507..a7b8595 100644
--- a/arch/ARM/mapping.c
+++ b/arch/ARM/mapping.c
@@ -2306,6 +2306,17 @@
 		memcpy(insn->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
 		memcpy(insn->groups, insns[i].groups, sizeof(insns[i].groups));
 		insn->arm.update_flags = cs_reg_write(1, insn, ARM_REG_CPSR);
+
+		if (insns[i].branch || insns[i].indirect_branch) {
+			// this insn also belongs to JUMP group
+			int j;
+			for (j = 0; j < ARR_SIZE(insns[i].groups); j++) {
+				if (insn->groups[j] == 0) {
+					insn->groups[j] = ARM_GRP_JUMP;
+					break;
+				}
+			}
+		}
 	}
 }
 
diff --git a/arch/Mips/MipsGenAsmWriter.inc b/arch/Mips/MipsGenAsmWriter.inc
index 42e2e84..fe1b836 100644
--- a/arch/Mips/MipsGenAsmWriter.inc
+++ b/arch/Mips/MipsGenAsmWriter.inc
@@ -3696,7 +3696,7 @@
   uint64_t Bits2 = OpInfo2[MCInst_getOpcode(MI)];
   uint64_t Bits = (Bits2 << 32) | Bits1;
   //assert(Bits != 0 && "Cannot print this instruction.");
-  SStream_concat(O, AsmStrs+(Bits & 8191)-1);
+  SStream_concat(O, "%s", AsmStrs+(Bits & 8191)-1);
 
   // Fragment 0 encoded into 3 bits for 6 unique commands.
   //printf("\nFrag-0: %llu\n", (Bits >> 13) & 7);
diff --git a/arch/Mips/mapping.c b/arch/Mips/mapping.c
index fe0872b..8127c34 100644
--- a/arch/Mips/mapping.c
+++ b/arch/Mips/mapping.c
@@ -1390,6 +1390,17 @@
 			memcpy(insn->regs_write, alias_insns[i].regs_mod, sizeof(alias_insns[i].regs_mod));
 			memcpy(insn->groups, alias_insns[i].groups, sizeof(alias_insns[i].groups));
 
+			if (insns[i].branch || insns[i].indirect_branch) {
+				// this insn also belongs to JUMP group
+				int j;
+				for (j = 0; j < ARR_SIZE(insns[i].groups); j++) {
+					if (insn->groups[j] == 0) {
+						insn->groups[j] = MIPS_GRP_JUMP;
+						break;
+					}
+				}
+			}
+
 			return;
 		}
 	}
@@ -1400,6 +1411,17 @@
 		memcpy(insn->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use));
 		memcpy(insn->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
 		memcpy(insn->groups, insns[i].groups, sizeof(insns[i].groups));
+
+		if (insns[i].branch || insns[i].indirect_branch) {
+			// this insn also belongs to JUMP group
+			int j;
+			for (j = 0; j < ARR_SIZE(insns[i].groups); j++) {
+				if (insn->groups[j] == 0) {
+					insn->groups[j] = MIPS_GRP_JUMP;
+					break;
+				}
+			}
+		}
 	}
 }
 
diff --git a/arch/X86/X86ATTInstPrinter.c b/arch/X86/X86ATTInstPrinter.c
index 285d5e6..f604dc8 100644
--- a/arch/X86/X86ATTInstPrinter.c
+++ b/arch/X86/X86ATTInstPrinter.c
@@ -144,16 +144,34 @@
 
 static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
 {
+	// If this has a segment register, print it.
+	// this is a hack. will fix it later
+	if (MI->pub_insn.x86.segment) {
+		SStream_concat(O, "%%%s:", X86_reg_name(MI->pub_insn.x86.segment));
+	}
+
 	printMemOffset(MI, OpNo, O);
 }
 
 static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
 {
+	// If this has a segment register, print it.
+	// this is a hack. will fix it later
+	if (MI->pub_insn.x86.segment) {
+		SStream_concat(O, "%%%s:", X86_reg_name(MI->pub_insn.x86.segment));
+	}
+
 	printMemOffset(MI, OpNo, O);
 }
 
 static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
 {
+	// If this has a segment register, print it.
+	// this is a hack. will fix it later
+	if (MI->pub_insn.x86.segment) {
+		SStream_concat(O, "%%%s:", X86_reg_name(MI->pub_insn.x86.segment));
+	}
+
 	printMemOffset(MI, OpNo, O);
 }
 
diff --git a/arch/X86/X86GenAsmWriter.inc b/arch/X86/X86GenAsmWriter.inc
index 0c5cca0..a4bf5d4 100644
--- a/arch/X86/X86GenAsmWriter.inc
+++ b/arch/X86/X86GenAsmWriter.inc
@@ -12150,7 +12150,7 @@
   uint64_t Bits2 = OpInfo2[MCInst_getOpcode(MI)];
   uint64_t Bits = (Bits2 << 32) | Bits1;
   //assert(Bits != 0 && "Cannot print this instruction.");
-  SStream_concat(O, AsmStrs+(Bits & 16383)-1);
+  SStream_concat(O, "%s", AsmStrs+(Bits & 16383)-1);
 
   // Fragment 0 encoded into 7 bits for 65 unique commands.
   // printf(">>> frag-0: %lu\n", (Bits >> 14) & 127);
diff --git a/arch/X86/X86GenAsmWriter1.inc b/arch/X86/X86GenAsmWriter1.inc
index a5f4bc8..40f9b91 100644
--- a/arch/X86/X86GenAsmWriter1.inc
+++ b/arch/X86/X86GenAsmWriter1.inc
@@ -11837,7 +11837,7 @@
   uint64_t Bits2 = OpInfo2[MCInst_getOpcode(MI)];
   uint64_t Bits = (Bits2 << 32) | Bits1;
   //assert(Bits != 0 && "Cannot print this instruction.");
-  SStream_concat(O, AsmStrs+(Bits & 16383)-1);
+  SStream_concat(O, "%s", AsmStrs+(Bits & 16383)-1);
 
 
   //	printf("F0: %lu\n", (Bits >> 14) & 63);
diff --git a/arch/X86/X86IntelInstPrinter.c b/arch/X86/X86IntelInstPrinter.c
index 5dd0caa..f9ff156 100644
--- a/arch/X86/X86IntelInstPrinter.c
+++ b/arch/X86/X86IntelInstPrinter.c
@@ -142,12 +142,26 @@
 static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
 {
 	SStream_concat(O, "byte ptr ");
+
+	// If this has a segment register, print it.
+	// this is a hack. will fix it later
+	if (MI->pub_insn.x86.segment) {
+		SStream_concat(O, "%s:", X86_reg_name(MI->pub_insn.x86.segment));
+	}
+
 	printMemOffset(MI, OpNo, O);
 }
 
 static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
 {
 	SStream_concat(O, "word ptr ");
+
+	// If this has a segment register, print it.
+	// this is a hack. will fix it later
+	if (MI->pub_insn.x86.segment) {
+		SStream_concat(O, "%s:", X86_reg_name(MI->pub_insn.x86.segment));
+	}
+
 	printMemOffset(MI, OpNo, O);
 
 }
@@ -155,6 +169,13 @@
 static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
 {
 	SStream_concat(O, "dword ptr ");
+
+	// If this has a segment register, print it.
+	// this is a hack. will fix it later
+	if (MI->pub_insn.x86.segment) {
+		SStream_concat(O, "%s:", X86_reg_name(MI->pub_insn.x86.segment));
+	}
+
 	printMemOffset(MI, OpNo, O);
 }
 
diff --git a/arch/X86/mapping.c b/arch/X86/mapping.c
index 49cbc3a..e6a3c2b 100644
--- a/arch/X86/mapping.c
+++ b/arch/X86/mapping.c
@@ -19,14 +19,14 @@
 // Fill-ins to make the compiler happy.  These constants are never actually
 //   assigned; they are just filler to make an automatically-generated switch
 //   statement work.
-static enum {
+enum {
 	X86_REG_BX_SI = 500,
 	X86_REG_BX_DI = 501,
 	X86_REG_BP_SI = 502,
 	X86_REG_BP_DI = 503,
 	X86_REG_sib   = 504,
 	X86_REG_sib64 = 505
-} __attribute__((unused)) _dummy;
+};
 
 static x86_reg sib_index_map[] = {
 	X86_REG_INVALID,
@@ -6579,6 +6579,17 @@
 		memcpy(insn->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use));
 		memcpy(insn->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
 		memcpy(insn->groups, insns[i].groups, sizeof(insns[i].groups));
+
+		if (insns[i].branch || insns[i].indirect_branch) {
+			// this insn also belongs to JUMP group
+			int j;
+			for (j = 0; j < ARR_SIZE(insns[i].groups); j++) {
+				if (insn->groups[j] == 0) {
+					insn->groups[j] = X86_GRP_JUMP;
+					break;
+				}
+			}
+		}
 	}
 }
 
diff --git a/asprintf.c b/asprintf.c
deleted file mode 100644
index dc3ead8..0000000
--- a/asprintf.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2007, The xFTPd Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *
- *     * Neither the name of the xFTPd Project nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *     * Redistributions of this project or parts of this project in any form
- *       must retain the following aknowledgment:
- *       "This product includes software developed by the xFTPd Project.
- *        http://www.xftpd.com/ - http://www.xftpd.org/"
- *
- * THIS SOFTWARE IS PROVIDED BY THE xFTPd PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE xFTPd PROJECT BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* MinGW lacks asprintf */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-int vasprintf(char **strp, const char *fmt, va_list ap)
-{
-  FILE *dev_null;
-  int arg_len;
-  
-  dev_null = fopen("nul", "w");
-  arg_len = vfprintf(dev_null, fmt, ap);
-  if(arg_len != -1) {
-    *strp = (char *)malloc((size_t)arg_len + 1);
-    arg_len = vsprintf(*strp, fmt, ap);
-  } else *strp = NULL;
-  fclose(dev_null);
-  return arg_len;
-}
-
-int asprintf(char **strp, const char *fmt, ...)
-{
-  int result;
-    
-  va_list args;
-  va_start(args, fmt);
-  result = vasprintf(strp, fmt, args);
-  va_end(args);
-  return result;
-}
diff --git a/asprintf.h b/asprintf.h
deleted file mode 100644
index 0000db1..0000000
--- a/asprintf.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2007, The xFTPd Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *
- *     * Neither the name of the xFTPd Project nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *     * Redistributions of this project or parts of this project in any form
- *       must retain the following aknowledgment:
- *       "This product includes software developed by the xFTPd Project.
- *        http://www.xftpd.com/ - http://www.xftpd.org/"
- *
- * THIS SOFTWARE IS PROVIDED BY THE xFTPd PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE xFTPd PROJECT BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* MinGW lacks asprintf */
-
-#ifndef __ASPRINTF_H
-#define __ASPRINTF_H
-
-#ifdef WIN32
-#include <windows.h>
-#else
-#include <stdarg.h>
-#endif
-
-int asprintf(char **ret, const char *fmt, ...);
-int vasprintf(char **strp, const char *fmt, va_list ap);
-
-#endif /* __ASPRINTF_H */
diff --git a/cs_priv.h b/cs_priv.h
index 32e03f5..07eeda8 100644
--- a/cs_priv.h
+++ b/cs_priv.h
@@ -21,6 +21,12 @@
 
 typedef void (*GetID_t)(cs_insn *insn, unsigned int id);
 
+// for ARM only
+typedef struct ARM_ITStatus {
+	unsigned char ITStates[128];	// FIXME
+	unsigned int size;
+} ARM_ITStatus;
+
 typedef struct cs_struct {
 	cs_arch arch;
 	cs_mode mode;
@@ -35,6 +41,7 @@
 	PostPrinter_t post_printer;
 	bool micro_mips;	// for Mips only
 	cs_err errnum;
+	ARM_ITStatus ITBlock;	// for Arm only
 } cs_struct;
 
 #endif
diff --git a/include/arm.h b/include/arm.h
index b18c565..3151ec8 100644
--- a/include/arm.h
+++ b/include/arm.h
@@ -670,6 +670,8 @@
 	ARM_GRP_CRC,
 	ARM_GRP_DPVFP,
 	ARM_GRP_V6M,
+
+	ARM_GRP_JUMP,	// jump insn (including conditional+direct+indirect jumps)
 	ARM_GRP_MAX,
 } arm_insn_group;
 
diff --git a/include/arm64.h b/include/arm64.h
index 8777897..dca5bfe 100644
--- a/include/arm64.h
+++ b/include/arm64.h
@@ -706,6 +706,7 @@
 	ARM64_INS_NGC,
 	ARM64_INS_NEG,
 
+	ARM64_GRP_JUMP,	// jump insn (including conditional+direct+indirect jumps)
 	ARM64_INS_MAX,
 } arm64_insn;
 
diff --git a/include/mips.h b/include/mips.h
index de65e78..4d05092 100644
--- a/include/mips.h
+++ b/include/mips.h
@@ -669,6 +669,8 @@
 	MIPS_GRP_NONANSFPMATH,
 	MIPS_GRP_NOTFP64BIT,
 	MIPS_GRP_RELOCSTATIC,
+
+	MIPS_GRP_JUMP,	// jump insn (including conditional+direct+indirect jumps)
 	MIPS_GRP_MAX,
 } mips_insn_group;
 
diff --git a/include/x86.h b/include/x86.h
index 7cf8cf5..d397117 100644
--- a/include/x86.h
+++ b/include/x86.h
@@ -1430,6 +1430,8 @@
 	X86_GRP_CDI,
 	X86_GRP_ERI,
 	X86_GRP_TBM,
+
+	X86_GRP_JUMP,	// jump insn (including conditional+direct+indirect jumps)
 	X86_GRP_MAX
 } x86_insn_group;
 
diff --git a/tests/test_arm.c b/tests/test_arm.c
index 9737980..4dbdaf0 100644
--- a/tests/test_arm.c
+++ b/tests/test_arm.c
@@ -152,6 +152,7 @@
 //#define THUMB_CODE "\x00\x47"	// bx r0
 //#define THUMB_CODE "\x01\x47"	// bx r0
 //#define THUMB_CODE "\x02\x47"	// bx r0
+//#define THUMB_CODE "\x0a\xbf" // itet eq
 #define THUMB_CODE "\x70\x47\xeb\x46\x83\xb0\xc9\x68\x1f\xb1"
 #define THUMB_CODE2 "\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
 
diff --git a/tests/test_arm64.c b/tests/test_arm64.c
index 993df04..29d1449 100644
--- a/tests/test_arm64.c
+++ b/tests/test_arm64.c
@@ -133,6 +133,7 @@
 //#define ARM64_CODE "\x20\x00\x02\xab"	// adds	 x0, x1, x2 (alias of adds x0, x1, x2, lsl #0)
 //#define ARM64_CODE "\x20\xf4\x18\x9e"	// fcvtzs	x0, s1, #3
 //#define ARM64_CODE "\x20\xfc\x02\x9b"	// mneg	x0, x1, x2
+//#define ARM64_CODE "\xd0\xb6\x1e\xd5"	// msr	s3_6_c11_c6_6, x16
 #define ARM64_CODE "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b"
 
 	struct platform platforms[] = {
diff --git a/tests/test_detail.c b/tests/test_detail.c
index 51b6178..d196190 100644
--- a/tests/test_detail.c
+++ b/tests/test_detail.c
@@ -46,6 +46,8 @@
 //#define ARM64_CODE "\x20\x74\x0b\xd5"	// dc	zva, x0
 //#define ARM64_CODE "\x20\xfc\x02\x9b"	// mneg	x0, x1, x2
 #define ARM64_CODE "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x10\x20\x21\x1e"
+//#define THUMB_CODE "\x0a\xbf" // itet eq
+//#define X86_CODE32 "\x77\x04"	// ja +6
 
 	struct platform platforms[] = {
 		{
diff --git a/tests/test_x86.c b/tests/test_x86.c
index d1d8298..4d9eb18 100644
--- a/tests/test_x86.c
+++ b/tests/test_x86.c
@@ -113,6 +113,8 @@
 //#define X86_CODE16 "\x67\x00\x18"
 //#define X86_CODE32 "\xd1\xe1"	// shl ecx, 1
 #define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6"
+//#define X86_CODE32 "\x64\xa1\x18\x00\x00\x00"	// mov eax, dword ptr fs:[18]
+//#define X86_CODE32 "\x64\xa3\x00\x00\x00\x00"	// mov [fs:0x0], eax
 
 	struct platform platforms[] = {
 		{