Skip to content

Commit b5c6996

Browse files
committed
finished branch testing
1 parent 80f9dab commit b5c6996

4 files changed

Lines changed: 113 additions & 5 deletions

File tree

src/cpu.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use bitflags::bitflags;
33
use std::fmt;
44
use std::time::Duration;
55

6+
mod branch_test;
67
mod group1_test;
78
mod group2_test;
89
mod group3_test;
@@ -87,7 +88,7 @@ impl CPU {
8788
x: 0,
8889
y: 0,
8990
sp: STACK_RESET,
90-
flags: CpuFlags::from_bits_truncate(0b00100100),
91+
flags: CpuFlags::from_bits_truncate(0b0010_0100),
9192
memory: [0; 0xFFFF],
9293
clock_time: Duration::from_millis(1), // Example value
9394
}
@@ -239,7 +240,6 @@ impl CPU {
239240
break;
240241
}
241242
// NOTE: Before this runs, PC must be at the instruction before the next command
242-
// BUG: This may affect branching and needs to be adjusted
243243
self.pc = self.pc.wrapping_add(1);
244244
}
245245
// CLeaning program ROM
@@ -849,8 +849,15 @@ impl CPU {
849849

850850
// This code will read the next item in the pc and set the pc to jump there with + 1 to go to the next instruction
851851
fn branch(&mut self) {
852+
println!(
853+
"branch: Initalized, starting to branch from pc {:#x}!",
854+
self.pc
855+
);
852856
let jump = self.mem_read(self.pc) as i8;
853-
self.pc = self.pc.wrapping_add(1).wrapping_add(jump as u16);
857+
println!("branch: jump is {:x}", jump);
858+
// NOTE We do not need to add 2 as at then end of every run cycle will add 1, the other 1 is added since the pc is on the address instead of the instruction
859+
self.pc = self.pc.wrapping_add(jump as u16);
860+
println!("Finished branch, pc is now on {:#x}", self.pc);
854861
}
855862

856863
fn if_contain_flag_branch(&mut self, flag: CpuFlags) {
@@ -860,7 +867,7 @@ impl CPU {
860867
}
861868

862869
fn if_clear_flag_branch(&mut self, flag: CpuFlags) {
863-
if self.flags.contains(flag) {
870+
if !self.flags.contains(flag) {
864871
self.branch();
865872
}
866873
}
@@ -899,6 +906,8 @@ impl CPU {
899906
bbb
900907
)
901908
} else if bbb == 0b100 {
909+
// Add pc by 1 to go to reading address
910+
self.pc = self.pc.wrapping_add(1);
902911
// Checking for branches
903912
match aaa {
904913
// BPL

src/cpu/branch_test.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#[cfg(test)]
2+
// Similar to JMP testing, and just branch further into the code
3+
// Eg. Set [BRANCH 0x02 0x00 INX]
4+
// And just test for x and see if branch has been or hasn't been done
5+
mod branch_test {
6+
use crate::cpu::op::*;
7+
use crate::cpu::CpuFlags;
8+
use crate::cpu::CPU;
9+
10+
// All this will do is run [op 0x01 0x00 INX]
11+
// Specify clear if the flag should be clear(This will enable all flags except the chosen flag)
12+
// It will initalize all flags as empty, specify in flags to enable flags
13+
// If x == 1, branch is successful, if not, branch is unsuccessful
14+
fn jump(cpu: &mut CPU, op: u8, clear: bool, flag: CpuFlags) {
15+
cpu.load_and_reset(vec![op, 0x01, 0x00, op::INX]);
16+
if clear {
17+
println!("branch_test: Allocating flags to clear!");
18+
cpu.flags = CpuFlags::from_bits_truncate(0b1111_1111);
19+
cpu.flags.remove(flag);
20+
} else {
21+
cpu.flags.insert(flag);
22+
}
23+
cpu.run();
24+
}
25+
26+
// Each test will test when branch should occur and branch should not occur
27+
// Clear tests if flag is clear
28+
fn helper_test(op: u8, clear: bool, flag: CpuFlags) {
29+
let mut cpu = CPU::new();
30+
// First test should succeed
31+
jump(&mut cpu, op, clear, flag);
32+
assert!(
33+
cpu.x == 1,
34+
"Helper_test positive failed on {:#x}, cpu.x is {}",
35+
op,
36+
cpu.x
37+
);
38+
39+
// Second test should fail
40+
jump(&mut cpu, op, !clear, flag);
41+
assert!(
42+
cpu.x == 0,
43+
"Helper_test negative failed on {:#x}, cpu.x is {}",
44+
op,
45+
cpu.x
46+
);
47+
}
48+
49+
#[test]
50+
fn bpl_test() {
51+
helper_test(branch_op::BPL, true, CpuFlags::NEGATIVE);
52+
}
53+
54+
#[test]
55+
fn bmi_test() {
56+
helper_test(branch_op::BMI, false, CpuFlags::NEGATIVE);
57+
}
58+
59+
#[test]
60+
fn bvc_test() {
61+
helper_test(branch_op::BVC, true, CpuFlags::OVERFLOW);
62+
}
63+
64+
#[test]
65+
fn bvs_test() {
66+
helper_test(branch_op::BVS, false, CpuFlags::OVERFLOW);
67+
}
68+
69+
#[test]
70+
fn bcc_test() {
71+
helper_test(branch_op::BCC, true, CpuFlags::CARRY);
72+
}
73+
74+
#[test]
75+
fn bcs_test() {
76+
helper_test(branch_op::BCS, false, CpuFlags::CARRY);
77+
}
78+
79+
#[test]
80+
fn bne_test() {
81+
helper_test(branch_op::BNE, true, CpuFlags::ZERO);
82+
}
83+
84+
#[test]
85+
fn beq_test() {
86+
helper_test(branch_op::BEQ, false, CpuFlags::ZERO);
87+
}
88+
}

src/cpu/group2_test.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ mod group2_test {
1010
use crate::cpu::op::*;
1111
use crate::cpu::CpuFlags;
1212
use crate::cpu::CPU;
13-
use crate::print_title;
1413

1514
fn g2_flag_test(cpu: &CPU, carry: bool, zero: bool, negative: bool) {
1615
if carry {

src/cpu/op.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,15 @@ pub mod g3_op {
102102

103103
pub const BIT: u8 = 0x20;
104104
}
105+
106+
#[cfg(test)]
107+
pub mod branch_op {
108+
pub const BPL: u8 = 0x10; // Branch on Plus (N=0)
109+
pub const BMI: u8 = 0x30; // Branch on Minus (N=1)
110+
pub const BVC: u8 = 0x50; // Branch on Overflow Clear (V=0)
111+
pub const BVS: u8 = 0x70; // Branch on Overflow Set (V=1)
112+
pub const BCC: u8 = 0x90; // Branch on Carry Clear (C=0)
113+
pub const BCS: u8 = 0xB0; // Branch on Carry Set (C=1)
114+
pub const BNE: u8 = 0xD0; // Branch on Not Equal (Z=0)
115+
pub const BEQ: u8 = 0xF0; // Branch on Equal (Z=1)
116+
}

0 commit comments

Comments
 (0)