JumpFlash.java

1
package com.rox.debug.cpu;
2
3
import com.rox.cpu.mos6502.assembler.DisassembledInstruction;
4
5
import java.util.List;
6
import java.util.function.LongSupplier;
7
8
/**
9
 * Whether to flash the current instruction's address: for {@link #FLASH_MILLIS} after a step lands on it by a
10
 * jump - any way control moves other than to the next instruction (JMP, JSR, RTS/RTI, a taken branch, an
11
 * interrupt) - while it's still the current instruction. Only while paused: running, nearly every refresh
12
 * follows some jump, so it would never stop.
13
 */
14
public final class JumpFlash {
15
    static final long FLASH_MILLIS = 600;
16
    private static final int ADDRESS_MASK = 0xFFFF;
17
18
    private final LongSupplier clockMillis;
19
    private long lastInstructionCount;
20
    private boolean pausedLastTime;
21
    private long flashUntil = Long.MIN_VALUE;
22
23
    /** @param clockMillis e.g. {@code System::currentTimeMillis} */
24
    public JumpFlash(final LongSupplier clockMillis){
25
        this.clockMillis = clockMillis;
26
    }
27
28
    /**
29
     * @param instructionCount see {@link CpuDebugSource#instructionCount()} - a rise while paused is a step
30
     * @param recent recently executed instructions, oldest first - see {@link CpuDebugSource#recentInstructions()}
31
     * @param currentAddress where the current instruction starts
32
     * @return whether the address should be flashing now
33
     */
34
    public boolean update(final long instructionCount, final boolean paused, final List<DisassembledInstruction> recent,
35
                          final int currentAddress){
36
        final long now = clockMillis.getAsLong();
37 1 1. update : negated conditional → KILLED
        if (!paused){
38
            flashUntil = Long.MIN_VALUE;
39
            pausedLastTime = false;
40
            lastInstructionCount = instructionCount;
41 1 1. update : replaced boolean return with true for com/rox/debug/cpu/JumpFlash::update → KILLED
            return false;
42
        }
43
        //an instruction run while already paused is a step; the first look after pausing is not
44 2 1. update : negated conditional → KILLED
2. update : negated conditional → KILLED
        if (pausedLastTime && instructionCount != lastInstructionCount){
45
            //a step that didn't jump ends any flash still showing for the instruction before it
46 2 1. update : Replaced long addition with subtraction → KILLED
2. update : negated conditional → KILLED
            flashUntil = landedByJump(recent, currentAddress) ? now + FLASH_MILLIS : Long.MIN_VALUE;
47
        }
48
        pausedLastTime = true;
49
        lastInstructionCount = instructionCount;
50 3 1. update : negated conditional → KILLED
2. update : changed conditional boundary → KILLED
3. update : replaced boolean return with true for com/rox/debug/cpu/JumpFlash::update → KILLED
        return now < flashUntil;
51
    }
52
53
    /** True unless {@code currentAddress} directly follows the last executed instruction. */
54
    static boolean landedByJump(final List<DisassembledInstruction> recent, final int currentAddress){
55 1 1. landedByJump : negated conditional → KILLED
        if (recent.isEmpty()){
56 1 1. landedByJump : replaced boolean return with true for com/rox/debug/cpu/JumpFlash::landedByJump → KILLED
            return false;
57
        }
58 1 1. landedByJump : Replaced integer subtraction with addition → KILLED
        final DisassembledInstruction previous = recent.get(recent.size() - 1);
59 4 1. landedByJump : Replaced integer addition with subtraction → KILLED
2. landedByJump : Replaced bitwise AND with OR → KILLED
3. landedByJump : negated conditional → KILLED
4. landedByJump : replaced boolean return with true for com/rox/debug/cpu/JumpFlash::landedByJump → KILLED
        return ((previous.address() + previous.length()) & ADDRESS_MASK) != currentAddress;
60
    }
61
}

Mutations

37

1.1
Location : update
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:runningNeverFlashes()]
negated conditional → KILLED

41

1.1
Location : update
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:runningNeverFlashes()]
replaced boolean return with true for com/rox/debug/cpu/JumpFlash::update → KILLED

44

1.1
Location : update
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:anUnchangedRefreshDoesNotRetriggerTheFlash()]
negated conditional → KILLED

2.2
Location : update
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:theFirstLookNeverFlashes()]
negated conditional → KILLED

46

1.1
Location : update
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:pausingIsNotAStep()]
Replaced long addition with subtraction → KILLED

2.2
Location : update
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:pausingIsNotAStep()]
negated conditional → KILLED

50

1.1
Location : update
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:theFirstLookNeverFlashes()]
negated conditional → KILLED

2.2
Location : update
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:anUnchangedRefreshDoesNotRetriggerTheFlash()]
changed conditional boundary → KILLED

3.3
Location : update
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:theFirstLookNeverFlashes()]
replaced boolean return with true for com/rox/debug/cpu/JumpFlash::update → KILLED

55

1.1
Location : landedByJump
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:pausingIsNotAStep()]
negated conditional → KILLED

56

1.1
Location : landedByJump
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:landedByJumpIsFalseWithNoHistoryOrASequentialStepAndHandlesWrapAround()]
replaced boolean return with true for com/rox/debug/cpu/JumpFlash::landedByJump → KILLED

58

1.1
Location : landedByJump
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:anUnchangedRefreshDoesNotRetriggerTheFlash()]
Replaced integer subtraction with addition → KILLED

59

1.1
Location : landedByJump
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:landedByJumpIsFalseWithNoHistoryOrASequentialStepAndHandlesWrapAround()]
Replaced integer addition with subtraction → KILLED

2.2
Location : landedByJump
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:landedByJumpIsFalseWithNoHistoryOrASequentialStepAndHandlesWrapAround()]
Replaced bitwise AND with OR → KILLED

3.3
Location : landedByJump
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:pausingIsNotAStep()]
negated conditional → KILLED

4.4
Location : landedByJump
Killed by : com.rox.debug.cpu.JumpFlashTest.[engine:junit-jupiter]/[class:com.rox.debug.cpu.JumpFlashTest]/[method:landedByJumpIsFalseWithNoHistoryOrASequentialStepAndHandlesWrapAround()]
replaced boolean return with true for com/rox/debug/cpu/JumpFlash::landedByJump → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1