static bool printSparcAliasInstr(MCInst *MI, SStream *O) { switch (MCInst_getOpcode(MI)) { default: return false; case SP_JMPLrr: case SP_JMPLri: if (MCInst_getNumOperands(MI) != 3) return false; if (!MCOperand_isReg(MCInst_getOperand(MI, 0))) return false; switch (MCOperand_getReg(MCInst_getOperand(MI, 0))) { default: return false; case SP_G0: // jmp $addr | ret | retl if (MCOperand_isImm(MCInst_getOperand(MI, 2)) && MCOperand_getImm(MCInst_getOperand(MI, 2)) == 8) { switch(MCOperand_getReg(MCInst_getOperand(MI, 1))) { default: break; case SP_I7: SStream_concat0(O, "ret"); MCInst_setOpcodePub(MI, SPARC_INS_RET); return true; case SP_O7: SStream_concat0(O, "retl"); MCInst_setOpcodePub(MI, SPARC_INS_RETL); return true; } } SStream_concat0(O, "jmp\t"); MCInst_setOpcodePub(MI, SPARC_INS_JMP); printMemOperand(MI, 1, O, NULL); return true; case SP_O7: // call $addr SStream_concat0(O, "call "); MCInst_setOpcodePub(MI, SPARC_INS_CALL); printMemOperand(MI, 1, O, NULL); return true; } case SP_V9FCMPS: case SP_V9FCMPD: case SP_V9FCMPQ: case SP_V9FCMPES: case SP_V9FCMPED: case SP_V9FCMPEQ: if (MI->csh->mode & CS_MODE_V9 || (MCInst_getNumOperands(MI) != 3) || (!MCOperand_isReg(MCInst_getOperand(MI, 0))) || (MCOperand_getReg(MCInst_getOperand(MI, 0)) != SP_FCC0)) return false; // if V8, skip printing %fcc0. switch(MCInst_getOpcode(MI)) { default: case SP_V9FCMPS: SStream_concat0(O, "fcmps\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPS); break; case SP_V9FCMPD: SStream_concat0(O, "fcmpd\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPD); break; case SP_V9FCMPQ: SStream_concat0(O, "fcmpq\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPQ); break; case SP_V9FCMPES: SStream_concat0(O, "fcmpes\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPES); break; case SP_V9FCMPED: SStream_concat0(O, "fcmped\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPED); break; case SP_V9FCMPEQ: SStream_concat0(O, "fcmpeq\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPEQ); break; } printOperand(MI, 1, O); SStream_concat0(O, ", "); printOperand(MI, 2, O); return true; } }
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 Sparc_printInst(MCInst *MI, SStream *O, void *Info) { char *mnem, *p; char instr[64]; // Sparc has no instruction this long mnem = printAliasInstr(MI, O, Info); if (mnem) { // fixup instruction id due to the change in alias instruction strncpy(instr, mnem, strlen(mnem)); instr[strlen(mnem)] = '\0'; // does this contains hint with a coma? p = strchr(instr, ','); if (p) *p = '\0'; // now instr only has instruction mnemonic MCInst_setOpcodePub(MI, Sparc_map_insn(instr)); switch(MCInst_getOpcode(MI)) { case SP_BCOND: case SP_BCONDA: case SP_BPICCANT: case SP_BPICCNT: case SP_BPXCCANT: case SP_BPXCCNT: case SP_TXCCri: case SP_TXCCrr: if (MI->csh->detail) { // skip 'b', 't' MI->flat_insn->detail->sparc.cc = Sparc_map_ICC(instr + 1); MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem); } break; case SP_BPFCCANT: case SP_BPFCCNT: if (MI->csh->detail) { // skip 'fb' MI->flat_insn->detail->sparc.cc = Sparc_map_FCC(instr + 2); MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem); } break; case SP_FMOVD_ICC: case SP_FMOVD_XCC: case SP_FMOVQ_ICC: case SP_FMOVQ_XCC: case SP_FMOVS_ICC: case SP_FMOVS_XCC: if (MI->csh->detail) { // skip 'fmovd', 'fmovq', 'fmovs' MI->flat_insn->detail->sparc.cc = Sparc_map_ICC(instr + 5); MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem); } break; case SP_MOVICCri: case SP_MOVICCrr: case SP_MOVXCCri: case SP_MOVXCCrr: if (MI->csh->detail) { // skip 'mov' MI->flat_insn->detail->sparc.cc = Sparc_map_ICC(instr + 3); MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem); } break; case SP_V9FMOVD_FCC: case SP_V9FMOVQ_FCC: case SP_V9FMOVS_FCC: if (MI->csh->detail) { // skip 'fmovd', 'fmovq', 'fmovs' MI->flat_insn->detail->sparc.cc = Sparc_map_FCC(instr + 5); MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem); } break; case SP_V9MOVFCCri: case SP_V9MOVFCCrr: if (MI->csh->detail) { // skip 'mov' MI->flat_insn->detail->sparc.cc = Sparc_map_FCC(instr + 3); MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem); } break; default: break; } cs_mem_free(mnem); } else { if (!printSparcAliasInstr(MI, O)) printInstruction(MI, O, NULL); } }
void AArch64_printInst(MCInst *MI, SStream *O, void *Info) { // Check for special encodings and print the canonical alias instead. unsigned Opcode = MCInst_getOpcode(MI); int LSB; int Width; char *mnem; if (Opcode == AArch64_SYSxt && printSysAlias(MI, O)) return; // SBFM/UBFM should print to a nicer aliased form if possible. if (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri || Opcode == AArch64_UBFMXri || Opcode == AArch64_UBFMWri) { MCOperand *Op0 = MCInst_getOperand(MI, 0); MCOperand *Op1 = MCInst_getOperand(MI, 1); MCOperand *Op2 = MCInst_getOperand(MI, 2); MCOperand *Op3 = MCInst_getOperand(MI, 3); bool IsSigned = (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri); bool Is64Bit = (Opcode == AArch64_SBFMXri || Opcode == AArch64_UBFMXri); if (MCOperand_isImm(Op2) && MCOperand_getImm(Op2) == 0 && MCOperand_isImm(Op3)) { char *AsmMnemonic = NULL; switch (MCOperand_getImm(Op3)) { default: break; case 7: if (IsSigned) AsmMnemonic = "sxtb"; else if (!Is64Bit) AsmMnemonic = "uxtb"; break; case 15: if (IsSigned) AsmMnemonic = "sxth"; else if (!Is64Bit) AsmMnemonic = "uxth"; break; case 31: // *xtw is only valid for signed 64-bit operations. if (Is64Bit && IsSigned) AsmMnemonic = "sxtw"; break; } if (AsmMnemonic) { SStream_concat(O, "%s\t%s, %s", AsmMnemonic, getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName), getRegisterName(getWRegFromXReg(MCOperand_getReg(Op1)), AArch64_NoRegAltName)); if (MI->csh->detail) { MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = getWRegFromXReg(MCOperand_getReg(Op1)); MI->flat_insn->detail->arm64.op_count++; } MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic)); return; } } // All immediate shifts are aliases, implemented using the Bitfield // instruction. In all cases the immediate shift amount shift must be in // the range 0 to (reg.size -1). if (MCOperand_isImm(Op2) && MCOperand_isImm(Op3)) { char *AsmMnemonic = NULL; int shift = 0; int immr = (int)MCOperand_getImm(Op2); int imms = (int)MCOperand_getImm(Op3); if (Opcode == AArch64_UBFMWri && imms != 0x1F && ((imms + 1) == immr)) { AsmMnemonic = "lsl"; shift = 31 - imms; } else if (Opcode == AArch64_UBFMXri && imms != 0x3f && ((imms + 1 == immr))) { AsmMnemonic = "lsl"; shift = 63 - imms; } else if (Opcode == AArch64_UBFMWri && imms == 0x1f) { AsmMnemonic = "lsr"; shift = immr; } else if (Opcode == AArch64_UBFMXri && imms == 0x3f) { AsmMnemonic = "lsr"; shift = immr; } else if (Opcode == AArch64_SBFMWri && imms == 0x1f) { AsmMnemonic = "asr"; shift = immr; } else if (Opcode == AArch64_SBFMXri && imms == 0x3f) { AsmMnemonic = "asr"; shift = immr; } if (AsmMnemonic) { SStream_concat(O, "%s\t%s, %s, ", AsmMnemonic, getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName), getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName)); printInt32Bang(O, shift); MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic)); if (MI->csh->detail) { MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = shift; MI->flat_insn->detail->arm64.op_count++; } return; } } // SBFIZ/UBFIZ aliases if (MCOperand_getImm(Op2) > MCOperand_getImm(Op3)) { SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfiz" : "ubfiz"), getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName), getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName)); printInt32Bang(O, (int)((Is64Bit ? 64 : 32) - MCOperand_getImm(Op2))); SStream_concat0(O, ", "); printInt32Bang(O, (int)MCOperand_getImm(Op3) + 1); MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfiz" : "ubfiz")); if (MI->csh->detail) { MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (Is64Bit ? 64 : 32) - (int)MCOperand_getImm(Op2); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)MCOperand_getImm(Op3) + 1; MI->flat_insn->detail->arm64.op_count++; } return; } // Otherwise SBFX/UBFX is the preferred form SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfx" : "ubfx"), getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName), getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName)); printInt32Bang(O, (int)MCOperand_getImm(Op2)); SStream_concat0(O, ", "); printInt32Bang(O, (int)MCOperand_getImm(Op3) - (int)MCOperand_getImm(Op2) + 1); MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfx" : "ubfx")); if (MI->csh->detail) { MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)MCOperand_getImm(Op2); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)MCOperand_getImm(Op3) - (int)MCOperand_getImm(Op2) + 1; MI->flat_insn->detail->arm64.op_count++; } return; } if (Opcode == AArch64_BFMXri || Opcode == AArch64_BFMWri) { MCOperand *Op0 = MCInst_getOperand(MI, 0); // Op1 == Op0 MCOperand *Op2 = MCInst_getOperand(MI, 2); int ImmR = (int)MCOperand_getImm(MCInst_getOperand(MI, 3)); int ImmS = (int)MCOperand_getImm(MCInst_getOperand(MI, 4)); // BFI alias if (ImmS < ImmR) { int BitWidth = Opcode == AArch64_BFMXri ? 64 : 32; LSB = (BitWidth - ImmR) % BitWidth; Width = ImmS + 1; SStream_concat(O, "bfi\t%s, %s, ", getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName), getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName)); printInt32Bang(O, LSB); SStream_concat0(O, ", "); printInt32Bang(O, Width); MCInst_setOpcodePub(MI, AArch64_map_insn("bfi")); if (MI->csh->detail) { MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB; MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width; MI->flat_insn->detail->arm64.op_count++; } return; } LSB = ImmR; Width = ImmS - ImmR + 1; // Otherwise BFXIL the preferred form SStream_concat(O, "bfxil\t%s, %s, ", getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName), getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName)); printInt32Bang(O, LSB); SStream_concat0(O, ", "); printInt32Bang(O, Width); MCInst_setOpcodePub(MI, AArch64_map_insn("bfxil")); if (MI->csh->detail) { MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2); MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB; MI->flat_insn->detail->arm64.op_count++; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width; MI->flat_insn->detail->arm64.op_count++; } return; } mnem = printAliasInstr(MI, O, Info); if (mnem) { MCInst_setOpcodePub(MI, AArch64_map_insn(mnem)); cs_mem_free(mnem); } else { printInstruction(MI, O, Info); } }
static bool printSysAlias(MCInst *MI, SStream *O) { // unsigned Opcode = MCInst_getOpcode(MI); //assert(Opcode == AArch64_SYSxt && "Invalid opcode for SYS alias!"); char *Asm = NULL; MCOperand *Op1 = MCInst_getOperand(MI, 0); MCOperand *Cn = MCInst_getOperand(MI, 1); MCOperand *Cm = MCInst_getOperand(MI, 2); MCOperand *Op2 = MCInst_getOperand(MI, 3); unsigned Op1Val = (unsigned)MCOperand_getImm(Op1); unsigned CnVal = (unsigned)MCOperand_getImm(Cn); unsigned CmVal = (unsigned)MCOperand_getImm(Cm); unsigned Op2Val = (unsigned)MCOperand_getImm(Op2); unsigned insn_id = ARM64_INS_INVALID; unsigned op_ic = 0, op_dc = 0, op_at = 0, op_tlbi = 0; if (CnVal == 7) { switch (CmVal) { default: break; // IC aliases case 1: if (Op1Val == 0 && Op2Val == 0) { Asm = "ic\tialluis"; insn_id = ARM64_INS_IC; op_ic = ARM64_IC_IALLUIS; } break; case 5: if (Op1Val == 0 && Op2Val == 0) { Asm = "ic\tiallu"; insn_id = ARM64_INS_IC; op_ic = ARM64_IC_IALLU; } else if (Op1Val == 3 && Op2Val == 1) { Asm = "ic\tivau"; insn_id = ARM64_INS_IC; op_ic = ARM64_IC_IVAU; } break; // DC aliases case 4: if (Op1Val == 3 && Op2Val == 1) { Asm = "dc\tzva"; insn_id = ARM64_INS_DC; op_dc = ARM64_DC_ZVA; } break; case 6: if (Op1Val == 0 && Op2Val == 1) { Asm = "dc\tivac"; insn_id = ARM64_INS_DC; op_dc = ARM64_DC_IVAC; } if (Op1Val == 0 && Op2Val == 2) { Asm = "dc\tisw"; insn_id = ARM64_INS_DC; op_dc = ARM64_DC_ISW; } break; case 10: if (Op1Val == 3 && Op2Val == 1) { Asm = "dc\tcvac"; insn_id = ARM64_INS_DC; op_dc = ARM64_DC_CVAC; } else if (Op1Val == 0 && Op2Val == 2) { Asm = "dc\tcsw"; insn_id = ARM64_INS_DC; op_dc = ARM64_DC_CSW; } break; case 11: if (Op1Val == 3 && Op2Val == 1) { Asm = "dc\tcvau"; insn_id = ARM64_INS_DC; op_dc = ARM64_DC_CVAU; } break; case 14: if (Op1Val == 3 && Op2Val == 1) { Asm = "dc\tcivac"; insn_id = ARM64_INS_DC; op_dc = ARM64_DC_CIVAC; } else if (Op1Val == 0 && Op2Val == 2) { Asm = "dc\tcisw"; insn_id = ARM64_INS_DC; op_dc = ARM64_DC_CISW; } break; // AT aliases case 8: switch (Op1Val) { default: break; case 0: switch (Op2Val) { default: break; case 0: Asm = "at\ts1e1r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1R; break; case 1: Asm = "at\ts1e1w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1W; break; case 2: Asm = "at\ts1e0r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0R; break; case 3: Asm = "at\ts1e0w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0W; break; } break; case 4: switch (Op2Val) { default: break; case 0: Asm = "at\ts1e2r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E2R; break; case 1: Asm = "at\ts1e2w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E2W; break; case 4: Asm = "at\ts12e1r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1R; break; case 5: Asm = "at\ts12e1w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1W; break; case 6: Asm = "at\ts12e0r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0R; break; case 7: Asm = "at\ts12e0w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0W; break; } break; case 6: switch (Op2Val) { default: break; case 0: Asm = "at\ts1e3r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E3R; break; case 1: Asm = "at\ts1e3w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E3W; break; } break; } break; } } else if (CnVal == 8) { // TLBI aliases switch (CmVal) { default: break; case 3: switch (Op1Val) { default: break; case 0: switch (Op2Val) { default: break; case 0: Asm = "tlbi\tvmalle1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLE1IS; break; case 1: Asm = "tlbi\tvae1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE1IS; break; case 2: Asm = "tlbi\taside1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ASIDE1IS; break; case 3: Asm = "tlbi\tvaae1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAAE1IS; break; case 5: Asm = "tlbi\tvale1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE1IS; break; case 7: Asm = "tlbi\tvaale1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAALE1IS; break; } break; case 4: switch (Op2Val) { default: break; case 0: Asm = "tlbi\talle2is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE2IS; break; case 1: Asm = "tlbi\tvae2is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE2IS; break; case 4: Asm = "tlbi\talle1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE1IS; break; case 5: Asm = "tlbi\tvale2is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE2IS; break; case 6: Asm = "tlbi\tvmalls12e1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLS12E1IS; break; } break; case 6: switch (Op2Val) { default: break; case 0: Asm = "tlbi\talle3is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE3IS; break; case 1: Asm = "tlbi\tvae3is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE3IS; break; case 5: Asm = "tlbi\tvale3is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE3IS; break; } break; } break; case 0: switch (Op1Val) { default: break; case 4: switch (Op2Val) { default: break; case 1: Asm = "tlbi\tipas2e1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2E1IS; break; case 5: Asm = "tlbi\tipas2le1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2LE1IS; break; } break; } break; case 4: switch (Op1Val) { default: break; case 4: switch (Op2Val) { default: break; case 1: Asm = "tlbi\tipas2e1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2E1; break; case 5: Asm = "tlbi\tipas2le1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2LE1; break; } break; } break; case 7: switch (Op1Val) { default: break; case 0: switch (Op2Val) { default: break; case 0: Asm = "tlbi\tvmalle1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLE1; break; case 1: Asm = "tlbi\tvae1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE1; break; case 2: Asm = "tlbi\taside1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ASIDE1; break; case 3: Asm = "tlbi\tvaae1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAAE1; break; case 5: Asm = "tlbi\tvale1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE1; break; case 7: Asm = "tlbi\tvaale1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAALE1; break; } break; case 4: switch (Op2Val) { default: break; case 0: Asm = "tlbi\talle2"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE2; break; case 1: Asm = "tlbi\tvae2"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE2; break; case 4: Asm = "tlbi\talle1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE1; break; case 5: Asm = "tlbi\tvale2"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE2; break; case 6: Asm = "tlbi\tvmalls12e1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLS12E1; break; } break; case 6: switch (Op2Val) { default: break; case 0: Asm = "tlbi\talle3"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE3; break; case 1: Asm = "tlbi\tvae3"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE3; break; case 5: Asm = "tlbi\tvale3"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE3; break; } break; } break; } } if (Asm) { MCInst_setOpcodePub(MI, insn_id); SStream_concat0(O, Asm); if (MI->csh->detail) { MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = op_ic + op_dc + op_at + op_tlbi; MI->flat_insn->detail->arm64.op_count++; } if (!strstr(Asm, "all")) { unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, 4)); SStream_concat(O, ", %s", getRegisterName(Reg, AArch64_NoRegAltName)); if (MI->csh->detail) { MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG; MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg; MI->flat_insn->detail->arm64.op_count++; } } } return Asm != NULL; }
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 } }