/*
Integer Branch Instructions
*/
-static Bool dis_branch ( UInt theInstr, DisResult* dres )
+static Bool dis_branch ( UInt theInstr,
+ /*OUT*/DisResult* dres,
+ Bool (*resteerOkFn)(Addr64) )
{
UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */
UChar BO = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */
Addr32 nia = 0;
- // IRTemp ctr = newTemp(Ity_I32);
- // IRTemp lr = newTemp(Ity_I32);
IRTemp ir_nia = newTemp(Ity_I32);
IRTemp do_branch = newTemp(Ity_I32);
IRTemp ctr_ok = newTemp(Ity_I32);
IRTemp cond_ok = newTemp(Ity_I32);
-// assign( ctr, getSPR( PPC32_SPR_CTR ) );
-
/* Hack to pass through code that just wants to read the PC */
if (theInstr == 0x429F0005) {
DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
putSPR( PPC32_SPR_LR, mkU32(guest_CIA_curr_instr + 4) );
return True;
}
-
+
+ /* The default what-next. Individual cases can override it. */
+ dres->whatNext = Dis_StopHere;
+
switch (opc1) {
case 0x12: // b (Branch, PPC32 p360)
if (flag_AA) {
if (flag_LK) {
putSPR( PPC32_SPR_LR, mkU32(guest_CIA_curr_instr + 4) );
- }
- irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
- irbb->next = mkU32(nia);
+ }
+
+ if (resteerOkFn((Addr64)nia)) {
+ dres->whatNext = Dis_Resteer;
+ dres->continueAt = (Addr64)nia;
+ } else {
+ irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
+ irbb->next = mkU32(nia);
+ }
break;
case 0x10: // bc (Branch Conditional, PPC32 p361)
return False;
}
break;
+
default:
vex_printf("dis_int_branch(PPC32)(opc1)\n");
return False;
}
- dres->whatNext = Dis_StopHere;
return True;
}
/* Branch Instructions */
case 0x12: case 0x10: // b, bc
- if (dis_branch(theInstr, &dres)) goto decode_success;
+ if (dis_branch(theInstr, &dres, resteerOkFn)) goto decode_success;
goto decode_failure;
/* System Linkage Instructions */
/* Branch Instructions */
case 0x210: case 0x010: // bcctr, bclr
- if (dis_branch(theInstr, &dres)) goto decode_success;
+ if (dis_branch(theInstr, &dres, resteerOkFn)) goto decode_success;
goto decode_failure;
/* Memory Synchronization Instructions */