static unsigned GetRegInfo2 (CodeSeg* S, CodeEntry* E, int Index, Collection* Visited, unsigned Used, unsigned Unused, unsigned Wanted) /* Recursively called subfunction for GetRegInfo. */ { /* Follow the instruction flow recording register usage. */ while (1) { unsigned R; /* Check if we have already visited the current code entry. If so, ** bail out. */ if (CE_HasMark (E)) { break; } /* Mark this entry as already visited */ CE_SetMark (E); CollAppend (Visited, E); /* Evaluate the used registers */ R = E->Use; if (E->OPC == OP65_RTS || ((E->Info & OF_UBRA) != 0 && E->JumpTo == 0)) { /* This instruction will leave the function */ R |= S->ExitRegs; } if (R != REG_NONE) { /* We are not interested in the use of any register that has been ** used before. */ R &= ~Unused; /* Remember the remaining registers */ Used |= R; } /* Evaluate the changed registers */ if ((R = E->Chg) != REG_NONE) { /* We are not interested in the use of any register that has been ** used before. */ R &= ~Used; /* Remember the remaining registers */ Unused |= R; } /* If we know about all registers now, bail out */ if (((Used | Unused) & Wanted) == Wanted) { break; } /* If the instruction is an RTS or RTI, we're done */ if ((E->Info & OF_RET) != 0) { break; } /* If we have an unconditional branch, follow this branch if possible, ** otherwise we're done. */ if ((E->Info & OF_UBRA) != 0) { /* Does this jump have a valid target? */ if (E->JumpTo) { /* Unconditional jump */ E = E->JumpTo->Owner; Index = -1; /* Invalidate */ } else { /* Jump outside means we're done */ break; } /* In case of conditional branches, follow the branch if possible and ** follow the normal flow (branch not taken) afterwards. If we cannot ** follow the branch, we're done. */ } else if ((E->Info & OF_CBRA) != 0) { /* Recursively determine register usage at the branch target */ unsigned U1; unsigned U2; if (E->JumpTo) { /* Jump to internal label */ U1 = GetRegInfo2 (S, E->JumpTo->Owner, -1, Visited, Used, Unused, Wanted); } else { /* Jump to external label. This will effectively exit the ** function, so we use the exitregs information here. */ U1 = S->ExitRegs; } /* Get the next entry */ if (Index < 0) { Index = CS_GetEntryIndex (S, E); } if ((E = CS_GetEntry (S, ++Index)) == 0) { Internal ("GetRegInfo2: No next entry!"); } /* Follow flow if branch not taken */ U2 = GetRegInfo2 (S, E, Index, Visited, Used, Unused, Wanted); /* Registers are used if they're use in any of the branches */ return U1 | U2; } else { /* Just go to the next instruction */ if (Index < 0) { Index = CS_GetEntryIndex (S, E); } E = CS_GetEntry (S, ++Index); if (E == 0) { /* No next entry */ Internal ("GetRegInfo2: No next entry!"); } } } /* Return to the caller the complement of all unused registers */ return Used; }
int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) /* Check if the given code segment range is a basic block. That is, check if * First is the only entrance and Last is the only exit. This means that no * jump/branch inside the block may jump to an insn below First or after(!) * Last, and that no insn may jump into this block from the outside. */ { unsigned I; /* Don't accept invalid ranges */ CHECK (First <= Last); /* First pass: Walk over the range and remove all marks from the entries */ CS_ResetMarks (S, First, Last); /* Second pass: Walk over the range checking all labels. Note: There may be * label on the first insn which is ok. */ I = First + 1; while (I <= Last) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this entry has one or more labels, if so, check which * entries jump to this label. */ unsigned LabelCount = CE_GetLabelCount (E); unsigned LabelIndex; for (LabelIndex = 0; LabelIndex < LabelCount; ++LabelIndex) { /* Get this label */ CodeLabel* L = CE_GetLabel (E, LabelIndex); /* Walk over all entries that jump to this label. Check for each * of the entries if it is out of the range. */ unsigned RefCount = CL_GetRefCount (L); unsigned RefIndex; for (RefIndex = 0; RefIndex < RefCount; ++RefIndex) { /* Get the code entry that jumps here */ CodeEntry* Ref = CL_GetRef (L, RefIndex); /* Walk over out complete range and check if we find the * refering entry. This is cheaper than using CS_GetEntryIndex, * because CS_GetEntryIndex will search the complete code * segment and not just our range. */ unsigned J; for (J = First; J <= Last; ++J) { if (Ref == CS_GetEntry (S, J)) { break; } } if (J > Last) { /* We did not find the entry. This means that the jump to * out code segment entry E came from outside the range, * which in turn means that the given range is not a basic * block. */ CS_ResetMarks (S, First, Last); return 0; } /* If we come here, we found the entry. Mark it, so we know * that the branch to the label is in range. */ CE_SetMark (Ref); } } /* Next entry */ ++I; } /* Third pass: Walk again over the range and check all branches. If we * find a branch that is not marked, its target is not inside the range * (since we checked all the labels in the range before). */ I = First; while (I <= Last) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this is a branch and if so, if it has a mark */ if (E->Info & (OF_UBRA | OF_CBRA)) { if (!CE_HasMark (E)) { /* No mark means not a basic block. Before bailing out, be sure * to remove the marks from the remaining entries. */ CS_ResetMarks (S, I+1, Last); return 0; } /* Remove the mark */ CE_ResetMark (E); } /* Next entry */ ++I; } /* Done - this is a basic block */ return 1; }