@@ -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 )-> bh = cond ? PPC_BH_NO_SUBROUTINE_RET : PPC_BH_SUBROUTINE_RET ;
147+ break ;
148+ case 0b01 :
149+ PPC_get_detail (MI )-> bh = cond ? PPC_BH_RESERVED : PPC_BH_NO_SUBROUTINE_RET ;
150+ break ;
151+ case 0b10 :
152+ PPC_get_detail (MI )-> bh = PPC_BH_RESERVED ;
153+ break ;
154+ case 0b11 :
155+ PPC_get_detail (MI )-> 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
0 commit comments