mirror of
https://github.com/capstone-engine/capstone.git
synced 2025-02-10 00:23:01 +00:00
PPC: Fix absolute/relative offset for branch instruction
PPC: Fix non handling of bc instruction that uses the CTR
This commit is contained in:
parent
39eb84a9b1
commit
a3f0aef79a
@ -145,7 +145,8 @@ void PPC_printInst(MCInst *MI, SStream *O, void *Info)
|
||||
}
|
||||
}
|
||||
|
||||
if (MCInst_getOpcode(MI) == PPC_gBC) {
|
||||
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);
|
||||
@ -526,18 +527,13 @@ static void printAbsBranchOperand(MCInst *MI, unsigned OpNo, SStream *O)
|
||||
}
|
||||
|
||||
imm = ((int)MCOperand_getImm(MCInst_getOperand(MI, OpNo)) << 2);
|
||||
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 (!PPC_abs_branch(MI->csh, MCInst_getOpcode(MI))) {
|
||||
imm = (int)MI->address + imm;
|
||||
}
|
||||
|
||||
SStream_concat(O, ".0x%x", imm);
|
||||
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
|
||||
MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = imm;
|
||||
@ -740,7 +736,7 @@ 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;
|
||||
int needComma;
|
||||
int decCtr, needComma;
|
||||
char *tmp, *AsmMnem, *AsmOps, *c;
|
||||
int OpIdx, PrintMethodIdx;
|
||||
MCRegisterInfo *MRI = (MCRegisterInfo *)info;
|
||||
@ -775,33 +771,23 @@ static char *printAliasInstrEx(MCInst *MI, SStream *OS, void *info)
|
||||
|
||||
if (MCInst_getNumOperands(MI) == 3 &&
|
||||
MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
|
||||
(MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 12) &&
|
||||
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, "+");
|
||||
(MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 0) &&
|
||||
(MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 1)) {
|
||||
SStream_concat(&ss, opCode, "dnzf");
|
||||
decCtr = 1;
|
||||
}
|
||||
|
||||
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 = 1;
|
||||
}
|
||||
|
||||
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)) {
|
||||
@ -825,50 +811,115 @@ static char *printAliasInstrEx(MCInst *MI, SStream *OS, void *info)
|
||||
SStream_concat0(&ss, "-");
|
||||
if(MCOperand_getImm(MCInst_getOperand(MI, 0)) == 7)
|
||||
SStream_concat0(&ss, "+");
|
||||
|
||||
decCtr = 0;
|
||||
}
|
||||
|
||||
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 = 1;
|
||||
}
|
||||
|
||||
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 = 1;
|
||||
}
|
||||
|
||||
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 = 0;
|
||||
}
|
||||
|
||||
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 = 0;
|
||||
}
|
||||
|
||||
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 = 0;
|
||||
}
|
||||
|
||||
if (MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
|
||||
GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 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)));
|
||||
switch(cr) {
|
||||
case PPC_CR1:
|
||||
SStream_concat0(&ss, " cr1");
|
||||
op_addReg(MI, PPC_REG_CR1);
|
||||
if(decCtr) {
|
||||
needComma = 1;
|
||||
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");
|
||||
break;
|
||||
case CRGT:
|
||||
SStream_concat0(&ss, "gt");
|
||||
break;
|
||||
case CRLT:
|
||||
SStream_concat0(&ss, "lt");
|
||||
break;
|
||||
case CRUN:
|
||||
SStream_concat0(&ss, "so");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(cr > PPC_CR0) {
|
||||
needComma = 1;
|
||||
break;
|
||||
case PPC_CR2:
|
||||
SStream_concat0(&ss, " cr2");
|
||||
op_addReg(MI, PPC_REG_CR2);
|
||||
needComma = 1;
|
||||
break;
|
||||
case PPC_CR3:
|
||||
SStream_concat0(&ss, " cr3");
|
||||
op_addReg(MI, PPC_REG_CR3);
|
||||
needComma = 1;
|
||||
break;
|
||||
case PPC_CR4:
|
||||
SStream_concat0(&ss, " cr4");
|
||||
op_addReg(MI, PPC_REG_CR4);
|
||||
needComma = 1;
|
||||
break;
|
||||
case PPC_CR5:
|
||||
SStream_concat0(&ss, " cr5");
|
||||
op_addReg(MI, PPC_REG_CR5);
|
||||
needComma = 1;
|
||||
break;
|
||||
case PPC_CR6:
|
||||
SStream_concat0(&ss, " cr6");
|
||||
op_addReg(MI, PPC_REG_CR6);
|
||||
needComma = 1;
|
||||
break;
|
||||
case PPC_CR7:
|
||||
SStream_concat0(&ss, " cr7");
|
||||
op_addReg(MI, PPC_REG_CR7);
|
||||
needComma = 1;
|
||||
break;
|
||||
default:
|
||||
SStream_concat(&ss, " cr%d", cr-PPC_CR0);
|
||||
} else {
|
||||
needComma = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8104,4 +8104,41 @@ bool PPC_alias_insn(const char *name, struct ppc_alias *alias)
|
||||
return false;
|
||||
}
|
||||
|
||||
// list all relative branch instructions
|
||||
static unsigned int insn_abs[] = {
|
||||
PPC_BA,
|
||||
PPC_BCCA,
|
||||
PPC_BCCLA,
|
||||
PPC_BDNZA,
|
||||
PPC_BDNZAm,
|
||||
PPC_BDNZAp,
|
||||
PPC_BDNZLA,
|
||||
PPC_BDNZLAm,
|
||||
PPC_BDNZLAp,
|
||||
PPC_BDZA,
|
||||
PPC_BDZAm,
|
||||
PPC_BDZAp,
|
||||
PPC_BDZLAm,
|
||||
PPC_BDZLAp,
|
||||
PPC_BLA,
|
||||
PPC_gBCA,
|
||||
PPC_gBCLA,
|
||||
0
|
||||
};
|
||||
|
||||
// check if this insn is relative branch
|
||||
bool PPC_abs_branch(cs_struct *h, unsigned int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; insn_abs[i]; i++) {
|
||||
if (id == insn_abs[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// not found
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -27,5 +27,8 @@ struct ppc_alias {
|
||||
// given alias mnemonic, return instruction ID & CC
|
||||
bool PPC_alias_insn(const char *name, struct ppc_alias *alias);
|
||||
|
||||
// check if this insn is relative branch
|
||||
bool PPC_abs_branch(cs_struct *h, unsigned int id);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -19,6 +19,11 @@ CODE32 += b"\x40\x9f\x10\x30" # bns cr5,.+0x94
|
||||
CODE32 += b"\x42\x00\xff\xd8" # bdnz .-0x28
|
||||
CODE32 += b"\x4d\x82\x00\x20" # beqlr
|
||||
CODE32 += b"\x4e\x80\x00\x20" # blr
|
||||
CODE32 += b"\x4a\x00\x00\x02" # ba .0xfe000000
|
||||
CODE32 += b"\x41\x80\xff\xda" # blta .0xffffffd8
|
||||
CODE32 += b"\x41\x4f\xff\x17" # bdztla 4*cr3+so, .0xffffff14
|
||||
CODE32 += b"\x43\x20\x0c\x07" # bdnzla+ .0xc04
|
||||
CODE32 += b"\x4c\x00\x04\x20" # bdnzfctr lt
|
||||
|
||||
_python3 = sys.version_info.major == 3
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user