/* Capstone Disassembly Engine, http://www.capstone-engine.org */ /* By Nguyen Anh Quynh , 2013-2022, */ /* Rot127 2022-2023 */ /* Automatically translated source file from LLVM. */ /* LLVM-commit: */ /* LLVM-tag: */ /* Only small edits allowed. */ /* For multiple similar edits, please create a Patch for the translator. */ /* Capstone's C++ file translator: */ /* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */ //===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This class prints an PPC MCInst to a .s file. // //===----------------------------------------------------------------------===// #include #include #include #include #include "../../LEB128.h" #include "../../Mapping.h" #include "../../MCInst.h" #include "../../MCInstPrinter.h" #include "../../MCInstrDesc.h" #include "../../MCRegisterInfo.h" #include "PPCInstrInfo.h" #include "PPCInstPrinter.h" #include "PPCLinkage.h" #include "PPCMCTargetDesc.h" #include "PPCMapping.h" #include "PPCPredicates.h" #include "PPCRegisterInfo.h" #define CONCAT(a, b) CONCAT_(a, b) #define CONCAT_(a, b) a##_##b #define DEBUG_TYPE "asm-printer" // Static function declarations. These are functions which have the same identifiers // over all architectures. Therefor they need to be static. #ifndef CAPSTONE_DIET static void printCustomAliasOperand(MCInst *MI, uint64_t Address, unsigned OpIdx, unsigned PrintMethodIdx, SStream *O); #endif static void printOperand(MCInst *MI, unsigned OpNo, SStream *O); static void printPredicateOperand(MCInst *MI, unsigned OpNo, SStream *O, const char *Modifier); static void printInst(MCInst *MI, uint64_t Address, const char *Annot, SStream *O); #define PRINT_ALIAS_INSTR #include "PPCGenAsmWriter.inc" static void printInst(MCInst *MI, uint64_t Address, const char *Annot, SStream *O) { bool isAlias = false; bool useAliasDetails = false; // Customize printing of the addis instruction on AIX. When an operand is a // symbol reference, the instruction syntax is changed to look like a load // operation, i.e: // Transform: addis $rD, $rA, $src --> addis $rD, $src($rA). if (PPC_getFeatureBits(MI->csh->mode, PPC_FeatureModernAIXAs) && (MCInst_getOpcode(MI) == PPC_ADDIS8 || MCInst_getOpcode(MI) == PPC_ADDIS) && MCOperand_isExpr(MCInst_getOperand(MI, (2)))) { SStream_concat0(O, "\taddis "); printOperand(MI, 0, O); SStream_concat0(O, ", "); printOperand(MI, 2, O); SStream_concat0(O, "("); printOperand(MI, 1, O); SStream_concat0(O, ")"); return; } // Check if the last operand is an expression with the variant kind // VK_PPC_PCREL_OPT. If this is the case then this is a linker optimization // relocation and the .reloc directive needs to be added. unsigned LastOp = MCInst_getNumOperands(MI) - 1; if (MCInst_getNumOperands(MI) > 1) { MCOperand *Operand = MCInst_getOperand(MI, (LastOp)); if (MCOperand_isExpr(Operand)) { assert(0 && "Expressions not supported."); } } // Check for slwi/srwi mnemonics. if (MCInst_getOpcode(MI) == PPC_RLWINM) { unsigned char SH = MCOperand_getImm(MCInst_getOperand(MI, (2))); unsigned char MB = MCOperand_getImm(MCInst_getOperand(MI, (3))); unsigned char ME = MCOperand_getImm(MCInst_getOperand(MI, (4))); bool useSubstituteMnemonic = false; if (SH <= 31 && MB == 0 && ME == (31 - SH)) { SStream_concat0(O, "slwi "); useSubstituteMnemonic = true; } if (SH <= 31 && MB == (32 - SH) && ME == 31) { SStream_concat0(O, "srwi "); useSubstituteMnemonic = true; SH = 32 - SH; } useAliasDetails |= map_use_alias_details(MI); map_set_fill_detail_ops(MI, useAliasDetails && useSubstituteMnemonic); if (useSubstituteMnemonic) { isAlias |= true; MCInst_setIsAlias(MI, isAlias); printOperand(MI, 0, O); SStream_concat0(O, ", "); printOperand(MI, 1, O); SStream_concat(O, "%s", ", "); printUInt32(O, (unsigned int)SH); PPC_insert_detail_op_imm_at(MI, 2, SH, CS_AC_READ); if (useAliasDetails) return; } } if (MCInst_getOpcode(MI) == PPC_RLDICR || MCInst_getOpcode(MI) == PPC_RLDICR_32) { unsigned char SH = MCOperand_getImm(MCInst_getOperand(MI, (2))); unsigned char ME = MCOperand_getImm(MCInst_getOperand(MI, (3))); useAliasDetails |= map_use_alias_details(MI); map_set_fill_detail_ops(MI, useAliasDetails && 63 - SH == ME); // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH if (63 - SH == ME) { isAlias |= true; MCInst_setIsAlias(MI, isAlias); SStream_concat0(O, "sldi "); printOperand(MI, 0, O); SStream_concat0(O, ", "); printOperand(MI, 1, O); SStream_concat(O, "%s", ", "); printUInt32(O, (unsigned int)SH); PPC_insert_detail_op_imm_at(MI, 2, SH, CS_AC_READ); if (useAliasDetails) return; } } // dcbt[st] is printed manually here because: // 1. The assembly syntax is different between embedded and server targets // 2. We must print the short mnemonics for TH == 0 because the // embedded/server syntax default will not be stable across assemblers // The syntax for dcbt is: // dcbt ra, rb, th [server] // dcbt th, ra, rb [embedded] // where th can be omitted when it is 0. dcbtst is the same. // On AIX, only emit the extended mnemonics for dcbt and dcbtst if // the "modern assembler" is available. if ((MCInst_getOpcode(MI) == PPC_DCBT || MCInst_getOpcode(MI) == PPC_DCBTST) && (!PPC_getFeatureBits(MI->csh->mode, PPC_FeatureModernAIXAs))) { unsigned char TH = MCOperand_getImm(MCInst_getOperand(MI, (0))); SStream_concat0(O, "\tdcbt"); if (MCInst_getOpcode(MI) == PPC_DCBTST) SStream_concat0(O, "st"); if (TH == 16) SStream_concat0(O, "t"); SStream_concat0(O, " "); bool IsBookE = PPC_getFeatureBits(MI->csh->mode, PPC_FeatureBookE); if (IsBookE && TH != 0 && TH != 16) { SStream_concat(O, "%s", (unsigned int)TH); SStream_concat0(O, ", "); PPC_set_detail_op_imm(MI, 0, TH); } set_mem_access(MI, true); printOperand(MI, 1, O); SStream_concat0(O, ", "); printOperand(MI, 2, O); set_mem_access(MI, false); if (!IsBookE && TH != 0 && TH != 16) { SStream_concat(O, "%s", ", "); printUInt32(O, (unsigned int)TH); PPC_set_detail_op_imm(MI, 0, TH); } return; } if (MCInst_getOpcode(MI) == PPC_DCBF) { unsigned char L = MCOperand_getImm(MCInst_getOperand(MI, (0))); if (!L || L == 1 || L == 3 || L == 4 || L == 6) { SStream_concat0(O, "\tdcb"); if (L != 6) SStream_concat0(O, "f"); if (L == 1) SStream_concat0(O, "l"); if (L == 3) SStream_concat0(O, "lp"); if (L == 4) SStream_concat0(O, "ps"); if (L == 6) SStream_concat0(O, "stps"); SStream_concat0(O, " "); printOperand(MI, 1, O); SStream_concat0(O, ", "); printOperand(MI, 2, O); return; } } // isAlias/useAliasDetails could have been set before. useAliasDetails |= map_use_alias_details(MI); map_set_fill_detail_ops(MI, useAliasDetails); isAlias |= printAliasInstr(MI, Address, O); MCInst_setIsAlias(MI, isAlias); if (!isAlias || !useAliasDetails) { map_set_fill_detail_ops(MI, true); if (isAlias) SStream_Close(O); printInstruction(MI, Address, O); if (isAlias) SStream_Open(O); } } void printPredicateOperand(MCInst *MI, unsigned OpNo, SStream *O, const char *Modifier) { add_cs_detail(MI, PPC_OP_GROUP_PredicateOperand, OpNo, Modifier); unsigned Code = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); if (strcmp(Modifier, "cc") == 0) { switch ((PPC_Predicate)Code) { default: assert(0 && "Invalid predicate code"); 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: assert(0 && "Invalid use of bit predicate code"); } assert(0 && "Invalid predicate code"); } if (strcmp(Modifier, "pm") == 0) { switch ((PPC_Predicate)Code) { default: assert(0 && "Invalid 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: assert(0 && "Invalid use of bit predicate code"); } assert(0 && "Invalid predicate code"); } printOperand(MI, OpNo + 1, O); } void printATBitsAsHint(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_ATBitsAsHint, OpNo); unsigned Code = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); if (Code == 2) SStream_concat0(O, "-"); else if (Code == 3) SStream_concat0(O, "+"); } void printU1ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U1ImmOperand, OpNo); unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned int)Value); } void printU2ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U2ImmOperand, OpNo); unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned int)Value); } void printU3ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U3ImmOperand, OpNo); unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned int)Value); } void printU4ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U4ImmOperand, OpNo); unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned int)Value); } void printS5ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_S5ImmOperand, OpNo); int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); Value = SignExtend32((Value), 5); printInt32(O, (int)Value); } void printImmZeroOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_ImmZeroOperand, OpNo); unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned int)Value); } void printU5ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U5ImmOperand, OpNo); unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned int)Value); } void printU6ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U6ImmOperand, OpNo); unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned int)Value); } void printU7ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U7ImmOperand, OpNo); unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned int)Value); } // Operands of BUILD_VECTOR are signed and we use this to print operands // of XXSPLTIB which are unsigned. So we simply truncate to 8 bits and // print as unsigned. void printU8ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U8ImmOperand, OpNo); unsigned char Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned int)Value); } void printU10ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U10ImmOperand, OpNo); unsigned short Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned short)Value); } void printU12ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U12ImmOperand, OpNo); unsigned short Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printUInt32(O, (unsigned short)Value); } void printS12ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_S12ImmOperand, OpNo); if (MCOperand_isImm(MCInst_getOperand(MI, OpNo))) { int Imm = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo)); Imm = SignExtend32(Imm, 12); printInt32(O, Imm); } else printOperand(MI, OpNo, O); } void printMemRegImmPS(MCInst *MI, unsigned OpNo, SStream *O) { set_mem_access(MI, true); printS12ImmOperand(MI, OpNo, O); SStream_concat0(O, "("); printOperand(MI, OpNo + 1, O); SStream_concat0(O, ")"); set_mem_access(MI, false); } void printS16ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_S16ImmOperand, OpNo); if (MCOperand_isImm(MCInst_getOperand(MI, (OpNo)))) printInt32(O, (short)MCOperand_getImm( MCInst_getOperand(MI, (OpNo)))); else printOperand(MI, OpNo, O); } void printS34ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_S34ImmOperand, OpNo); if (MCOperand_isImm(MCInst_getOperand(MI, (OpNo)))) { long long Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); printInt64(O, (long long)Value); } else printOperand(MI, OpNo, O); } void printU16ImmOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_U16ImmOperand, OpNo); if (MCOperand_isImm(MCInst_getOperand(MI, (OpNo)))) printUInt32(O, (unsigned short)MCOperand_getImm( MCInst_getOperand(MI, (OpNo)))); else printOperand(MI, OpNo, O); } void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_BranchOperand, OpNo); if (!MCOperand_isImm(MCInst_getOperand(MI, (OpNo)))) { printOperand(MI, OpNo, O); return; } int32_t Imm = SignExtend32( ((unsigned)MCOperand_getImm(MCInst_getOperand(MI, (OpNo))) << 2), 32); if (!MI->csh->PrintBranchImmNotAsAddress) { uint64_t Target = Address + Imm; if (!IS_64BIT(MI->csh->mode)) Target &= 0xffffffff; printUInt64(O, (Target)); } else { // Branches can take an immediate operand. This is used by the branch // selection pass to print, for example `.+8` (for ELF) or `$+8` (for // AIX) to express an eight byte displacement from the program counter. if (!PPC_getFeatureBits(MI->csh->mode, PPC_FeatureModernAIXAs)) SStream_concat0(O, "."); else SStream_concat0(O, "$"); if (Imm >= 0) SStream_concat0(O, "+"); printInt32(O, Imm); } } void printAbsBranchOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_AbsBranchOperand, OpNo); if (!MCOperand_isImm(MCInst_getOperand(MI, (OpNo)))) { printOperand(MI, OpNo, O); return; } printInt32(O, SignExtend32(((unsigned)MCOperand_getImm( MCInst_getOperand(MI, (OpNo))) << 2), 32)); } void printcrbitm(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_crbitm, OpNo); unsigned CCReg = MCOperand_getReg(MCInst_getOperand(MI, (OpNo))); unsigned RegNo; switch (CCReg) { default: assert(0 && "Unknown CR register"); case PPC_CR0: RegNo = 0; break; case PPC_CR1: RegNo = 1; break; case PPC_CR2: RegNo = 2; break; case PPC_CR3: RegNo = 3; break; case PPC_CR4: RegNo = 4; break; case PPC_CR5: RegNo = 5; break; case PPC_CR6: RegNo = 6; break; case PPC_CR7: RegNo = 7; break; } printUInt32(O, (0x80 >> RegNo)); } void printMemRegImm(MCInst *MI, unsigned OpNo, SStream *O) { set_mem_access(MI, true); add_cs_detail(MI, PPC_OP_GROUP_MemRegImm, OpNo); printS16ImmOperand(MI, OpNo, O); SStream_concat0(O, "("); if (MCOperand_getReg(MCInst_getOperand(MI, (OpNo + 1))) == PPC_R0) SStream_concat0(O, "0"); else printOperand(MI, OpNo + 1, O); SStream_concat0(O, ")"); set_mem_access(MI, false); } void printMemRegImmHash(MCInst *MI, unsigned OpNo, SStream *O) { set_mem_access(MI, true); add_cs_detail(MI, PPC_OP_GROUP_MemRegImmHash, OpNo); printInt32(O, MCOperand_getImm(MCInst_getOperand(MI, (OpNo)))); SStream_concat0(O, "("); printOperand(MI, OpNo + 1, O); SStream_concat0(O, ")"); set_mem_access(MI, false); } void printMemRegImm34PCRel(MCInst *MI, unsigned OpNo, SStream *O) { set_mem_access(MI, true); add_cs_detail(MI, PPC_OP_GROUP_MemRegImm34PCRel, OpNo); printS34ImmOperand(MI, OpNo, O); SStream_concat0(O, "("); printImmZeroOperand(MI, OpNo + 1, O); SStream_concat0(O, ")"); set_mem_access(MI, false); } void printMemRegImm34(MCInst *MI, unsigned OpNo, SStream *O) { set_mem_access(MI, true); add_cs_detail(MI, PPC_OP_GROUP_MemRegImm34, OpNo); printS34ImmOperand(MI, OpNo, O); SStream_concat0(O, "("); printOperand(MI, OpNo + 1, O); SStream_concat0(O, ")"); set_mem_access(MI, false); } void printMemRegReg(MCInst *MI, unsigned OpNo, SStream *O) { set_mem_access(MI, true); add_cs_detail(MI, PPC_OP_GROUP_MemRegReg, OpNo); // When used as the base register, r0 reads constant zero rather than // the value contained in the register. For this reason, the darwin // assembler requires that we print r0 as 0 (no r) when used as the base. if (MCOperand_getReg(MCInst_getOperand(MI, (OpNo))) == PPC_R0) SStream_concat0(O, "0"); else printOperand(MI, OpNo, O); SStream_concat0(O, ", "); printOperand(MI, OpNo + 1, O); set_mem_access(MI, false); } void printTLSCall(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_TLSCall, OpNo); // Expression logic removed. set_mem_access(MI, true); SStream_concat0(O, "("); printOperand(MI, OpNo + 1, O); SStream_concat0(O, ")"); set_mem_access(MI, false); } /// showRegistersWithPercentPrefix - Check if this register name should be /// printed with a percentage symbol as prefix. bool showRegistersWithPercentPrefix(const MCInst *MI, const char *RegName) { if ((MI->csh->syntax & CS_OPT_SYNTAX_NOREGNAME) || !(MI->csh->syntax & CS_OPT_SYNTAX_PERCENT) || PPC_getFeatureBits(MI->csh->mode, PPC_FeatureModernAIXAs)) return false; switch (RegName[0]) { default: return false; case 'r': case 'f': case 'q': case 'v': case 'c': return true; } } /// getVerboseConditionalRegName - This method expands the condition register /// when requested explicitly or targeting Darwin. const char *getVerboseConditionRegName(const MCInst *MI, unsigned RegNum, unsigned RegEncoding) { if (MI->csh->syntax & CS_OPT_SYNTAX_NOREGNAME) return NULL; if (RegNum < PPC_CR0EQ || RegNum > PPC_CR7UN) return NULL; const char *CRBits[] = { "lt", "gt", "eq", "un", "4*cr1+lt", "4*cr1+gt", "4*cr1+eq", "4*cr1+un", "4*cr2+lt", "4*cr2+gt", "4*cr2+eq", "4*cr2+un", "4*cr3+lt", "4*cr3+gt", "4*cr3+eq", "4*cr3+un", "4*cr4+lt", "4*cr4+gt", "4*cr4+eq", "4*cr4+un", "4*cr5+lt", "4*cr5+gt", "4*cr5+eq", "4*cr5+un", "4*cr6+lt", "4*cr6+gt", "4*cr6+eq", "4*cr6+un", "4*cr7+lt", "4*cr7+gt", "4*cr7+eq", "4*cr7+un" }; return CRBits[RegEncoding]; } // showRegistersWithPrefix - This method determines whether registers // should be number-only or include the prefix. bool showRegistersWithPrefix(const MCInst *MI) { return !(MI->csh->syntax & CS_OPT_SYNTAX_NOREGNAME); } void printOperand(MCInst *MI, unsigned OpNo, SStream *O) { add_cs_detail(MI, PPC_OP_GROUP_Operand, OpNo); MCOperand *Op = MCInst_getOperand(MI, (OpNo)); if (MCOperand_isReg(Op)) { unsigned Reg = MCOperand_getReg(Op); if (!MI->csh->ShowVSRNumsAsVR) Reg = PPCInstrInfo_getRegNumForOperand( &PPCInsts[MCInst_getOpcode(MI)], Reg, OpNo); const char *RegName; RegName = getVerboseConditionRegName( MI, Reg, MI->MRI->RegEncodingTable[Reg]); if (RegName == NULL) RegName = getRegisterName(Reg); if (showRegistersWithPercentPrefix(MI, RegName)) SStream_concat0(O, "%"); if (!showRegistersWithPrefix(MI)) RegName = PPCRegisterInfo_stripRegisterPrefix(RegName); SStream_concat0(O, RegName); return; } if (MCOperand_isImm(Op)) { printInt64(O, MCOperand_getImm(Op)); return; } } const char *PPC_LLVM_getRegisterName(unsigned RegNo) { return getRegisterName(RegNo); } void PPC_LLVM_printInst(MCInst *MI, uint64_t Address, const char *Annot, SStream *O) { printInst(MI, Address, Annot, O); }