Skip to content

Commit 5563507

Browse files
committed
Decode branch predicates and BH fields.
1 parent a2b4184 commit 5563507

File tree

3 files changed

+74
-3
lines changed

3 files changed

+74
-3
lines changed

arch/PowerPC/PPCMapping.c

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,72 @@ void PPC_check_updates_cr0(MCInst *MI)
9999
#endif // CAPSTONE_DIET
100100
}
101101

102-
void PPC_set_instr_map_data(MCInst *MI)
102+
/// Parses and adds the branch predicate information and the BH field.
103+
static void PPC_add_branch_predicates(MCInst *MI, const uint8_t *Bytes, size_t BytesLen) {
104+
#ifndef CAPSTONE_DIET
105+
assert(MI && Bytes);
106+
if (BytesLen < 4)
107+
return;
108+
109+
ppc_insn_form form = ppc_insns[MI->Opcode].suppl_info.ppc.form;
110+
bool b_form = ppc_is_b_form(form);
111+
if (!(b_form || form == PPC_INSN_FORM_XLFORM_2))
112+
return;
113+
114+
uint32_t Inst = readBytes32(MI, Bytes);
115+
printf("0x%x\n", Inst);
116+
117+
uint8_t bi = 0;
118+
if (b_form)
119+
bi = (Inst & PPC_INSN_FORM_B_BI_MASK) >> 16;
120+
else
121+
bi = (Inst & PPC_INSN_FORM_XL_BI_MASK) >> 16;
122+
123+
uint8_t bo = 0;
124+
if (b_form)
125+
bo = (Inst & PPC_INSN_FORM_B_BO_MASK) >> 21;
126+
else
127+
bo = (Inst & PPC_INSN_FORM_XL_BO_MASK) >> 21;
128+
129+
PPC_get_detail(MI)->bc.bi = bi;
130+
PPC_get_detail(MI)->bc.bo = bo;
131+
PPC_get_detail(MI)->bc.hint = PPC_get_hint(bo);
132+
PPC_get_detail(MI)->bc.pred = (bi << 5) | bo;
133+
if (ppc_is_b_form(form))
134+
return;
135+
136+
uint8_t bh = (Inst & PPC_INSN_FORM_XL_BH_MASK) >> 11;
137+
uint16_t xo = (Inst & PPC_INSN_FORM_XL_XO_MASK) >> 1;
138+
// Pre-defined values for XO fields (PowerISA v3.1B)
139+
uint16_t bcctr_xo_field = 528;
140+
uint16_t bctar_xo_field = 560;
141+
bool cond = (xo == bcctr_xo_field || xo == bctar_xo_field);
142+
switch (bh) {
143+
default:
144+
assert(0 && "Invalid BH value.");
145+
case 0b00:
146+
PPC_get_detail(MI)->bc.bh = cond ? PPC_BH_NO_SUBROUTINE_RET : PPC_BH_SUBROUTINE_RET;
147+
break;
148+
case 0b01:
149+
PPC_get_detail(MI)->bc.bh = cond ? PPC_BH_RESERVED : PPC_BH_NO_SUBROUTINE_RET;
150+
break;
151+
case 0b10:
152+
PPC_get_detail(MI)->bc.bh = PPC_BH_RESERVED;
153+
break;
154+
case 0b11:
155+
PPC_get_detail(MI)->bc.bh = PPC_BH_NOT_PREDICTABLE;
156+
break;
157+
}
158+
#endif // CAPSTONE_DIET
159+
}
160+
161+
void PPC_set_instr_map_data(MCInst *MI, const uint8_t *Bytes, size_t BytesLen)
103162
{
104163
map_cs_id(MI, ppc_insns, ARR_SIZE(ppc_insns));
105164
map_implicit_reads(MI, ppc_insns);
106165
map_implicit_writes(MI, ppc_insns);
107166
map_groups(MI, ppc_insns);
167+
PPC_add_branch_predicates(MI, Bytes, BytesLen);
108168
PPC_check_updates_cr0(MI);
109169
}
110170

@@ -128,7 +188,7 @@ bool PPC_getInstruction(csh handle, const uint8_t *bytes, size_t bytes_len,
128188
void *info) {
129189
PPC_init_cs_detail(instr);
130190
DecodeStatus result = PPC_LLVM_getInstruction(handle, bytes, bytes_len, instr, size, address, info);
131-
PPC_set_instr_map_data(instr);
191+
PPC_set_instr_map_data(instr, bytes, bytes_len);
132192
return result != MCDisassembler_Fail;
133193
}
134194

arch/PowerPC/PPCMapping.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ void PPC_set_detail_op_mem(MCInst *MI, unsigned OpNum, uint64_t Val, bool is_off
6868

6969
ppc_pred PPC_get_no_hint_pred(unsigned Code);
7070
void PPC_check_updates_cr0(MCInst *MI);
71-
void PPC_set_instr_map_data(MCInst *MI);
71+
void PPC_set_instr_map_data(MCInst *MI, const uint8_t *Bytes, size_t BytesLen);
7272

7373
#endif
7474

include/capstone/ppc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,22 @@ typedef enum {
120120
PPC_BR_HINT_MASK = 0b11
121121
} ppc_br_hint;
122122

123+
/// Encodes the different meanings of the BH field.
124+
/// The enum values does NOT match the BH field values!
125+
typedef enum {
126+
PPC_BH_INVALID = 0,
127+
PPC_BH_SUBROUTINE_RET,
128+
PPC_BH_NO_SUBROUTINE_RET,
129+
PPC_BH_NOT_PREDICTABLE,
130+
PPC_BH_RESERVED,
131+
} ppc_bh;
132+
123133
typedef struct {
124134
ppc_bi bi; ///< BI field of branch condition.
125135
uint8_t bo; ///< BO field of branch condition.
126136
ppc_br_hint hint; ///< The encoded hint.
127137
ppc_pred pred; ///< Resulting branch predicate.
138+
ppc_bh bh; ///< The BH field hint if any is present.
128139
} ppc_bc;
129140

130141
/// Returns the hint encoded in the BO bits a and t.

0 commit comments

Comments
 (0)