void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info) { char *mnem; unsigned int i; x86_reg reg; // Try to print any aliases first. mnem = printAliasInstr(MI, OS, NULL); if (mnem) cs_mem_free(mnem); else printInstruction(MI, OS, NULL); if (MI->csh->detail) { // special instruction needs to supply register op reg = X86_insn_reg(MCInst_getOpcode(MI)); if (reg) { // add register operand for (i = 0;; i++) { // find the first empty slot to put it there if (MI->flat_insn->detail->x86.operands[i].type == 0) { MI->flat_insn->detail->x86.operands[i].type = X86_OP_REG; MI->flat_insn->detail->x86.operands[i].reg = reg; MI->flat_insn->detail->x86.op_count++; break; } } } } }
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; } }
void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info) { char *mnem; x86_reg reg, reg2; enum cs_ac_type access1, access2; // Try to print any aliases first. mnem = printAliasInstr(MI, O, Info); if (mnem) cs_mem_free(mnem); else printInstruction(MI, O, Info); reg = X86_insn_reg_intel(MCInst_getOpcode(MI), &access1); if (MI->csh->detail) { #ifndef CAPSTONE_DIET uint8_t access[6]; #endif // first op can be embedded in the asm by llvm. // so we have to add the missing register as the first operand 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.operands[0].access = access1; MI->flat_insn->detail->x86.op_count++; } else { if (X86_insn_reg_intel2(MCInst_getOpcode(MI), ®, &access1, ®2, &access2)) { 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[0].access = access1; 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.operands[1].access = access2; 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 } if (MI->op1_size == 0 && reg) MI->op1_size = MI->csh->regsize_map[reg]; }
void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, const MCSubtargetInfo &STI) { unsigned Opcode = MI->getOpcode(); // First handle load and store instructions with postinc or predec // of the form "ld reg, X+". // TODO: We should be able to rewrite this using TableGen data. switch (Opcode) { case AVR::LDRdPtr: case AVR::LDRdPtrPi: case AVR::LDRdPtrPd: O << "\tld\t"; printOperand(MI, 0, O); O << ", "; if (Opcode == AVR::LDRdPtrPd) O << '-'; printOperand(MI, 1, O); if (Opcode == AVR::LDRdPtrPi) O << '+'; break; case AVR::STPtrRr: O << "\tst\t"; printOperand(MI, 0, O); O << ", "; printOperand(MI, 1, O); break; case AVR::STPtrPiRr: case AVR::STPtrPdRr: O << "\tst\t"; if (Opcode == AVR::STPtrPdRr) O << '-'; printOperand(MI, 1, O); if (Opcode == AVR::STPtrPiRr) O << '+'; O << ", "; printOperand(MI, 2, O); break; default: if (!printAliasInstr(MI, O)) printInstruction(MI, O); printAnnotation(O, Annot); break; } }
void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info) { //if (TSFlags & X86II::LOCK) // O << "\tlock\n"; if (printAliasInstr(MI, O)) { char *mnem = cs_strdup(O->buffer); char *tab = strchr(mnem, '\t'); if (tab) *tab = '\0'; // reflect the new insn name (alias) in the opcode MCInst_setOpcode(MI, X86_get_insn_id2(X86_map_insn(mnem))); cs_mem_free(mnem); } else printInstruction(MI, O, NULL); if (MI->csh->detail) { char tmp[64]; if (get_first_op(O->buffer, tmp)) { int post; char *acc_regs[] = { "al", "ax", "eax", "rax", NULL }; unsigned int acc_regs_id[] = { X86_REG_AL, X86_REG_AX, X86_REG_EAX, X86_REG_RAX }; if (tmp[0] != 0 && ((post = str_in_list(acc_regs, tmp)) != -1)) { // first op is register, so set operand size following register size MI->flat_insn.x86.op_size = 1 << post; // tmp is a register if ((MI->flat_insn.x86.operands[0].type != X86_OP_INVALID) && ((MI->flat_insn.x86.operands[0].type != X86_OP_REG) || (MI->flat_insn.x86.operands[0].reg != acc_regs_id[post]))) { // first op is register, so insert its detail to position 0 int i; for (i = MI->flat_insn.x86.op_count; i > 0; i--) { memcpy(&(MI->flat_insn.x86.operands[i]), &(MI->flat_insn.x86.operands[i - 1]), sizeof(MI->flat_insn.x86.operands[0])); } MI->flat_insn.x86.operands[0].type = X86_OP_REG; MI->flat_insn.x86.operands[0].reg = x86_map_regname(tmp); MI->flat_insn.x86.op_count++; } } } } }
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); } }
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); }
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), ®, ®2)) { 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), ®, ®2)) { 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 } }