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; } }
static void printSaveRestore(MCInst *MI, SStream *O) { unsigned i, e; for (i = 0, e = MCInst_getNumOperands(MI); i != e; ++i) { if (i != 0) SStream_concat(O, ", "); if (MCOperand_isReg(MCInst_getOperand(MI, i))) printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, i))); else printUnsignedImm(MI, i, O); } }
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; }