x86: fix SHR, SHL, SAR insn when second op is 1 (Intel syntax). reported by Edgar Barbosa
diff --git a/arch/X86/X86IntelInstPrinter.c b/arch/X86/X86IntelInstPrinter.c
index cec137c..5dd0caa 100644
--- a/arch/X86/X86IntelInstPrinter.c
+++ b/arch/X86/X86IntelInstPrinter.c
@@ -165,8 +165,9 @@
 }
 
 // get the first op from the asm buffer
+// return False if there is no op. On True, put fist op in @firstop
 // NOTE: make sure firstop is big enough to contain the resulted string
-static void get_first_op(char *buffer, char *firstop)
+static bool get_first_op(char *buffer, char *firstop)
 {
 	char *tab = strchr(buffer, '\t');
 	if (tab) {
@@ -176,8 +177,28 @@
 			firstop[comma - tab - 1] = '\0';
 		} else
 			strcpy(firstop, tab + 1);
+
+		return true;
 	} else	// no op
-		firstop[0] = '\0';
+		return false;
+}
+
+// hacky: get mnem string from buffer if this insn has only 1 operand
+// return mnem if True, or False if above condition was not satisfied
+// NOTE: make sure mnem is big enough to contain the resulted string
+static bool get_mnem1(char *buffer, char *mnem)
+{
+	if (strchr(buffer, ','))
+		return false;
+
+	char *tab = strchr(buffer, '\t');
+	if (!tab)
+		return false;
+
+	memcpy(mnem, buffer, tab - buffer);
+	mnem[tab - buffer + 1] = '\0';
+
+	return true;
 }
 
 static bool printAliasInstr(MCInst *MI, SStream *OS);
@@ -202,23 +223,37 @@
 	} else
 		printInstruction(MI, O);
 
-	// first op can be embedded in the asm by llvm.
-	// so we have to handle that case to not miss the first op.
-	char firstop[128];
-	get_first_op(O->buffer, firstop);
-	char *acc_regs[] = {"rax", "eax", "ax", "al", NULL};
-	if (firstop[0] != 0 && str_in_list(acc_regs, firstop)) {
-		// firstop is a register
-		if (MI->pub_insn.x86.operands[0].type != X86_OP_INVALID &&
-				MI->pub_insn.x86.operands[0].type != X86_OP_REG) {
-			int i;
-			for (i = MI->pub_insn.x86.op_count; i > 0; i--) {
-				memcpy(&(MI->pub_insn.x86.operands[i]), &(MI->pub_insn.x86.operands[i - 1]),
-						sizeof(MI->pub_insn.x86.operands[0]));
-			}
-			MI->pub_insn.x86.operands[0].type = X86_OP_REG;
-			MI->pub_insn.x86.operands[0].reg = x86_map_regname(firstop);
+	// currently LLVM presents "shr reg, 1" as "shr reg"
+	// until that is fixed, we need this hack
+	char tmp[128];
+	if (get_mnem1(O->buffer, tmp)) {
+		char *mnems[] = {"shr", "shl", "sar", NULL};
+		if (str_in_list(mnems, tmp)) {
+			// this insn needs to have op "1"
+			strcat(O->buffer, ", 1");
+			MI->pub_insn.x86.operands[1].type = X86_OP_IMM;
+			MI->pub_insn.x86.operands[1].imm = 1;
 			MI->pub_insn.x86.op_count++;
+
+			return;
+		}
+	}
+
+	if (get_first_op(O->buffer, tmp)) {
+		char *acc_regs[] = {"rax", "eax", "ax", "al", NULL};
+		if (tmp[0] != 0 && str_in_list(acc_regs, tmp)) {
+			// tmp is a register
+			if (MI->pub_insn.x86.operands[0].type != X86_OP_INVALID &&
+					MI->pub_insn.x86.operands[0].type != X86_OP_REG) {
+				int i;
+				for (i = MI->pub_insn.x86.op_count; i > 0; i--) {
+					memcpy(&(MI->pub_insn.x86.operands[i]), &(MI->pub_insn.x86.operands[i - 1]),
+							sizeof(MI->pub_insn.x86.operands[0]));
+				}
+				MI->pub_insn.x86.operands[0].type = X86_OP_REG;
+				MI->pub_insn.x86.operands[0].reg = x86_map_regname(tmp);
+				MI->pub_insn.x86.op_count++;
+			}
 		}
 	}
 }