GP-3962 Fix for test failures from delayslot with branches flow

following, also fixed backward flow following through delayslots with
branches
This commit is contained in:
emteere 2023-11-23 09:36:22 -05:00
parent 041be82286
commit 00bbee3163
3 changed files with 41 additions and 15 deletions

View File

@ -175,7 +175,7 @@ public class FollowDelaySlotFlowTest extends AbstractFollowFlowTest {
AddressSet flowAddresses = followFlow.getFlowAddressSet(TaskMonitor.DUMMY);
AddressSet expectedAddresses = new AddressSet();
expectedAddresses.add(address(10), address(15));
expectedAddresses.add(address(10), address(17));
expectedAddresses.add(address(20), address(25));
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
@ -580,7 +580,7 @@ public class FollowDelaySlotFlowTest extends AbstractFollowFlowTest {
AddressSet flowAddresses = followFlow.getFlowToAddressSet(TaskMonitor.DUMMY);
AddressSet expectedAddresses = new AddressSet();
expectedAddresses.add(address(16), address(17));
expectedAddresses.add(address(14), address(17));
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));

View File

@ -220,7 +220,7 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
}
do {
// skip past delay slot instructions
// skip past delay slot instructions which satisfy specific conditions
try {
instr = program.getListing()
.getInstructionContaining(
@ -229,28 +229,31 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
catch (AddressOverflowException e) {
return null;
}
// if an instruction is in a delay slot and has references to it,
// consider this the fallfrom instruction
if (instr != null && instr.isInDelaySlot() && instr.hasFallthrough()) {
if (program.getSymbolTable().hasSymbol(instr.getMinAddress())) {
break;
}
}
}
while (instr != null && instr.isInDelaySlot());
// Continue walking instructions backwards if a delay-slot instruction is found and
// either the delay slot instruction does not fallthrough or it does not have a
// ref or label on it.
while (instr != null && instr.isInDelaySlot() &&
(!instr.hasFallthrough() ||
!program.getSymbolTable().hasSymbol(instr.getMinAddress())));
if (instr == null) {
return null;
}
// If this instruction is in a delay slot,
// it is assumed to always fall from the delay-slotted
// instruction regardless of its fall-through
if (this.isInDelaySlot()) {
// If this instruction is within delay-slot, return a null fall-from address if
// previous instruction (i.e., instruction with delay slot, found above)
// does not have a fallthrough and this instruction has a ref or label on it.
if (!instr.hasFallthrough() &&
program.getSymbolTable().hasSymbol(this.getMinAddress())) {
return null;
}
// Return previous instruction's address (i.e., instruction with delay slot, found above)
return instr.getMinAddress();
}
// No delay slot, but check if the instruction falls into this one.
// No delay-slot, but check if the instruction falls into this one.
Address fallAddr = instr.getFallThrough();
if (fallAddr != null && fallAddr.equals(address)) {
return instr.getMinAddress();

View File

@ -143,6 +143,29 @@ public interface Instruction extends CodeUnit, ProcessorContext {
* this instruction.
* This is useful for handling instructions that are found
* in a delay slot.
*
* Note: if an instruction is in a delayslot, then it may have
* a branch into the delayslot, which is handled as follows
*
* <pre>
* JMPIF Y, X
* lab:
* _ADD getFallFrom() = JMPIF
* MOV getFallFrom() = _ADD
*
* JMP Y, X
* lab:
* _ADD getFallFrom() = null
* MOV getFallFrom() = _ADD
*
* JMPIF Y, X
* _ADD getFallFrom() = JMPIF
* MOV getFallFrom() = JMPIF
*
* JMP Y, X
* _ADD getFallFrom() = JMP
* MOV getFallFrom() = null
*</pre>
*/
public Address getFallFrom();