Example #1
0
static void printPrefetchOp(MCInst *MI, unsigned OpNum, SStream *O)
{
	unsigned prfop = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
	bool Valid;
	char *Name = A64NamedImmMapper_toString(&A64PRFM_PRFMMapper, prfop, &Valid);

	if (Valid) {
		SStream_concat0(O, Name);
		if (MI->csh->detail) {
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_PREFETCH;
			// we have to plus 1 to prfop because 0 is a valid value of prfop
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].prefetch = prfop + 1;
			MI->flat_insn->detail->arm64.op_count++;
		}
	} else {
		printInt32Bang(O, prfop);
		if (MI->csh->detail) {
			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 = prfop;
			MI->flat_insn->detail->arm64.op_count++;
		}
	}
}
/// printPCRelImm - This is used to print an immediate value that ends up
/// being encoded as a pc-relative value.
static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
{
	MCOperand *Op = MCInst_getOperand(MI, OpNo);
	if (MCOperand_isImm(Op)) {
		int64_t imm = MCOperand_getImm(Op) + MI->insn_size + MI->address;
		if (imm < 0) {
			if (imm <= -HEX_THRESHOLD)
				SStream_concat(O, "-0x%"PRIx64, -imm);
			else
				SStream_concat(O, "-%"PRIu64, -imm);
		} else {
			if (imm > HEX_THRESHOLD)
				SStream_concat(O, "0x%"PRIx64, imm);
			else
				SStream_concat(O, "%"PRIu64, imm);
		}
		if (MI->csh->detail) {
			MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_IMM;
			MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].imm = imm;
			MI->flat_insn.x86.op_count++;
		}
	}
}
Example #3
0
static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
{
	int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 7;
	switch (Imm) {
		default: break;	// never reach
		case    0: SStream_concat0(OS, "eq"); op_addSseCC(MI, X86_SSE_CC_EQ); break;
		case    1: SStream_concat0(OS, "lt"); op_addSseCC(MI, X86_SSE_CC_LT); break;
		case    2: SStream_concat0(OS, "le"); op_addSseCC(MI, X86_SSE_CC_LE); break;
		case    3: SStream_concat0(OS, "unord"); op_addSseCC(MI, X86_SSE_CC_UNORD); break;
		case    4: SStream_concat0(OS, "neq"); op_addSseCC(MI, X86_SSE_CC_NEQ); break;
		case    5: SStream_concat0(OS, "nlt"); op_addSseCC(MI, X86_SSE_CC_NLT); break;
		case    6: SStream_concat0(OS, "nle"); op_addSseCC(MI, X86_SSE_CC_NLE); break;
		case    7: SStream_concat0(OS, "ord"); op_addSseCC(MI, X86_SSE_CC_ORD); break;
		case    8: SStream_concat0(OS, "eq_uq"); op_addSseCC(MI, X86_SSE_CC_EQ_UQ); break;
		case    9: SStream_concat0(OS, "nge"); op_addSseCC(MI, X86_SSE_CC_NGE); break;
		case  0xa: SStream_concat0(OS, "ngt"); op_addSseCC(MI, X86_SSE_CC_NGT); break;
		case  0xb: SStream_concat0(OS, "false"); op_addSseCC(MI, X86_SSE_CC_FALSE); break;
		case  0xc: SStream_concat0(OS, "neq_oq"); op_addSseCC(MI, X86_SSE_CC_NEQ_OQ); break;
		case  0xd: SStream_concat0(OS, "ge"); op_addSseCC(MI, X86_SSE_CC_GE); break;
		case  0xe: SStream_concat0(OS, "gt"); op_addSseCC(MI, X86_SSE_CC_GT); break;
		case  0xf: SStream_concat0(OS, "true"); op_addSseCC(MI, X86_SSE_CC_TRUE); break;
	}
}
static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
{
	int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xf;
	switch (Imm) {
		default: break;	// never reach
		case    0: SStream_concat(OS, "eq"); break;
		case    1: SStream_concat(OS, "lt"); break;
		case    2: SStream_concat(OS, "le"); break;
		case    3: SStream_concat(OS, "unord"); break;
		case    4: SStream_concat(OS, "neq"); break;
		case    5: SStream_concat(OS, "nlt"); break;
		case    6: SStream_concat(OS, "nle"); break;
		case    7: SStream_concat(OS, "ord"); break;
		case    8: SStream_concat(OS, "eq_uq"); break;
		case    9: SStream_concat(OS, "nge"); break;
		case  0xa: SStream_concat(OS, "ngt"); break;
		case  0xb: SStream_concat(OS, "false"); break;
		case  0xc: SStream_concat(OS, "neq_oq"); break;
		case  0xd: SStream_concat(OS, "ge"); break;
		case  0xe: SStream_concat(OS, "gt"); break;
		case  0xf: SStream_concat(OS, "true"); break;
	}
}
Example #5
0
static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
{
	MCOperand *SegReg;
	int reg;

	if (MI->csh->detail) {
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
	}

	SegReg = MCInst_getOperand(MI, Op+1);
	reg = MCOperand_getReg(SegReg);

	// If this has a segment register, print it.
	if (reg) {
		_printOperand(MI, Op+1, O);
		if (MI->csh->detail) {
			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
		}

		SStream_concat0(O, ":");
	}

	SStream_concat0(O, "(");
	set_mem_access(MI, true);

	printOperand(MI, Op, O);

	SStream_concat0(O, ")");
	set_mem_access(MI, false);
}
Example #6
0
static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
{
    MCOperand *DispSpec = MCInst_getOperand(MI, Op);

    if (MI->detail) {
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_MEM;
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.base = X86_REG_INVALID;
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.index = X86_REG_INVALID;
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.scale = 1;
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = 0;
    }

    SStream_concat(O, "[");

    if (MCOperand_isImm(DispSpec)) {
        int64_t imm = MCOperand_getImm(DispSpec);
        if (MI->detail)
            MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = imm;
        if (imm < 0) {
            if (imm <= -HEX_THRESHOLD)
                SStream_concat(O, "-0x%"PRIx64, -imm);
            else
                SStream_concat(O, "-%"PRIu64, -imm);
        } else {
            if (imm > HEX_THRESHOLD)
                SStream_concat(O, "0x%"PRIx64, imm);
            else
                SStream_concat(O, "%"PRIu64, imm);
        }
    }

    SStream_concat(O, "]");

    if (MI->detail)
        MI->pub_insn.x86.op_count++;
}
Example #7
0
static void printUnsignedImm(MCInst *MI, int opNum, SStream *O)
{
	MCOperand *MO = MCInst_getOperand(MI, opNum);
	if (MCOperand_isImm(MO)) {
		int64_t imm = MCOperand_getImm(MO);
		if (imm >= 0) {
			if (imm > HEX_THRESHOLD)
				SStream_concat(O, "0x%x", (unsigned short int)imm);
			else
				SStream_concat(O, "%u", (unsigned short int)imm);
		} else {
			if (imm <= -HEX_THRESHOLD)
				SStream_concat(O, "-0x%x", (short int)-imm);
			else
				SStream_concat(O, "-%u", (short int)-imm);
		}
		if (MI->csh->detail) {
			MI->flat_insn.mips.operands[MI->flat_insn.mips.op_count].type = MIPS_OP_IMM;
			MI->flat_insn.mips.operands[MI->flat_insn.mips.op_count].imm = (unsigned short int)imm;
			MI->flat_insn.mips.op_count++;
		}
	} else
		printOperand(MI, opNum, O);
}
Example #8
0
static void printShifter(MCInst *MI, unsigned OpNum, SStream *O)
{
	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));

	// LSL #0 should not be printed.
	if (AArch64_AM_getShiftType(Val) == AArch64_AM_LSL &&
			AArch64_AM_getShiftValue(Val) == 0)
		return;

	SStream_concat(O, ", %s ", AArch64_AM_getShiftExtendName(AArch64_AM_getShiftType(Val)));
	printInt32BangDec(O, AArch64_AM_getShiftValue(Val));
	if (MI->csh->detail) {
		arm64_shifter shifter = ARM64_SFT_INVALID;
		switch(AArch64_AM_getShiftType(Val)) {
			default:	// never reach
			case AArch64_AM_LSL:
				shifter = ARM64_SFT_LSL;
				break;
			case AArch64_AM_LSR:
				shifter = ARM64_SFT_LSR;
				break;
			case AArch64_AM_ASR:
				shifter = ARM64_SFT_ASR;
				break;
			case AArch64_AM_ROR:
				shifter = ARM64_SFT_ROR;
				break;
			case AArch64_AM_MSL:
				shifter = ARM64_SFT_MSL;
				break;
		}

		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = shifter;
		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = AArch64_AM_getShiftValue(Val);
	}
}
Example #9
0
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
{
	MCOperand *Op  = MCInst_getOperand(MI, OpNo);
	if (MCOperand_isReg(Op)) {
		unsigned int reg = MCOperand_getReg(Op);
		printRegName(O, reg);
		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
			} else {
				uint8_t access[6];

				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];

				get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];

				MI->flat_insn->detail->x86.op_count++;
			}
		}
	} else if (MCOperand_isImm(Op)) {
		// Print X86 immediates as signed values.
		uint8_t encsize;
		int64_t imm = MCOperand_getImm(Op);
		uint8_t opsize = X86_immediate_size(MCInst_getOpcode(MI), &encsize);

		if (opsize == 1)    // print 1 byte immediate in positive form
			imm = imm & 0xff;

		switch(MI->flat_insn->id) {
			default:
				if (imm >= 0) {
					if (imm > HEX_THRESHOLD)
						SStream_concat(O, "$0x%"PRIx64, imm);
					else
						SStream_concat(O, "$%"PRIu64, imm);
				} else {
					if (MI->csh->imm_unsigned) {
						if (opsize) {
							switch(opsize) {
								default:
									break;
								case 1:
									imm &= 0xff;
									break;
								case 2:
									imm &= 0xffff;
									break;
								case 4:
									imm &= 0xffffffff;
									break;
							}
						}

						SStream_concat(O, "$0x%"PRIx64, imm);
					} else {
						if (imm == 0x8000000000000000LL)  // imm == -imm
							SStream_concat0(O, "$0x8000000000000000");
						else if (imm < -HEX_THRESHOLD)
							SStream_concat(O, "$-0x%"PRIx64, -imm);
						else
							SStream_concat(O, "$-%"PRIu64, -imm);
					}
				}
				break;

			case X86_INS_MOVABS:
				// do not print number in negative form
				SStream_concat(O, "$0x%"PRIx64, imm);
				break;

			case X86_INS_IN:
			case X86_INS_OUT:
			case X86_INS_INT:
				// do not print number in negative form
				imm = imm & 0xff;
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "$%u", imm);
				else {
					SStream_concat(O, "$0x%x", imm);
				}
				break;

			case X86_INS_LCALL:
			case X86_INS_LJMP:
				// always print address in positive form
				if (OpNo == 1) {	// selector is ptr16
					imm = imm & 0xffff;
					opsize = 2;
				}
				SStream_concat(O, "$0x%"PRIx64, imm);
				break;

			case X86_INS_AND:
			case X86_INS_OR:
			case X86_INS_XOR:
				// do not print number in negative form
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "$%u", imm);
				else {
					imm = arch_masks[opsize? opsize : MI->imm_size] & imm;
					SStream_concat(O, "$0x%"PRIx64, imm);
				}
				break;

			case X86_INS_RET:
			case X86_INS_RETF:
				// RET imm16
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "$%u", imm);
				else {
					imm = 0xffff & imm;
					SStream_concat(O, "$0x%x", imm);
				}
				break;
		}

		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
			} else {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
				MI->has_imm = true;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;

				if (opsize > 0) {
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize;
					MI->flat_insn->detail->x86.encoding.imm_size = encsize;
				} else if (MI->op1_size > 0)
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->op1_size;
				else
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;

				MI->flat_insn->detail->x86.op_count++;
			}
		}
	}
}
Example #10
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);
}
Example #11
0
static bool isReg(MCInst *MI, unsigned OpNo, unsigned R)
{
	return (MCOperand_isReg(MCInst_getOperand(MI, OpNo)) &&
			MCOperand_getReg(MCInst_getOperand(MI, OpNo)) == R);
}
Example #12
0
static void printPredicateOperand(MCInst *MI, unsigned OpNo,
		SStream *O, const char *Modifier)
{
	unsigned Code = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));

	MI->flat_insn->detail->ppc.bc = (ppc_bc)cc_normalize(Code);

	if (!strcmp(Modifier, "cc")) {
		switch ((ppc_predicate)Code) {
			default:	// unreachable
			case PPC_PRED_LT_MINUS:
			case PPC_PRED_LT_PLUS:
			case PPC_PRED_LT:
				SStream_concat0(O, "lt");
				return;
			case PPC_PRED_LE_MINUS:
			case PPC_PRED_LE_PLUS:
			case PPC_PRED_LE:
				SStream_concat0(O, "le");
				return;
			case PPC_PRED_EQ_MINUS:
			case PPC_PRED_EQ_PLUS:
			case PPC_PRED_EQ:
				SStream_concat0(O, "eq");
				return;
			case PPC_PRED_GE_MINUS:
			case PPC_PRED_GE_PLUS:
			case PPC_PRED_GE:
				SStream_concat0(O, "ge");
				return;
			case PPC_PRED_GT_MINUS:
			case PPC_PRED_GT_PLUS:
			case PPC_PRED_GT:
				SStream_concat0(O, "gt");
				return;
			case PPC_PRED_NE_MINUS:
			case PPC_PRED_NE_PLUS:
			case PPC_PRED_NE:
				SStream_concat0(O, "ne");
				return;
			case PPC_PRED_UN_MINUS:
			case PPC_PRED_UN_PLUS:
			case PPC_PRED_UN:
				SStream_concat0(O, "un");
				return;
			case PPC_PRED_NU_MINUS:
			case PPC_PRED_NU_PLUS:
			case PPC_PRED_NU:
				SStream_concat0(O, "nu");
				return;
			case PPC_PRED_BIT_SET:
			case PPC_PRED_BIT_UNSET:
				// llvm_unreachable("Invalid use of bit predicate code");
				SStream_concat0(O, "invalid-predicate");
				return;
		}
	}

	if (!strcmp(Modifier, "pm")) {
		switch ((ppc_predicate)Code) {
			case PPC_PRED_LT:
			case PPC_PRED_LE:
			case PPC_PRED_EQ:
			case PPC_PRED_GE:
			case PPC_PRED_GT:
			case PPC_PRED_NE:
			case PPC_PRED_UN:
			case PPC_PRED_NU:
				return;
			case PPC_PRED_LT_MINUS:
			case PPC_PRED_LE_MINUS:
			case PPC_PRED_EQ_MINUS:
			case PPC_PRED_GE_MINUS:
			case PPC_PRED_GT_MINUS:
			case PPC_PRED_NE_MINUS:
			case PPC_PRED_UN_MINUS:
			case PPC_PRED_NU_MINUS:
				SStream_concat0(O, "-");
				return;
			case PPC_PRED_LT_PLUS:
			case PPC_PRED_LE_PLUS:
			case PPC_PRED_EQ_PLUS:
			case PPC_PRED_GE_PLUS:
			case PPC_PRED_GT_PLUS:
			case PPC_PRED_NE_PLUS:
			case PPC_PRED_UN_PLUS:
			case PPC_PRED_NU_PLUS:
				SStream_concat0(O, "+");
				return;
			case PPC_PRED_BIT_SET:
			case PPC_PRED_BIT_UNSET:
				// llvm_unreachable("Invalid use of bit predicate code");
				SStream_concat0(O, "invalid-predicate");
				return;
			default:	// unreachable
				return;
		}
		// llvm_unreachable("Invalid predicate code");
	}

	//assert(StringRef(Modifier) == "reg" &&
	//		"Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!");
	printOperand(MI, OpNo + 1, O);
}
Example #13
0
static char *printAliasInstrEx(MCInst *MI, SStream *OS, void *info)
{
#define GETREGCLASS_CONTAIN(_class, _reg) MCRegisterClass_contains(MCRegisterInfo_getRegClass(MRI, _class), MCOperand_getReg(MCInst_getOperand(MI, _reg)))
	SStream ss;
	const char *opCode;
	char *tmp, *AsmMnem, *AsmOps, *c;
	int OpIdx, PrintMethodIdx;
	int decCtr = false, needComma = false;
	MCRegisterInfo *MRI = (MCRegisterInfo *)info;

	SStream_Init(&ss);
	switch (MCInst_getOpcode(MI)) {
		default: return NULL;
		case PPC_gBC:
				 opCode = "b%s";
				 break;
		case PPC_gBCA:
				 opCode = "b%sa";
				 break;
		case PPC_gBCCTR:
				 opCode = "b%sctr";
				 break;
		case PPC_gBCCTRL:
				 opCode = "b%sctrl";
				 break;
		case PPC_gBCL:
				 opCode = "b%sl";
				 break;
		case PPC_gBCLA:
				 opCode = "b%sla";
				 break;
		case PPC_gBCLR:
				 opCode = "b%slr";
				 break;
		case PPC_gBCLRL:
				 opCode = "b%slrl";
				 break;
	}

	if (MCInst_getNumOperands(MI) == 3 &&
			MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 0) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 1)) {
		SStream_concat(&ss, opCode, "dnzf");
		decCtr = true;
	}

	if (MCInst_getNumOperands(MI) == 3 &&
			MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 2) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 3)) {
		SStream_concat(&ss, opCode, "dzf");
		decCtr = true;
	}

	if (MCInst_getNumOperands(MI) == 3 &&
			MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 4) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 7) &&
			MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
			GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 1)) {
		int cr = getBICRCond(MCOperand_getReg(MCInst_getOperand(MI, 1)));
		switch(cr) {
			case CREQ:
				SStream_concat(&ss, opCode, "ne");
				break;
			case CRGT:
				SStream_concat(&ss, opCode, "le");
				break;
			case CRLT:
				SStream_concat(&ss, opCode, "ge");
				break;
			case CRUN:
				SStream_concat(&ss, opCode, "ns");
				break;
		}

		if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 6)
			SStream_concat0(&ss, "-");

		if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 7)
			SStream_concat0(&ss, "+");

		decCtr = false;
	}

	if (MCInst_getNumOperands(MI) == 3 &&
			MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 8) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 9)) {
		SStream_concat(&ss, opCode, "dnzt");
		decCtr = true;
	}

	if (MCInst_getNumOperands(MI) == 3 &&
			MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 10) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 11)) {
		SStream_concat(&ss, opCode, "dzt");
		decCtr = true;
	}

	if (MCInst_getNumOperands(MI) == 3 &&
			MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 12) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 15) &&
			MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
			GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 1)) {
		int cr = getBICRCond(MCOperand_getReg(MCInst_getOperand(MI, 1)));
		switch(cr) {
			case CREQ:
				SStream_concat(&ss, opCode, "eq");
				break;
			case CRGT:
				SStream_concat(&ss, opCode, "gt");
				break;
			case CRLT:
				SStream_concat(&ss, opCode, "lt");
				break;
			case CRUN:
				SStream_concat(&ss, opCode, "so");
				break;
		}

		if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 14)
			SStream_concat0(&ss, "-");

		if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 15)
			SStream_concat0(&ss, "+");

		decCtr = false;
	}

	if (MCInst_getNumOperands(MI) == 3 &&
			MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
			((MCOperand_getImm(MCInst_getOperand(MI, 0)) & 0x12)== 16)) {
		SStream_concat(&ss, opCode, "dnz");

		if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 24)
			SStream_concat0(&ss, "-");

		if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 25)
			SStream_concat0(&ss, "+");

		needComma = false;
	}

	if (MCInst_getNumOperands(MI) == 3 &&
			MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
			((MCOperand_getImm(MCInst_getOperand(MI, 0)) & 0x12)== 18)) {
		SStream_concat(&ss, opCode, "dz");

		if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 26)
			SStream_concat0(&ss, "-");

		if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 27)
			SStream_concat0(&ss, "+");

		needComma = false;
	}

	if (MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
			GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 1) &&
			MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
			(MCOperand_getImm(MCInst_getOperand(MI, 0)) < 16)) {
		int cr = getBICR(MCOperand_getReg(MCInst_getOperand(MI, 1)));

		if (decCtr) {
			needComma = true;
			SStream_concat0(&ss, " ");

			if (cr > PPC_CR0) {
				SStream_concat(&ss, "4*cr%d+", cr - PPC_CR0);
			}

			cr = getBICRCond(MCOperand_getReg(MCInst_getOperand(MI, 1)));
			switch(cr) {
				case CREQ:
					SStream_concat0(&ss, "eq");
					op_addBC(MI, PPC_BC_EQ);
					break;
				case CRGT:
					SStream_concat0(&ss, "gt");
					op_addBC(MI, PPC_BC_GT);
					break;
				case CRLT:
					SStream_concat0(&ss, "lt");
					op_addBC(MI, PPC_BC_LT);
					break;
				case CRUN:
					SStream_concat0(&ss, "so");
					op_addBC(MI, PPC_BC_SO);
					break;
			}

			cr = getBICR(MCOperand_getReg(MCInst_getOperand(MI, 1)));
			if (cr > PPC_CR0) {
				if (MI->csh->detail) {
					MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_CRX;
					MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].crx.scale = 4;
					MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].crx.reg = PPC_REG_CR0 + cr - PPC_CR0;
					MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].crx.cond = MI->flat_insn->detail->ppc.bc;
					MI->flat_insn->detail->ppc.op_count++;
				}
			}
		} else {
			if (cr > PPC_CR0) {
				needComma = true;
				SStream_concat(&ss, " cr%d", cr - PPC_CR0);
				op_addReg(MI, PPC_REG_CR0 + cr - PPC_CR0);
			}
		}
	}

	if (MCOperand_isImm(MCInst_getOperand(MI, 2)) &&
			MCOperand_getImm(MCInst_getOperand(MI, 2)) != 0) {
		if (needComma)
			SStream_concat0(&ss, ",");

		SStream_concat0(&ss, " $\xFF\x03\x01");
	}

	tmp = cs_strdup(ss.buffer);
	AsmMnem = tmp;
	for(AsmOps = tmp; *AsmOps; AsmOps++) {
		if (*AsmOps == ' ' || *AsmOps == '\t') {
			*AsmOps = '\0';
			AsmOps++;
			break;
		}
	}

	SStream_concat0(OS, AsmMnem);
	if (*AsmOps) {
		SStream_concat0(OS, "\t");
		for (c = AsmOps; *c; c++) {
			if (*c == '$') {
				c += 1;
				if (*c == (char)0xff) {
					c += 1;
					OpIdx = *c - 1;
					c += 1;
					PrintMethodIdx = *c - 1;
					printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, OS);
				} else
					printOperand(MI, *c - 1, OS);
			} else {
				SStream_concat(OS, "%c", *c);
			}
		}
	}

	return tmp;
}
Example #14
0
static void printArithExtend(MCInst *MI, unsigned OpNum, SStream *O)
{
	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
	AArch64_AM_ShiftExtendType ExtType = AArch64_AM_getArithExtendType(Val);
	unsigned ShiftVal = AArch64_AM_getArithShiftValue(Val);

	// If the destination or first source register operand is [W]SP, print
	// UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at
	// all.
	if (ExtType == AArch64_AM_UXTW || ExtType == AArch64_AM_UXTX) {
		unsigned Dest = MCOperand_getReg(MCInst_getOperand(MI, 0));
		unsigned Src1 = MCOperand_getReg(MCInst_getOperand(MI, 1));
		if ( ((Dest == AArch64_SP || Src1 == AArch64_SP) &&
					ExtType == AArch64_AM_UXTX) ||
				((Dest == AArch64_WSP || Src1 == AArch64_WSP) &&
				 ExtType == AArch64_AM_UXTW) ) {
			if (ShiftVal != 0) {
				SStream_concat0(O, ", lsl ");
				printInt32Bang(O, ShiftVal);
				if (MI->csh->detail) {
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = ARM64_SFT_LSL;
					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = ShiftVal;
				}
			}

			return;
		}
	}

	SStream_concat(O, ", %s", AArch64_AM_getShiftExtendName(ExtType));
	if (MI->csh->detail) {
		arm64_extender ext = ARM64_EXT_INVALID;
		switch(ExtType) {
			default:	// never reach
			case AArch64_AM_UXTB:
				ext = ARM64_EXT_UXTW;
				break;
			case AArch64_AM_UXTH:
				ext = ARM64_EXT_UXTW;
				break;
			case AArch64_AM_UXTW:
				ext = ARM64_EXT_UXTW;
				break;
			case AArch64_AM_UXTX:
				ext = ARM64_EXT_UXTW;
				break;
			case AArch64_AM_SXTB:
				ext = ARM64_EXT_UXTW;
				break;
			case AArch64_AM_SXTH:
				ext = ARM64_EXT_UXTW;
				break;
			case AArch64_AM_SXTW:
				ext = ARM64_EXT_UXTW;
				break;
			case AArch64_AM_SXTX:
				ext = ARM64_EXT_UXTW;
				break;
		}

		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].ext = ext;
	}

	if (ShiftVal != 0) {
		SStream_concat0(O, " ");
		printInt32Bang(O, ShiftVal);
		if (MI->csh->detail) {
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = ARM64_SFT_LSL;
			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = ShiftVal;
		}
	}
}
Example #15
0
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
{
	int opsize = 0;
	MCOperand *Op  = MCInst_getOperand(MI, OpNo);

	if (MCOperand_isReg(Op)) {
		unsigned int reg = MCOperand_getReg(Op);

		printRegName(O, reg);
		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
			} else {
#ifndef CAPSTONE_DIET
				uint8_t access[6];
#endif

				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];

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

				MI->flat_insn->detail->x86.op_count++;
			}
		}

		if (MI->op1_size == 0)
			MI->op1_size = MI->csh->regsize_map[reg];
	} else if (MCOperand_isImm(Op)) {
		int64_t imm = MCOperand_getImm(Op);

		switch(MCInst_getOpcode(MI)) {
			default:
				break;

			case X86_AAD8i8:
			case X86_AAM8i8:
			case X86_ADC8i8:
			case X86_ADD8i8:
			case X86_AND8i8:
			case X86_CMP8i8:
			case X86_OR8i8:
			case X86_SBB8i8:
			case X86_SUB8i8:
			case X86_TEST8i8:
			case X86_XOR8i8:
			case X86_ROL8ri:
			case X86_ADC8ri:
			case X86_ADC8ri8:
			case X86_ADD8ri:
			case X86_ADD8ri8:
			case X86_AND8ri:
			case X86_AND8ri8:
			case X86_CMP8ri:
			case X86_CMP8ri8:
			case X86_IN8ri:
			case X86_MOV8ri:
			case X86_MOV8ri_alt:
			case X86_OR8ri:
			case X86_OR8ri8:
			case X86_RCL8ri:
			case X86_RCR8ri:
			case X86_ROR8ri:
			case X86_SAL8ri:
			case X86_SAR8ri:
			case X86_SBB8ri:
			case X86_SBB8ri8:
			case X86_SHL8ri:
			case X86_SHR8ri:
			case X86_SUB8ri:
			case X86_SUB8ri8:
			case X86_TEST8ri:
			case X86_TEST8ri_NOREX:
			case X86_TEST8ri_alt:
			case X86_XOR8ri:
			case X86_XOR8ri8:
			case X86_OUT8ir:

			case X86_ADC8mi:
			case X86_ADC8mi8:
			case X86_ADD8mi:
			case X86_ADD8mi8:
			case X86_AND8mi:
			case X86_AND8mi8:
			case X86_CMP8mi:
			case X86_CMP8mi8:
			case X86_LOCK_ADD8mi:
			case X86_LOCK_AND8mi:
			case X86_LOCK_OR8mi:
			case X86_LOCK_SUB8mi:
			case X86_LOCK_XOR8mi:
			case X86_MOV8mi:
			case X86_OR8mi:
			case X86_OR8mi8:
			case X86_RCL8mi:
			case X86_RCR8mi:
			case X86_ROL8mi:
			case X86_ROR8mi:
			case X86_SAL8mi:
			case X86_SAR8mi:
			case X86_SBB8mi:
			case X86_SBB8mi8:
			case X86_SHL8mi:
			case X86_SHR8mi:
			case X86_SUB8mi:
			case X86_SUB8mi8:
			case X86_TEST8mi:
			case X86_TEST8mi_alt:
			case X86_XOR8mi:
			case X86_XOR8mi8:
			case X86_PUSH64i8:
			case X86_CMP32ri8:
			case X86_CMP64ri8:

				imm = imm & 0xff;
				opsize = 1;	// immediate of 1 byte
				break;
		}

		switch(MI->flat_insn->id) {
			default:
				if (imm >= 0) {
					if (imm > HEX_THRESHOLD)
						SStream_concat(O, "0x%"PRIx64, imm);
					else
						SStream_concat(O, "%"PRIu64, imm);
				} else {
					if (imm < -HEX_THRESHOLD)
						SStream_concat(O, "-0x%"PRIx64, -imm);
					else
						SStream_concat(O, "-%"PRIu64, -imm);
				}

				break;

			case X86_INS_INT:
				// do not print number in negative form
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "%u", imm);
				else
					SStream_concat(O, "0x%x", imm & 0xff);
				break;

			case X86_INS_AND:
			case X86_INS_OR:
			case X86_INS_XOR:
				// do not print number in negative form
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "%u", imm);
				else
					SStream_concat(O, "0x%"PRIx64, arch_masks[MI->op1_size? MI->op1_size : MI->imm_size] & imm);
				break;

			case X86_INS_RET:
				// RET imm16
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "%u", imm);
				else {
					imm = 0xffff & imm;
					SStream_concat(O, "0x%x", 0xffff & imm);
				}
				break;
		}

		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
			} else {
#ifndef CAPSTONE_DIET
				uint8_t access[6];
#endif

				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
				if (opsize > 0)
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize;
				else if (MI->flat_insn->detail->x86.op_count > 0)
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->flat_insn->detail->x86.operands[0].size;
				else
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;

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

				MI->flat_insn->detail->x86.op_count++;
			}
		}

		//if (MI->op1_size == 0)
		//	MI->op1_size = MI->imm_size;
	}
}
Example #16
0
static void printFCCOperand(MCInst *MI, int opNum, SStream *O)
{
	MCOperand *MO = MCInst_getOperand(MI, opNum);
	SStream_concat(O, MipsFCCToString((Mips_CondCode)MCOperand_getImm(MO)));
}
Example #17
0
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 void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
{
	MCOperand *Op  = MCInst_getOperand(MI, OpNo);
	if (MCOperand_isReg(Op)) {
		unsigned int reg = MCOperand_getReg(Op);

		printRegName(O, reg);
		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
			} else {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];
				MI->flat_insn->detail->x86.op_count++;
			}
		}

		if (MI->op1_size == 0)
			MI->op1_size = MI->csh->regsize_map[reg];
	} else if (MCOperand_isImm(Op)) {
		int64_t imm = MCOperand_getImm(Op);

		switch(MI->flat_insn->id) {
			default:
				if (imm >= 0) {
					if (imm > HEX_THRESHOLD)
						SStream_concat(O, "0x%"PRIx64, imm);
					else
						SStream_concat(O, "%"PRIu64, imm);
				} else {
					if (imm < -HEX_THRESHOLD)
						SStream_concat(O, "-0x%"PRIx64, -imm);
					else
						SStream_concat(O, "-%"PRIu64, -imm);
				}

				break;

			case X86_INS_AND:
			case X86_INS_OR:
			case X86_INS_XOR:
				// do not print number in negative form
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "%u", imm);
				else
					SStream_concat(O, "0x%"PRIx64, arch_masks[MI->op1_size? MI->op1_size : MI->imm_size] & imm);
				break;
			case X86_INS_RET:
				// RET imm16
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "%u", imm);
				else {
					imm = 0xffff & imm;
					SStream_concat(O, "0x%x", 0xffff & imm);
				}
				break;
		}

		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
			} else {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
				if (MI->flat_insn->detail->x86.op_count > 0)
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->flat_insn->detail->x86.operands[0].size;
				else
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
				MI->flat_insn->detail->x86.op_count++;
			}
		}

		//if (MI->op1_size == 0)
		//	MI->op1_size = MI->imm_size;
	}
}
Example #19
0
static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
{
	bool NeedPlus = false;
	MCOperand *BaseReg  = MCInst_getOperand(MI, Op + X86_AddrBaseReg);
	uint64_t ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt));
	MCOperand *IndexReg  = MCInst_getOperand(MI, Op + X86_AddrIndexReg);
	MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp);
	MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg);
	int reg;

	if (MI->csh->detail) {
#ifndef CAPSTONE_DIET
		uint8_t access[6];
#endif

		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = MCOperand_getReg(BaseReg);
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;

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

	// If this has a segment register, print it.
	reg = MCOperand_getReg(SegReg);
	if (reg) {
		_printOperand(MI, Op + X86_AddrSegmentReg, O);
		if (MI->csh->detail) {
			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
		}
		SStream_concat0(O, ":");
	}

	SStream_concat0(O, "[");

	if (MCOperand_getReg(BaseReg)) {
		_printOperand(MI, Op + X86_AddrBaseReg, O);
		NeedPlus = true;
	}

	if (MCOperand_getReg(IndexReg)) {
		if (NeedPlus) SStream_concat0(O, " + ");
		_printOperand(MI, Op + X86_AddrIndexReg, O);
		if (ScaleVal != 1)
			SStream_concat(O, "*%u", ScaleVal);
		NeedPlus = true;
	}

	if (MCOperand_isImm(DispSpec)) {
		int64_t DispVal = MCOperand_getImm(DispSpec);
		if (MI->csh->detail)
			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal;
		if (DispVal) {
			if (NeedPlus) {
				if (DispVal < 0) {
					SStream_concat0(O, " - ");
					printImm(MI->csh->syntax, O, -DispVal, true);
				} else {
					SStream_concat0(O, " + ");
					printImm(MI->csh->syntax, O, DispVal, true);
				}
			} else {
				// memory reference to an immediate address
				if (DispVal < 0) {
					printImm(MI->csh->syntax, O, arch_masks[MI->csh->mode] & DispVal, true);
				} else {
					printImm(MI->csh->syntax, O, DispVal, true);
				}
			}

		} else {
			// DispVal = 0
			if (!NeedPlus)	// [0]
				SStream_concat0(O, "0");
		}
	}

	SStream_concat0(O, "]");

	if (MI->csh->detail)
		MI->flat_insn->detail->x86.op_count++;

	if (MI->op1_size == 0)
		MI->op1_size = MI->x86opsize;
}
Example #20
0
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
{
	MCOperand *Op  = MCInst_getOperand(MI, OpNo);

	if (MCOperand_isReg(Op)) {
		unsigned int reg = MCOperand_getReg(Op);

		printRegName(O, reg);
		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
			} else {
#ifndef CAPSTONE_DIET
				uint8_t access[6];
#endif

				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];

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

				MI->flat_insn->detail->x86.op_count++;
			}
		}

		if (MI->op1_size == 0)
			MI->op1_size = MI->csh->regsize_map[reg];
	} else if (MCOperand_isImm(Op)) {
		int64_t imm = MCOperand_getImm(Op);
		int opsize = X86_immediate_size(MCInst_getOpcode(MI));
		if (opsize == 1)    // print 1 byte immediate in positive form
			imm = imm & 0xff;

		switch(MI->flat_insn->id) {
			default:
				printImm(MI->csh->syntax, O, imm, false);
				break;

			case X86_INS_INT:
				// do not print number in negative form
				imm = imm & 0xff;
				printImm(MI->csh->syntax, O, imm, true);
				break;

			case X86_INS_LCALL:
			case X86_INS_LJMP:
				// always print address in positive form
				if (OpNo == 1) {	// ptr16 part
					imm = imm & 0xffff;
					opsize = 2;
				}
				printImm(MI->csh->syntax, O, imm, true);
				break;

			case X86_INS_AND:
			case X86_INS_OR:
			case X86_INS_XOR:
				// do not print number in negative form
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					printImm(MI->csh->syntax, O, imm, true);
				else {
					imm = arch_masks[opsize? opsize : MI->imm_size] & imm;
					printImm(MI->csh->syntax, O, imm, true);
				}
				break;

			case X86_INS_RET:
				// RET imm16
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					printImm(MI->csh->syntax, O, imm, true);
				else {
					imm = 0xffff & imm;
					printImm(MI->csh->syntax, O, imm, true);
				}
				break;
		}

		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
			} else {
#ifndef CAPSTONE_DIET
				uint8_t access[6];
#endif

				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
				if (opsize > 0)
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize;
				else if (MI->flat_insn->detail->x86.op_count > 0) {
					if (MI->flat_insn->id != X86_INS_LCALL && MI->flat_insn->id != X86_INS_LJMP) {
						MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size =
							MI->flat_insn->detail->x86.operands[0].size;
					} else
						MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
				} else
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;

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

				MI->flat_insn->detail->x86.op_count++;
			}
		}
	}
}
Example #21
0
static void printMemReference(MCInst *MI, unsigned Op, SStream *O)	// qqq
{
    MCOperand *BaseReg  = MCInst_getOperand(MI, Op);
    unsigned ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op+1));
    MCOperand *IndexReg  = MCInst_getOperand(MI, Op+2);
    MCOperand *DispSpec = MCInst_getOperand(MI, Op+3);
    MCOperand *SegReg = MCInst_getOperand(MI, Op+4);

    if (MI->detail) {
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_MEM;
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.base = MCOperand_getReg(BaseReg);
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.index = MCOperand_getReg(IndexReg);
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.scale = ScaleVal;
        MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = 0;
    }

    // If this has a segment register, print it.
    if (MCOperand_getReg(SegReg)) {
        _printOperand(MI, Op+4, O);
        SStream_concat(O, ":");
    }

    SStream_concat(O, "[");

    bool NeedPlus = false;
    if (MCOperand_getReg(BaseReg)) {
        _printOperand(MI, Op, O);
        NeedPlus = true;
    }

    if (MCOperand_getReg(IndexReg)) {
        if (NeedPlus) SStream_concat(O, " + ");
        _printOperand(MI, Op+2, O);
        if (ScaleVal != 1)
            SStream_concat(O, "*%u", ScaleVal);
        NeedPlus = true;
    }

    if (!MCOperand_isImm(DispSpec)) {
        if (NeedPlus) SStream_concat(O, " + ");
        //assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
    } else {
        int64_t DispVal = MCOperand_getImm(DispSpec);
        if (MI->detail)
            MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = DispVal;
        if (DispVal || (!MCOperand_getReg(IndexReg) && !MCOperand_getReg(BaseReg))) {
            if (NeedPlus) {
                if (DispVal > 0)
                    SStream_concat(O, " + ");
                else {
                    SStream_concat(O, " - ");
                    DispVal = -DispVal;
                }
            }
            if (DispVal < 0) {
                if (DispVal <= -HEX_THRESHOLD)
                    SStream_concat(O, "-0x%"PRIx64, -DispVal);
                else
                    SStream_concat(O, "-%"PRIu64, -DispVal);
            } else {
                if (DispVal > HEX_THRESHOLD)
                    SStream_concat(O, "0x%"PRIx64, DispVal);
                else
                    SStream_concat(O, "%"PRIu64, DispVal);
            }
        }
    }

    SStream_concat(O, "]");

    if (MI->detail)
        MI->pub_insn.x86.op_count++;
}
Example #22
0
static void printAVXCC(MCInst *MI, unsigned Op, SStream *O)
{
    int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x1f;
    switch (Imm) {
    default:
        printf("Invalid avxcc argument!\n");
        break;
    case    0:
        SStream_concat(O, "eq");
        break;
    case    1:
        SStream_concat(O, "lt");
        break;
    case    2:
        SStream_concat(O, "le");
        break;
    case    3:
        SStream_concat(O, "unord");
        break;
    case    4:
        SStream_concat(O, "neq");
        break;
    case    5:
        SStream_concat(O, "nlt");
        break;
    case    6:
        SStream_concat(O, "nle");
        break;
    case    7:
        SStream_concat(O, "ord");
        break;
    case    8:
        SStream_concat(O, "eq_uq");
        break;
    case    9:
        SStream_concat(O, "nge");
        break;
    case  0xa:
        SStream_concat(O, "ngt");
        break;
    case  0xb:
        SStream_concat(O, "false");
        break;
    case  0xc:
        SStream_concat(O, "neq_oq");
        break;
    case  0xd:
        SStream_concat(O, "ge");
        break;
    case  0xe:
        SStream_concat(O, "gt");
        break;
    case  0xf:
        SStream_concat(O, "true");
        break;
    case 0x10:
        SStream_concat(O, "eq_os");
        break;
    case 0x11:
        SStream_concat(O, "lt_oq");
        break;
    case 0x12:
        SStream_concat(O, "le_oq");
        break;
    case 0x13:
        SStream_concat(O, "unord_s");
        break;
    case 0x14:
        SStream_concat(O, "neq_us");
        break;
    case 0x15:
        SStream_concat(O, "nlt_uq");
        break;
    case 0x16:
        SStream_concat(O, "nle_uq");
        break;
    case 0x17:
        SStream_concat(O, "ord_s");
        break;
    case 0x18:
        SStream_concat(O, "eq_us");
        break;
    case 0x19:
        SStream_concat(O, "nge_uq");
        break;
    case 0x1a:
        SStream_concat(O, "ngt_uq");
        break;
    case 0x1b:
        SStream_concat(O, "false_os");
        break;
    case 0x1c:
        SStream_concat(O, "neq_os");
        break;
    case 0x1d:
        SStream_concat(O, "ge_oq");
        break;
    case 0x1e:
        SStream_concat(O, "gt_oq");
        break;
    case 0x1f:
        SStream_concat(O, "true_us");
        break;
    }
}
Example #23
0
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;
}
Example #24
0
static void printBDXAddrOperand(MCInst *MI, int OpNum, SStream *O)
{
	printAddress(MI, MCOperand_getReg(MCInst_getOperand(MI, OpNum)),
			MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)),
			MCOperand_getReg(MCInst_getOperand(MI, OpNum + 2)), O);
}
static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
{
	MCOperand *BaseReg  = MCInst_getOperand(MI, Op);
	MCOperand *IndexReg  = MCInst_getOperand(MI, Op+2);
	MCOperand *DispSpec = MCInst_getOperand(MI, Op+3);
	MCOperand *SegReg = MCInst_getOperand(MI, Op+4);
	uint64_t ScaleVal;

	if (MI->csh->detail) {
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = MCOperand_getReg(BaseReg);
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
	}

	SStream_concat0(O, markup("<mem:"));

	// If this has a segment register, print it.
	if (MCOperand_getReg(SegReg)) {
		_printOperand(MI, Op+4, O);
		SStream_concat0(O, ":");
	}

	if (MCOperand_isImm(DispSpec)) {
		int64_t DispVal = MCOperand_getImm(DispSpec);
		if (MI->csh->detail)
			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal;
		if (DispVal || (!MCOperand_getReg(IndexReg) && !MCOperand_getReg(BaseReg))) {
			if (DispVal < 0) {
				SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal);
			} else {
				if (DispVal > HEX_THRESHOLD)
					SStream_concat(O, "0x%"PRIx64, DispVal);
				else
					SStream_concat(O, "%"PRIu64, DispVal);
			}
		}
	}

	if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
		SStream_concat0(O, "(");

		if (MCOperand_getReg(BaseReg))
			_printOperand(MI, Op, O);

		if (MCOperand_getReg(IndexReg)) {
			SStream_concat0(O, ", ");
			_printOperand(MI, Op+2, O);
			ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op+1));
			if (MI->csh->detail)
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal;
			if (ScaleVal != 1) {
				SStream_concat(O, ", %s%u%s", markup("<imm:"), ScaleVal, markup(">"));
			}
		}
		SStream_concat0(O, ")");
	}

	SStream_concat0(O, markup(">"));

	if (MI->csh->detail)
		MI->flat_insn->detail->x86.op_count++;
}
Example #26
0
static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
{
	MCOperand *BaseReg  = MCInst_getOperand(MI, Op + X86_AddrBaseReg);
	MCOperand *IndexReg  = MCInst_getOperand(MI, Op + X86_AddrIndexReg);
	MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp);
	MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg);
	uint64_t ScaleVal;
	int reg;

	if (MI->csh->detail) {
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = MCOperand_getReg(BaseReg);
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
	}

	// If this has a segment register, print it.
	reg = MCOperand_getReg(SegReg);
	if (reg) {
		_printOperand(MI, Op + X86_AddrSegmentReg, O);
		if (MI->csh->detail) {
			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
		}

		SStream_concat0(O, ":");
	}

	if (MCOperand_isImm(DispSpec)) {
		int64_t DispVal = MCOperand_getImm(DispSpec);
		if (MI->csh->detail)
			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal;
		if (DispVal) {
			if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
				if (DispVal < 0) {
					if (DispVal <  -HEX_THRESHOLD)
						SStream_concat(O, "-0x%"PRIx64, -DispVal);
					else
						SStream_concat(O, "-%"PRIu64, -DispVal);
				} else {
					if (DispVal > HEX_THRESHOLD)
						SStream_concat(O, "0x%"PRIx64, DispVal);
					else
						SStream_concat(O, "%"PRIu64, DispVal);
				}
			} else {
				// only immediate as address of memory
				if (DispVal < 0) {
					SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal);
				} else {
					if (DispVal > HEX_THRESHOLD)
						SStream_concat(O, "0x%"PRIx64, DispVal);
					else
						SStream_concat(O, "%"PRIu64, DispVal);
				}
			}
		} else {
			SStream_concat0(O, "0");
		}
	}

	if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
		SStream_concat0(O, "(");

		if (MCOperand_getReg(BaseReg))
			_printOperand(MI, Op + X86_AddrBaseReg, O);

		if (MCOperand_getReg(IndexReg)) {
			SStream_concat0(O, ", ");
			_printOperand(MI, Op + X86_AddrIndexReg, O);
			ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt));
			if (MI->csh->detail)
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal;
			if (ScaleVal != 1) {
				SStream_concat(O, ", %u", ScaleVal);
			}
		}
		SStream_concat0(O, ")");
	}

	if (MI->csh->detail)
		MI->flat_insn->detail->x86.op_count++;
}
Example #27
0
static void printOperand(MCInst *MI, int OpNum, SStream *O)
{
	_printOperand(MI, MCInst_getOperand(MI, OpNum), O);
}
Example #28
0
void PPC_printInst(MCInst *MI, SStream *O, void *Info)
{
    // 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_concat(O, "slwi\t");
            useSubstituteMnemonic = true;
        }

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

        if (useSubstituteMnemonic) {
            printOperand(MI, 0, O);
            SStream_concat(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_OR || MCInst_getOpcode(MI) == PPC_OR8) &&
            MCOperand_getReg(MCInst_getOperand(MI, 1)) == MCOperand_getReg(MCInst_getOperand(MI, 1))) {
        SStream_concat(O, "mr\t");
        printOperand(MI, 0, O);
        SStream_concat(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_concat(O, "sldi\t");
            printOperand(MI, 0, O);
            SStream_concat(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;
        }
    }

    printInstruction(MI, O, NULL);
}
Example #29
0
static void printOperand(MCInst *MI, int opNum, SStream *O)
{
	int Imm;
	unsigned reg;
	MCOperand *MO = MCInst_getOperand(MI, opNum);

	if (MCOperand_isReg(MO)) {
		reg = MCOperand_getReg(MO);
		printRegName(O, reg);
		reg = Sparc_map_register(reg);

		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				if (MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.base)
					MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.index = reg;
				else
					MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.base = reg;
			} else {
				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].type = SPARC_OP_REG;
				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].reg = reg;
				MI->flat_insn->detail->sparc.op_count++;
			}
		}

		return;
	}

	if (MCOperand_isImm(MO)) {
		Imm = (int)MCOperand_getImm(MO);

		// Conditional branches displacements needs to be signextended to be
		// able to jump backwards.
		//
		// Displacements are measured as the number of instructions forward or
		// backward, so they need to be multiplied by 4
		switch (MI->Opcode) {
			case SP_CALL:
				Imm = SignExtend32(Imm, 30);
				Imm += (uint32_t)MI->address;
				break;

			// Branch on integer condition with prediction (BPcc)
			// Branch on floating point condition with prediction (FBPfcc)
			case SP_BPICC:
			case SP_BPICCA:
			case SP_BPICCANT:
			case SP_BPICCNT:
			case SP_BPXCC:
			case SP_BPXCCA:
			case SP_BPXCCANT:
			case SP_BPXCCNT:
			case SP_BPFCC:
			case SP_BPFCCA:
			case SP_BPFCCANT:
			case SP_BPFCCNT:
				Imm = SignExtend32(Imm, 19);
				Imm = (uint32_t)MI->address + Imm * 4;
				break;

			// Branch on integer condition (Bicc)
			// Branch on floating point condition (FBfcc)
			case SP_BA:
			case SP_BCOND:
			case SP_BCONDA:
			case SP_FBCOND:
			case SP_FBCONDA:
				Imm = SignExtend32(Imm, 22);
				Imm = (uint32_t)MI->address + Imm * 4;
				break;

			// Branch on integer register with prediction (BPr)
			case SP_BPGEZapn:
			case SP_BPGEZapt:
			case SP_BPGEZnapn:
			case SP_BPGEZnapt:
			case SP_BPGZapn:
			case SP_BPGZapt:
			case SP_BPGZnapn:
			case SP_BPGZnapt:
			case SP_BPLEZapn:
			case SP_BPLEZapt:
			case SP_BPLEZnapn:
			case SP_BPLEZnapt:
			case SP_BPLZapn:
			case SP_BPLZapt:
			case SP_BPLZnapn:
			case SP_BPLZnapt:
			case SP_BPNZapn:
			case SP_BPNZapt:
			case SP_BPNZnapn:
			case SP_BPNZnapt:
			case SP_BPZapn:
			case SP_BPZapt:
			case SP_BPZnapn:
			case SP_BPZnapt:
				Imm = SignExtend32(Imm, 16);
				Imm = (uint32_t)MI->address + Imm * 4;
				break;
		}

		if (Imm >= 0) {
			if (Imm > HEX_THRESHOLD)
				SStream_concat(O, "0x%x", Imm);
			else
				SStream_concat(O, "%u", Imm);
		} else {
			if (Imm < -HEX_THRESHOLD)
				SStream_concat(O, "-0x%x", -Imm);
			else
				SStream_concat(O, "-%u", -Imm);
		}

		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.disp = Imm;
			} else {
				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].type = SPARC_OP_IMM;
				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].imm = Imm;
				MI->flat_insn->detail->sparc.op_count++;
			}
		}
	}

	return;
}
Example #30
0
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
{
	uint8_t opsize = 0;
	MCOperand *Op  = MCInst_getOperand(MI, OpNo);

	if (MCOperand_isReg(Op)) {
		unsigned int reg = MCOperand_getReg(Op);
		printRegName(O, reg);
		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
			} else {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];
				MI->flat_insn->detail->x86.op_count++;
			}
		}
	} else if (MCOperand_isImm(Op)) {
		// Print X86 immediates as signed values.
		int64_t imm = MCOperand_getImm(Op);

		switch(MCInst_getOpcode(MI)) {
			default:
				break;

			case X86_AAD8i8:
			case X86_AAM8i8:
			case X86_ADC8i8:
			case X86_ADD8i8:
			case X86_AND8i8:
			case X86_CMP8i8:
			case X86_OR8i8:
			case X86_SBB8i8:
			case X86_SUB8i8:
			case X86_TEST8i8:
			case X86_XOR8i8:
			case X86_ROL8ri:
			case X86_ADC8ri:
			case X86_ADD8ri:
			case X86_ADD8ri8:
			case X86_AND8ri:
			case X86_AND8ri8:
			case X86_CMP8ri:
			case X86_MOV8ri:
			case X86_MOV8ri_alt:
			case X86_OR8ri:
			case X86_OR8ri8:
			case X86_RCL8ri:
			case X86_RCR8ri:
			case X86_ROR8ri:
			case X86_SAL8ri:
			case X86_SAR8ri:
			case X86_SBB8ri:
			case X86_SHL8ri:
			case X86_SHR8ri:
			case X86_SUB8ri:
			case X86_SUB8ri8:
			case X86_TEST8ri:
			case X86_TEST8ri_NOREX:
			case X86_TEST8ri_alt:
			case X86_XOR8ri:
			case X86_XOR8ri8:
			case X86_OUT8ir:

			case X86_ADC8mi:
			case X86_ADD8mi:
			case X86_AND8mi:
			case X86_CMP8mi:
			case X86_LOCK_ADD8mi:
			case X86_LOCK_AND8mi:
			case X86_LOCK_OR8mi:
			case X86_LOCK_SUB8mi:
			case X86_LOCK_XOR8mi:
			case X86_MOV8mi:
			case X86_OR8mi:
			case X86_RCL8mi:
			case X86_RCR8mi:
			case X86_ROL8mi:
			case X86_ROR8mi:
			case X86_SAL8mi:
			case X86_SAR8mi:
			case X86_SBB8mi:
			case X86_SHL8mi:
			case X86_SHR8mi:
			case X86_SUB8mi:
			case X86_TEST8mi:
			case X86_TEST8mi_alt:
			case X86_XOR8mi:
			case X86_PUSH64i8:
			case X86_CMP32ri8:
			case X86_CMP64ri8:

				imm = imm & 0xff;
				opsize = 1;     // immediate of 1 byte
				break;
		}

		switch(MI->flat_insn->id) {
			default:
				if (imm >= 0) {
					if (imm > HEX_THRESHOLD)
						SStream_concat(O, "$0x%"PRIx64, imm);
					else
						SStream_concat(O, "$%"PRIu64, imm);
				} else {
					if (imm < -HEX_THRESHOLD)
						SStream_concat(O, "$-0x%"PRIx64, -imm);
					else
						SStream_concat(O, "$-%"PRIu64, -imm);
				}
				break;

			case X86_INS_INT:
				// do not print number in negative form
				imm = imm & 0xff;
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "$%u", imm);
				else {
					SStream_concat(O, "$0x%x", imm);
				}
				break;

			case X86_INS_LCALL:
			case X86_INS_LJMP:
				// always print address in positive form
				if (OpNo == 1) { // selector is ptr16
					imm = imm & 0xffff;
					opsize = 2;
				}
				SStream_concat(O, "$0x%"PRIx64, imm);
				break;

			case X86_INS_AND:
			case X86_INS_OR:
			case X86_INS_XOR:
				// do not print number in negative form
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "$%u", imm);
				else {
					imm = arch_masks[MI->op1_size? MI->op1_size : MI->imm_size] & imm;
					SStream_concat(O, "$0x%"PRIx64, imm);
				}
				break;

			case X86_INS_RET:
				// RET imm16
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "$%u", imm);
				else {
					imm = 0xffff & imm;
					SStream_concat(O, "$0x%x", imm);
				}
				break;
		}

		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
			} else {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
				MI->has_imm = true;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;

				if (opsize > 0)
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize;
				else if (MI->op1_size > 0)
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->op1_size;
				else
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;

				MI->flat_insn->detail->x86.op_count++;
			}
		}
	}
}