Beispiel #1
0
static bool printSparcAliasInstr(MCInst *MI, SStream *O)
{
	switch (MCInst_getOpcode(MI)) {
		default: return false;
		case SP_JMPLrr:
		case SP_JMPLri:
				 if (MCInst_getNumOperands(MI) != 3)
					 return false;
				 if (!MCOperand_isReg(MCInst_getOperand(MI, 0)))
					 return false;

				 switch (MCOperand_getReg(MCInst_getOperand(MI, 0))) {
					 default: return false;
					 case SP_G0: // jmp $addr | ret | retl
							  if (MCOperand_isImm(MCInst_getOperand(MI, 2)) &&
									MCOperand_getImm(MCInst_getOperand(MI, 2)) == 8) {
								  switch(MCOperand_getReg(MCInst_getOperand(MI, 1))) {
									  default: break;
									  case SP_I7: SStream_concat0(O, "ret"); MCInst_setOpcodePub(MI, SPARC_INS_RET); return true;
									  case SP_O7: SStream_concat0(O, "retl"); MCInst_setOpcodePub(MI, SPARC_INS_RETL); return true;
								  }
							  }

							  SStream_concat0(O, "jmp\t");
							  MCInst_setOpcodePub(MI, SPARC_INS_JMP);
							  printMemOperand(MI, 1, O, NULL);
							  return true;
					 case SP_O7: // call $addr
							  SStream_concat0(O, "call ");
							  MCInst_setOpcodePub(MI, SPARC_INS_CALL);
							  printMemOperand(MI, 1, O, NULL);
							  return true;
				 }
		case SP_V9FCMPS:
		case SP_V9FCMPD:
		case SP_V9FCMPQ:
		case SP_V9FCMPES:
		case SP_V9FCMPED:
		case SP_V9FCMPEQ:
				 if (MI->csh->mode & CS_MODE_V9 || (MCInst_getNumOperands(MI) != 3) ||
						 (!MCOperand_isReg(MCInst_getOperand(MI, 0))) ||
						 (MCOperand_getReg(MCInst_getOperand(MI, 0)) != SP_FCC0))
						 return false;
				 // if V8, skip printing %fcc0.
				 switch(MCInst_getOpcode(MI)) {
					 default:
					 case SP_V9FCMPS:  SStream_concat0(O, "fcmps\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPS); break;
					 case SP_V9FCMPD:  SStream_concat0(O, "fcmpd\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPD); break;
					 case SP_V9FCMPQ:  SStream_concat0(O, "fcmpq\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPQ); break;
					 case SP_V9FCMPES: SStream_concat0(O, "fcmpes\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPES); break;
					 case SP_V9FCMPED: SStream_concat0(O, "fcmped\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPED); break;
					 case SP_V9FCMPEQ: SStream_concat0(O, "fcmpeq\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPEQ); break;
				 }
				 printOperand(MI, 1, O);
				 SStream_concat0(O, ", ");
				 printOperand(MI, 2, O);
				 return true;
	}
}
Beispiel #2
0
void Mips_printInst(MCInst *MI, SStream *O, void *info)
{
	switch (MCInst_getOpcode(MI)) {
		default: break;
		case Mips_RDHWR:
		case Mips_RDHWR64:
			SStream_concat(O, ".set\tpush\n");
			SStream_concat(O, ".set\tmips32r2\n");
			break;
		case Mips_Save16:
			SStream_concat(O, "\tsave\t");
			printSaveRestore(MI, O);
			SStream_concat(O, " # 16 bit inst\n");
			return;
		case Mips_SaveX16:
			SStream_concat(O, "\tsave\t");
			printSaveRestore(MI, O);
			SStream_concat(O, "\n");
			return;
		case Mips_Restore16:
			SStream_concat(O, "\trestore\t");
			printSaveRestore(MI, O);
			SStream_concat(O, " # 16 bit inst\n");
			return;
		case Mips_RestoreX16:
			SStream_concat(O, "\trestore\t");
			printSaveRestore(MI, O);
			SStream_concat(O, "\n");
			return;
	}

	// Try to print any aliases first.
	if (!printAliasInstr(MI, O, info) && !printAlias(MI, O))
		printInstruction(MI, O, NULL);
	else {
		// fixup instruction id due to the change in alias instruction
		char *mnem = cs_strdup(O->buffer);
		char *tab = strchr(mnem, '\t');
		if (tab)
			*tab = '\0';

		// reflect the new insn name (alias) in the opcode
		unsigned id = Mips_map_insn(mnem);
		MCInst_setOpcode(MI, Mips_get_insn_id2(id));
		MCInst_setOpcodePub(MI, id);
		cs_mem_free(mnem);
	}

	switch (MCInst_getOpcode(MI)) {
		default: break;
		case Mips_RDHWR:
		case Mips_RDHWR64:
			SStream_concat(O, "\n.set\tpop");
			break;
	}
}
Beispiel #3
0
void Sparc_printInst(MCInst *MI, SStream *O, void *Info)
{
	char *mnem, *p;
	char instr[64];	// Sparc has no instruction this long

	mnem = printAliasInstr(MI, O, Info);
	if (mnem) {
		// fixup instruction id due to the change in alias instruction
		strncpy(instr, mnem, strlen(mnem));
		instr[strlen(mnem)] = '\0';
		// does this contains hint with a coma?
		p = strchr(instr, ',');
		if (p)
			*p = '\0';	// now instr only has instruction mnemonic
		MCInst_setOpcodePub(MI, Sparc_map_insn(instr));
		switch(MCInst_getOpcode(MI)) {
			case SP_BCOND:
			case SP_BCONDA:
			case SP_BPICCANT:
			case SP_BPICCNT:
			case SP_BPXCCANT:
			case SP_BPXCCNT:
			case SP_TXCCri:
			case SP_TXCCrr:
				if (MI->csh->detail) {
					// skip 'b', 't'
					MI->flat_insn->detail->sparc.cc = Sparc_map_ICC(instr + 1);
					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
				}
				break;
			case SP_BPFCCANT:
			case SP_BPFCCNT:
				if (MI->csh->detail) {
					// skip 'fb'
					MI->flat_insn->detail->sparc.cc = Sparc_map_FCC(instr + 2);
					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
				}
				break;
			case SP_FMOVD_ICC:
			case SP_FMOVD_XCC:
			case SP_FMOVQ_ICC:
			case SP_FMOVQ_XCC:
			case SP_FMOVS_ICC:
			case SP_FMOVS_XCC:
				if (MI->csh->detail) {
					// skip 'fmovd', 'fmovq', 'fmovs'
					MI->flat_insn->detail->sparc.cc = Sparc_map_ICC(instr + 5);
					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
				}
				break;
			case SP_MOVICCri:
			case SP_MOVICCrr:
			case SP_MOVXCCri:
			case SP_MOVXCCrr:
				if (MI->csh->detail) {
					// skip 'mov'
					MI->flat_insn->detail->sparc.cc = Sparc_map_ICC(instr + 3);
					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
				}
				break;
			case SP_V9FMOVD_FCC:
			case SP_V9FMOVQ_FCC:
			case SP_V9FMOVS_FCC:
				if (MI->csh->detail) {
					// skip 'fmovd', 'fmovq', 'fmovs'
					MI->flat_insn->detail->sparc.cc = Sparc_map_FCC(instr + 5);
					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
				}
				break;
			case SP_V9MOVFCCri:
			case SP_V9MOVFCCrr:
				if (MI->csh->detail) {
					// skip 'mov'
					MI->flat_insn->detail->sparc.cc = Sparc_map_FCC(instr + 3);
					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
				}
				break;
			default:
				break;
		}
		cs_mem_free(mnem);
	} else {
		if (!printSparcAliasInstr(MI, O))
			printInstruction(MI, O, NULL);
	}
}
void AArch64_printInst(MCInst *MI, SStream *O, void *Info)
{
	// Check for special encodings and print the canonical alias instead.
	unsigned Opcode = MCInst_getOpcode(MI);
	int LSB;
	int Width;
	char *mnem;

	if (Opcode == AArch64_SYSxt && printSysAlias(MI, O))
		return;

	// SBFM/UBFM should print to a nicer aliased form if possible.
	if (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri ||
			Opcode == AArch64_UBFMXri || Opcode == AArch64_UBFMWri) {
		MCOperand *Op0 = MCInst_getOperand(MI, 0);
		MCOperand *Op1 = MCInst_getOperand(MI, 1);
		MCOperand *Op2 = MCInst_getOperand(MI, 2);
		MCOperand *Op3 = MCInst_getOperand(MI, 3);

		bool IsSigned = (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri);
		bool Is64Bit = (Opcode == AArch64_SBFMXri || Opcode == AArch64_UBFMXri);

		if (MCOperand_isImm(Op2) && MCOperand_getImm(Op2) == 0 && MCOperand_isImm(Op3)) {
			char *AsmMnemonic = NULL;

			switch (MCOperand_getImm(Op3)) {
				default:
					break;
				case 7:
					if (IsSigned)
						AsmMnemonic = "sxtb";
					else if (!Is64Bit)
						AsmMnemonic = "uxtb";
					break;
				case 15:
					if (IsSigned)
						AsmMnemonic = "sxth";
					else if (!Is64Bit)
						AsmMnemonic = "uxth";
					break;
				case 31:
					// *xtw is only valid for signed 64-bit operations.
					if (Is64Bit && IsSigned)
						AsmMnemonic = "sxtw";
					break;
			}

			if (AsmMnemonic) {
				SStream_concat(O, "%s\t%s, %s", AsmMnemonic,
						getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
						getRegisterName(getWRegFromXReg(MCOperand_getReg(Op1)), AArch64_NoRegAltName));

				if (MI->csh->detail) {
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
					MI->flat_insn->detail->arm64.op_count++;
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = getWRegFromXReg(MCOperand_getReg(Op1));
					MI->flat_insn->detail->arm64.op_count++;
				}

				MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic));

				return;
			}
		}

		// All immediate shifts are aliases, implemented using the Bitfield
		// instruction. In all cases the immediate shift amount shift must be in
		// the range 0 to (reg.size -1).
		if (MCOperand_isImm(Op2) && MCOperand_isImm(Op3)) {
			char *AsmMnemonic = NULL;
			int shift = 0;
			int immr = (int)MCOperand_getImm(Op2);
			int imms = (int)MCOperand_getImm(Op3);

			if (Opcode == AArch64_UBFMWri && imms != 0x1F && ((imms + 1) == immr)) {
				AsmMnemonic = "lsl";
				shift = 31 - imms;
			} else if (Opcode == AArch64_UBFMXri && imms != 0x3f &&
					((imms + 1 == immr))) {
				AsmMnemonic = "lsl";
				shift = 63 - imms;
			} else if (Opcode == AArch64_UBFMWri && imms == 0x1f) {
				AsmMnemonic = "lsr";
				shift = immr;
			} else if (Opcode == AArch64_UBFMXri && imms == 0x3f) {
				AsmMnemonic = "lsr";
				shift = immr;
			} else if (Opcode == AArch64_SBFMWri && imms == 0x1f) {
				AsmMnemonic = "asr";
				shift = immr;
			} else if (Opcode == AArch64_SBFMXri && imms == 0x3f) {
				AsmMnemonic = "asr";
				shift = immr;
			}

			if (AsmMnemonic) {
				SStream_concat(O, "%s\t%s, %s, ", AsmMnemonic,
						getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
						getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));

				printInt32Bang(O, shift);

				MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic));

				if (MI->csh->detail) {
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
					MI->flat_insn->detail->arm64.op_count++;
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
					MI->flat_insn->detail->arm64.op_count++;
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = shift;
					MI->flat_insn->detail->arm64.op_count++;
				}

				return;
			}
		}

		// SBFIZ/UBFIZ aliases
		if (MCOperand_getImm(Op2) > MCOperand_getImm(Op3)) {
			SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfiz" : "ubfiz"),
					getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
					getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
			printInt32Bang(O, (int)((Is64Bit ? 64 : 32) - MCOperand_getImm(Op2)));
			SStream_concat0(O, ", ");
			printInt32Bang(O, (int)MCOperand_getImm(Op3) + 1);

			MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfiz" : "ubfiz"));

			if (MI->csh->detail) {
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
				MI->flat_insn->detail->arm64.op_count++;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
				MI->flat_insn->detail->arm64.op_count++;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (Is64Bit ? 64 : 32) - (int)MCOperand_getImm(Op2);
				MI->flat_insn->detail->arm64.op_count++;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)MCOperand_getImm(Op3) + 1;
				MI->flat_insn->detail->arm64.op_count++;
			}

			return;
		}

		// Otherwise SBFX/UBFX is the preferred form
		SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfx" : "ubfx"),
				getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
				getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
		printInt32Bang(O, (int)MCOperand_getImm(Op2));
		SStream_concat0(O, ", ");
		printInt32Bang(O, (int)MCOperand_getImm(Op3) - (int)MCOperand_getImm(Op2) + 1);

		MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfx" : "ubfx"));

		if (MI->csh->detail) {
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
			MI->flat_insn->detail->arm64.op_count++;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
			MI->flat_insn->detail->arm64.op_count++;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)MCOperand_getImm(Op2);
			MI->flat_insn->detail->arm64.op_count++;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)MCOperand_getImm(Op3) - (int)MCOperand_getImm(Op2) + 1;
			MI->flat_insn->detail->arm64.op_count++;
		}

		return;
	}

	if (Opcode == AArch64_BFMXri || Opcode == AArch64_BFMWri) {
		MCOperand *Op0 = MCInst_getOperand(MI, 0); // Op1 == Op0
		MCOperand *Op2 = MCInst_getOperand(MI, 2);
		int ImmR = (int)MCOperand_getImm(MCInst_getOperand(MI, 3));
		int ImmS = (int)MCOperand_getImm(MCInst_getOperand(MI, 4));

		// BFI alias
		if (ImmS < ImmR) {
			int BitWidth = Opcode == AArch64_BFMXri ? 64 : 32;
			LSB = (BitWidth - ImmR) % BitWidth;
			Width = ImmS + 1;

			SStream_concat(O, "bfi\t%s, %s, ",
					getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
					getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName));
			printInt32Bang(O, LSB);
			SStream_concat0(O, ", ");
			printInt32Bang(O, Width);
			MCInst_setOpcodePub(MI, AArch64_map_insn("bfi"));

			if (MI->csh->detail) {
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
				MI->flat_insn->detail->arm64.op_count++;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2);
				MI->flat_insn->detail->arm64.op_count++;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
				MI->flat_insn->detail->arm64.op_count++;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
				MI->flat_insn->detail->arm64.op_count++;
			}

			return;
		}

		LSB = ImmR;
		Width = ImmS - ImmR + 1;
		// Otherwise BFXIL the preferred form
		SStream_concat(O, "bfxil\t%s, %s, ",
				getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
				getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName));
		printInt32Bang(O, LSB);
		SStream_concat0(O, ", ");
		printInt32Bang(O, Width);
		MCInst_setOpcodePub(MI, AArch64_map_insn("bfxil"));

		if (MI->csh->detail) {
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
			MI->flat_insn->detail->arm64.op_count++;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2);
			MI->flat_insn->detail->arm64.op_count++;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
			MI->flat_insn->detail->arm64.op_count++;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
			MI->flat_insn->detail->arm64.op_count++;
		}

		return;
	}

	mnem = printAliasInstr(MI, O, Info);
	if (mnem) {
		MCInst_setOpcodePub(MI, AArch64_map_insn(mnem));
		cs_mem_free(mnem);
	} else {
		printInstruction(MI, O, Info);
	}
}
static bool printSysAlias(MCInst *MI, SStream *O)
{
	// unsigned Opcode = MCInst_getOpcode(MI);
	//assert(Opcode == AArch64_SYSxt && "Invalid opcode for SYS alias!");

	char *Asm = NULL;
	MCOperand *Op1 = MCInst_getOperand(MI, 0);
	MCOperand *Cn = MCInst_getOperand(MI, 1);
	MCOperand *Cm = MCInst_getOperand(MI, 2);
	MCOperand *Op2 = MCInst_getOperand(MI, 3);

	unsigned Op1Val = (unsigned)MCOperand_getImm(Op1);
	unsigned CnVal = (unsigned)MCOperand_getImm(Cn);
	unsigned CmVal = (unsigned)MCOperand_getImm(Cm);
	unsigned Op2Val = (unsigned)MCOperand_getImm(Op2);
	unsigned insn_id = ARM64_INS_INVALID;
	unsigned op_ic = 0, op_dc = 0, op_at = 0, op_tlbi = 0;

	if (CnVal == 7) {
		switch (CmVal) {
			default:
				break;

				// IC aliases
			case 1:
				if (Op1Val == 0 && Op2Val == 0) {
					Asm = "ic\tialluis";
					insn_id = ARM64_INS_IC;
					op_ic = ARM64_IC_IALLUIS;
				}
				break;
			case 5:
				if (Op1Val == 0 && Op2Val == 0) {
					Asm = "ic\tiallu";
					insn_id = ARM64_INS_IC;
					op_ic = ARM64_IC_IALLU;
				} else if (Op1Val == 3 && Op2Val == 1) {
					Asm = "ic\tivau";
					insn_id = ARM64_INS_IC;
					op_ic = ARM64_IC_IVAU;
				}
				break;

				// DC aliases
			case 4:
				if (Op1Val == 3 && Op2Val == 1) {
					Asm = "dc\tzva";
					insn_id = ARM64_INS_DC;
					op_dc = ARM64_DC_ZVA;
				}
				break;
			case 6:
				if (Op1Val == 0 && Op2Val == 1) {
					Asm = "dc\tivac";
					insn_id = ARM64_INS_DC;
					op_dc = ARM64_DC_IVAC;
				}
				if (Op1Val == 0 && Op2Val == 2) {
					Asm = "dc\tisw";
					insn_id = ARM64_INS_DC;
					op_dc = ARM64_DC_ISW;
				}
				break;
			case 10:
				if (Op1Val == 3 && Op2Val == 1) {
					Asm = "dc\tcvac";
					insn_id = ARM64_INS_DC;
					op_dc = ARM64_DC_CVAC;
				} else if (Op1Val == 0 && Op2Val == 2) {
					Asm = "dc\tcsw";
					insn_id = ARM64_INS_DC;
					op_dc = ARM64_DC_CSW;
				}
				break;
			case 11:
				if (Op1Val == 3 && Op2Val == 1) {
					Asm = "dc\tcvau";
					insn_id = ARM64_INS_DC;
					op_dc = ARM64_DC_CVAU;
				}
				break;
			case 14:
				if (Op1Val == 3 && Op2Val == 1) {
					Asm = "dc\tcivac";
					insn_id = ARM64_INS_DC;
					op_dc = ARM64_DC_CIVAC;
				} else if (Op1Val == 0 && Op2Val == 2) {
					Asm = "dc\tcisw";
					insn_id = ARM64_INS_DC;
					op_dc = ARM64_DC_CISW;
				}
				break;

				// AT aliases
			case 8:
				switch (Op1Val) {
					default:
						break;
					case 0:
						switch (Op2Val) {
							default:
								break;
							case 0: Asm = "at\ts1e1r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1R; break;
							case 1: Asm = "at\ts1e1w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1W; break;
							case 2: Asm = "at\ts1e0r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0R; break;
							case 3: Asm = "at\ts1e0w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0W; break;
						}
						break;
					case 4:
						switch (Op2Val) {
							default:
								break;
							case 0: Asm = "at\ts1e2r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E2R; break;
							case 1: Asm = "at\ts1e2w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E2W; break;
							case 4: Asm = "at\ts12e1r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1R; break;
							case 5: Asm = "at\ts12e1w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1W; break;
							case 6: Asm = "at\ts12e0r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0R; break;
							case 7: Asm = "at\ts12e0w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0W; break;
						}
						break;
					case 6:
						switch (Op2Val) {
							default:
								break;
							case 0: Asm = "at\ts1e3r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E3R; break;
							case 1: Asm = "at\ts1e3w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E3W; break;
						}
						break;
				}
				break;
		}
	} else if (CnVal == 8) {
		// TLBI aliases
		switch (CmVal) {
			default:
				break;
			case 3:
				switch (Op1Val) {
					default:
						break;
					case 0:
						switch (Op2Val) {
							default:
								break;
							case 0: Asm = "tlbi\tvmalle1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLE1IS; break;
							case 1: Asm = "tlbi\tvae1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE1IS; break;
							case 2: Asm = "tlbi\taside1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ASIDE1IS; break;
							case 3: Asm = "tlbi\tvaae1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAAE1IS; break;
							case 5: Asm = "tlbi\tvale1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE1IS; break;
							case 7: Asm = "tlbi\tvaale1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAALE1IS; break;
						}
						break;
					case 4:
						switch (Op2Val) {
							default:
								break;
							case 0: Asm = "tlbi\talle2is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE2IS; break;
							case 1: Asm = "tlbi\tvae2is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE2IS; break;
							case 4: Asm = "tlbi\talle1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE1IS; break;
							case 5: Asm = "tlbi\tvale2is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE2IS; break;
							case 6: Asm = "tlbi\tvmalls12e1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLS12E1IS; break;
						}
						break;
					case 6:
						switch (Op2Val) {
							default:
								break;
							case 0: Asm = "tlbi\talle3is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE3IS; break;
							case 1: Asm = "tlbi\tvae3is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE3IS; break;
							case 5: Asm = "tlbi\tvale3is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE3IS; break;
						}
						break;
				}
				break;
			case 0:
				switch (Op1Val) {
					default:
						break;
					case 4:
						switch (Op2Val) {
							default:
								break;
							case 1: Asm = "tlbi\tipas2e1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2E1IS; break;
							case 5: Asm = "tlbi\tipas2le1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2LE1IS; break;
						}
						break;
				}
				break;
			case 4:
				switch (Op1Val) {
					default:
						break;
					case 4:
						switch (Op2Val) {
							default:
								break;
							case 1: Asm = "tlbi\tipas2e1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2E1; break;
							case 5: Asm = "tlbi\tipas2le1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2LE1; break;
						}
						break;
				}
				break;
			case 7:
				switch (Op1Val) {
					default:
						break;
					case 0:
						switch (Op2Val) {
							default:
								break;
							case 0: Asm = "tlbi\tvmalle1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLE1; break;
							case 1: Asm = "tlbi\tvae1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE1; break;
							case 2: Asm = "tlbi\taside1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ASIDE1; break;
							case 3: Asm = "tlbi\tvaae1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAAE1; break;
							case 5: Asm = "tlbi\tvale1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE1; break;
							case 7: Asm = "tlbi\tvaale1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAALE1; break;
						}
						break;
					case 4:
						switch (Op2Val) {
							default:
								break;
							case 0: Asm = "tlbi\talle2"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE2; break;
							case 1: Asm = "tlbi\tvae2"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE2; break;
							case 4: Asm = "tlbi\talle1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE1; break;
							case 5: Asm = "tlbi\tvale2"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE2; break;
							case 6: Asm = "tlbi\tvmalls12e1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLS12E1; break;
						}
						break;
					case 6:
						switch (Op2Val) {
							default:
								break;
							case 0: Asm = "tlbi\talle3"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE3; break;
							case 1: Asm = "tlbi\tvae3"; insn_id = ARM64_INS_TLBI;  op_tlbi = ARM64_TLBI_VAE3; break;
							case 5: Asm = "tlbi\tvale3"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE3; break;
						}
						break;
				}
				break;
		}
	}

	if (Asm) {
		MCInst_setOpcodePub(MI, insn_id);
		SStream_concat0(O, Asm);
		if (MI->csh->detail) {
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = op_ic + op_dc + op_at + op_tlbi;
			MI->flat_insn->detail->arm64.op_count++;
		}

		if (!strstr(Asm, "all")) {
			unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, 4));
			SStream_concat(O, ", %s", getRegisterName(Reg, AArch64_NoRegAltName));
			if (MI->csh->detail) {
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
				MI->flat_insn->detail->arm64.op_count++;
			}
		}
	}

	return Asm != NULL;
}
Beispiel #6
0
void PPC_printInst(MCInst *MI, SStream *O, void *Info)
{
	char *mnem;

	// Check for slwi/srwi mnemonics.
	if (MCInst_getOpcode(MI) == PPC_RLWINM) {
		unsigned char SH = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 2));
		unsigned char MB = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 3));
		unsigned char ME = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 4));
		bool useSubstituteMnemonic = false;

		if (SH <= 31 && MB == 0 && ME == (31-SH)) {
			SStream_concat0(O, "slwi\t");
			MCInst_setOpcodePub(MI, PPC_INS_SLWI);
			useSubstituteMnemonic = true;
		}

		if (SH <= 31 && MB == (32-SH) && ME == 31) {
			SStream_concat0(O, "srwi\t");
			MCInst_setOpcodePub(MI, PPC_INS_SRWI);
			useSubstituteMnemonic = true;
			SH = 32-SH;
		}

		if (useSubstituteMnemonic) {
			printOperand(MI, 0, O);
			SStream_concat0(O, ", ");
			printOperand(MI, 1, O);
			if (SH > HEX_THRESHOLD)
				SStream_concat(O, ", 0x%x", (unsigned int)SH);
			else
				SStream_concat(O, ", %u", (unsigned int)SH);

			if (MI->csh->detail) {
				cs_ppc *ppc = &MI->flat_insn->detail->ppc;

				ppc->operands[ppc->op_count].type = PPC_OP_IMM;
				ppc->operands[ppc->op_count].imm = SH;
				++ppc->op_count;
			}

			return;
		}
	}

	if ((MCInst_getOpcode(MI) == PPC_OR || MCInst_getOpcode(MI) == PPC_OR8) &&
			MCOperand_getReg(MCInst_getOperand(MI, 1)) == MCOperand_getReg(MCInst_getOperand(MI, 2))) {
		SStream_concat0(O, "mr\t");
		MCInst_setOpcodePub(MI, PPC_INS_MR);
		printOperand(MI, 0, O);
		SStream_concat0(O, ", ");
		printOperand(MI, 1, O);
		return;
	}

	if (MCInst_getOpcode(MI) == PPC_RLDICR) {
		unsigned char SH = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 2));
		unsigned char ME = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 3));
		// rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
		if (63-SH == ME) {
			SStream_concat0(O, "sldi\t");
			MCInst_setOpcodePub(MI, PPC_INS_SLDI);
			printOperand(MI, 0, O);
			SStream_concat0(O, ", ");
			printOperand(MI, 1, O);
			if (SH > HEX_THRESHOLD)
				SStream_concat(O, ", 0x%x", (unsigned int)SH);
			else
				SStream_concat(O, ", %u", (unsigned int)SH);

			return;
		}
	}

	if ((MCInst_getOpcode(MI) == PPC_gBC)||(MCInst_getOpcode(MI) == PPC_gBCA)||
			(MCInst_getOpcode(MI) == PPC_gBCL)||(MCInst_getOpcode(MI) == PPC_gBCLA)) {
		int64_t bd = MCOperand_getImm(MCInst_getOperand(MI, 2));
		bd = SignExtend64(bd, 14);
		MCOperand_setImm(MCInst_getOperand(MI, 2),bd);
	}

	if (isBOCTRBranch(MCInst_getOpcode(MI))) {
		if (MCOperand_isImm(MCInst_getOperand(MI,0)))
		{
			int64_t bd = MCOperand_getImm(MCInst_getOperand(MI, 0));
			bd = SignExtend64(bd, 14);
			MCOperand_setImm(MCInst_getOperand(MI, 0),bd);
		}
	}

	if ((MCInst_getOpcode(MI) == PPC_B)||(MCInst_getOpcode(MI) == PPC_BA)||
			(MCInst_getOpcode(MI) == PPC_BL)||(MCInst_getOpcode(MI) == PPC_BLA)) {
		int64_t bd = MCOperand_getImm(MCInst_getOperand(MI, 0));
		bd = SignExtend64(bd, 24);
		MCOperand_setImm(MCInst_getOperand(MI, 0),bd);
	}

	// consider our own alias instructions first
	mnem = printAliasInstrEx(MI, O, Info);
	if (!mnem)
		mnem = printAliasInstr(MI, O, Info);

	if (mnem != NULL) {
		if (strlen(mnem) > 0) {
			struct ppc_alias alias;
			// check to remove the last letter of ('.', '-', '+')
			if (mnem[strlen(mnem) - 1] == '-' || mnem[strlen(mnem) - 1] == '+' || mnem[strlen(mnem) - 1] == '.')
				mnem[strlen(mnem) - 1] = '\0';

			if (PPC_alias_insn(mnem, &alias)) {
				MCInst_setOpcodePub(MI, alias.id);
				if (MI->csh->detail) {
					MI->flat_insn->detail->ppc.bc = (ppc_bc)alias.cc;
				}
			}
		}

		cs_mem_free(mnem);
	} else
		printInstruction(MI, O, NULL);
}
Beispiel #7
0
void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
{
	char *mnem;
	x86_reg reg, reg2;
	int i;

	// Output CALLpcrel32 as "callq" in 64-bit mode.
	// In Intel annotation it's always emitted as "call".
	//
	// TODO: Probably this hack should be redesigned via InstAlias in
	// InstrInfo.td as soon as Requires clause is supported properly
	// for InstAlias.
	if (MI->csh->mode == CS_MODE_64 && MCInst_getOpcode(MI) == X86_CALLpcrel32) {
		SStream_concat0(OS, "callq\t");
		MCInst_setOpcodePub(MI, X86_INS_CALL);
		printPCRelImm(MI, 0, OS);
		return;
	}

	// Try to print any aliases first.
	mnem = printAliasInstr(MI, OS, info);
	if (mnem)
		cs_mem_free(mnem);
	else
		printInstruction(MI, OS, info);

	if (MI->has_imm) {
		// if op_count > 1, then this operand's size is taken from the destination op
		if (MI->flat_insn->detail->x86.op_count > 1) {
			if (MI->flat_insn->id != X86_INS_LCALL && MI->flat_insn->id != X86_INS_LJMP) {
				for (i = 0; i < MI->flat_insn->detail->x86.op_count; i++) {
					if (MI->flat_insn->detail->x86.operands[i].type == X86_OP_IMM)
						MI->flat_insn->detail->x86.operands[i].size =
							MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count - 1].size;
				}
			}
		} else
			MI->flat_insn->detail->x86.operands[0].size = MI->imm_size;
	}

	if (MI->csh->detail) {
        // some instructions need to supply immediate 1 in the first op
        switch(MCInst_getOpcode(MI)) {
            default:
                break;
            case X86_SHL8r1:
            case X86_SHL16r1:
            case X86_SHL32r1:
            case X86_SHL64r1:
            case X86_SAL8r1:
            case X86_SAL16r1:
            case X86_SAL32r1:
            case X86_SAL64r1:
            case X86_SHR8r1:
            case X86_SHR16r1:
            case X86_SHR32r1:
            case X86_SHR64r1:
            case X86_SAR8r1:
            case X86_SAR16r1:
            case X86_SAR32r1:
            case X86_SAR64r1:
            case X86_RCL8r1:
            case X86_RCL16r1:
            case X86_RCL32r1:
            case X86_RCL64r1:
            case X86_RCR8r1:
            case X86_RCR16r1:
            case X86_RCR32r1:
            case X86_RCR64r1:
            case X86_ROL8r1:
            case X86_ROL16r1:
            case X86_ROL32r1:
            case X86_ROL64r1:
            case X86_ROR8r1:
            case X86_ROR16r1:
            case X86_ROR32r1:
            case X86_ROR64r1:
            case X86_SHL8m1:
            case X86_SHL16m1:
            case X86_SHL32m1:
            case X86_SHL64m1:
            case X86_SAL8m1:
            case X86_SAL16m1:
            case X86_SAL32m1:
            case X86_SAL64m1:
            case X86_SHR8m1:
            case X86_SHR16m1:
            case X86_SHR32m1:
            case X86_SHR64m1:
            case X86_SAR8m1:
            case X86_SAR16m1:
            case X86_SAR32m1:
            case X86_SAR64m1:
            case X86_RCL8m1:
            case X86_RCL16m1:
            case X86_RCL32m1:
            case X86_RCL64m1:
            case X86_RCR8m1:
            case X86_RCR16m1:
            case X86_RCR32m1:
            case X86_RCR64m1:
            case X86_ROL8m1:
            case X86_ROL16m1:
            case X86_ROL32m1:
            case X86_ROL64m1:
            case X86_ROR8m1:
            case X86_ROR16m1:
            case X86_ROR32m1:
            case X86_ROR64m1:
                // shift all the ops right to leave 1st slot for this new register op
                memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]),
                        sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1));
                MI->flat_insn->detail->x86.operands[0].type = X86_OP_IMM;
                MI->flat_insn->detail->x86.operands[0].imm = 1;
                MI->flat_insn->detail->x86.operands[0].size = 1;
                MI->flat_insn->detail->x86.op_count++;
        }

		// special instruction needs to supply register op
		// first op can be embedded in the asm by llvm.
		// so we have to add the missing register as the first operand
		reg = X86_insn_reg_att(MCInst_getOpcode(MI));
		if (reg) {
			// shift all the ops right to leave 1st slot for this new register op
			memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]),
					sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1));
			MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
			MI->flat_insn->detail->x86.operands[0].reg = reg;
			MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
			MI->flat_insn->detail->x86.op_count++;
		} else {
			if (X86_insn_reg_att2(MCInst_getOpcode(MI), &reg, &reg2)) {
				MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
				MI->flat_insn->detail->x86.operands[0].reg = reg;
				MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
				MI->flat_insn->detail->x86.operands[1].type = X86_OP_REG;
				MI->flat_insn->detail->x86.operands[1].reg = reg2;
				MI->flat_insn->detail->x86.operands[1].size = MI->csh->regsize_map[reg2];
				MI->flat_insn->detail->x86.op_count = 2;
			}
		}
	}
}
void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
{
	char *mnem;
	x86_reg reg, reg2;
	int i;

	// Output CALLpcrel32 as "callq" in 64-bit mode.
	// In Intel annotation it's always emitted as "call".
	//
	// TODO: Probably this hack should be redesigned via InstAlias in
	// InstrInfo.td as soon as Requires clause is supported properly
	// for InstAlias.
	if (MI->csh->mode == CS_MODE_64 && MCInst_getOpcode(MI) == X86_CALLpcrel32) {
		SStream_concat0(OS, "callq\t");
		MCInst_setOpcodePub(MI, X86_INS_CALL);
		printPCRelImm(MI, 0, OS);
		return;
	}

	// Try to print any aliases first.
	mnem = printAliasInstr(MI, OS, info);
	if (mnem)
		cs_mem_free(mnem);
	else
		printInstruction(MI, OS, info);

	if (MI->has_imm) {
		// if op_count > 1, then this operand's size is taken from the destination op
		if (MI->flat_insn->detail->x86.op_count > 1) {
			for (i = 0; i < MI->flat_insn->detail->x86.op_count; i++) {
				if (MI->flat_insn->detail->x86.operands[i].type == X86_OP_IMM)
					MI->flat_insn->detail->x86.operands[i].size = MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count - 1].size;
			}
		} else
			MI->flat_insn->detail->x86.operands[0].size = MI->imm_size;
	}

	if (MI->csh->detail) {
		uint8_t access[6];
		// special instruction needs to supply register op
		// first op can be embedded in the asm by llvm.
		// so we have to add the missing register as the first operand

		//printf(">>> opcode = %u\n", MCInst_getOpcode(MI));

		reg = X86_insn_reg_att(MCInst_getOpcode(MI));
		if (reg) {
			// shift all the ops right to leave 1st slot for this new register op
			memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]),
					sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1));
			MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
			MI->flat_insn->detail->x86.operands[0].reg = reg;
			MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];

			MI->flat_insn->detail->x86.op_count++;
		} else {
			if (X86_insn_reg_att2(MCInst_getOpcode(MI), &reg, &reg2)) {

				MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
				MI->flat_insn->detail->x86.operands[0].reg = reg;
				MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
				MI->flat_insn->detail->x86.operands[1].type = X86_OP_REG;
				MI->flat_insn->detail->x86.operands[1].reg = reg2;
				MI->flat_insn->detail->x86.operands[1].size = MI->csh->regsize_map[reg2];
				MI->flat_insn->detail->x86.op_count = 2;
			}
		}

#ifndef CAPSTONE_DIET
		get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
		MI->flat_insn->detail->x86.operands[0].access = access[0];
		MI->flat_insn->detail->x86.operands[1].access = access[1];
#endif
	}
}