Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/tiny8/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class CPU:
def __init__(self, memory: Optional[Memory] = None):
self.mem = memory or Memory()
# 32 general purpose 8-bit registers R0-R31
self.regs: [int] = [0] * 32
self.regs: list[int] = [0] * 32
# Program Counter (word-addressable for AVR) - we use byte addressing for simplicity
self.pc: int = 0
# Stack Pointer - point into RAM
Expand Down Expand Up @@ -927,6 +927,30 @@ def op_brlt(self, label: str | int):
if s:
self.op_jmp(label)

def op_brmi(self, label: str | int):
"""BRMI - Branch if Minus (Negative flag set).

Branches when the N flag is set (negative result).

Args:
label: Destination label or address to jump to if the condition is met.
"""
n = self.get_flag(SREG_N)
if n:
self.op_jmp(label)

def op_brpl(self, label: str | int):
"""BRPL - Branch if Plus (Negative flag clear).

Branches when the N flag is clear (non-negative result).

Args:
label: Destination label or address to jump to if the condition is met.
"""
n = self.get_flag(SREG_N)
if not n:
self.op_jmp(label)

def op_push(self, rr: int):
"""Push a register value onto the stack.

Expand Down
52 changes: 44 additions & 8 deletions tests/test_control_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,16 @@ def test_brlt(self):
ldi r1, $01 ; 1
cp r0, r1
brlt less
ldi r3, $01
ldi r2, $01
jmp done
less:
ldi r3, $02
ldi r2, $02
done:
nop
"""
cpu = self.run_asm(src)
# -1 < 1 so branch taken -> r3 == 2
self.assertEqual(cpu.read_reg(3), 0x02)
# -1 < 1 so branch taken -> r2 == 2
self.assertEqual(cpu.read_reg(2), 0x02)

def test_brge(self):
# BRGE: branch when signed (Rd >= Rr). Use 1 >= -1
Expand All @@ -124,13 +124,49 @@ def test_brge(self):
ldi r1, $FF ; -1
cp r0, r1
brge ge
ldi r3, $01
ldi r2, $01
jmp done
ge:
ldi r3, $02
ldi r2, $02
done:
nop
"""
cpu2 = self.run_asm(src2)
# 1 >= -1 so branch taken -> r2 == 2
self.assertEqual(cpu2.read_reg(2), 0x02)

def test_brmi(self):
# BRMI: branch when negative (N == 1)
src = """
ldi r0, $FF ; -1
ldi r1, $00 ; 0
cp r0, r1
brmi neg
ldi r2, $01
jmp done
neg:
ldi r2, $02
done:
nop
"""
cpu = self.run_asm(src)
# -1 < 0 so negative -> branch taken -> r2 == 2
self.assertEqual(cpu.read_reg(2), 0x02)

def test_brpl(self):
# BRPL: branch when plus (N == 0)
src2 = """
ldi r0, $02 ; 2
ldi r1, $FF ; -1
cp r0, r1
brpl plus
ldi r2, $01
jmp done2
plus:
ldi r2, $02
done2:
nop
"""
cpu2 = self.run_asm(src2)
# 1 >= -1 so branch taken -> r3 == 2
self.assertEqual(cpu2.read_reg(3), 0x02)
# 2 >= -1 so non-negative -> branch taken -> r2 == 2
self.assertEqual(cpu2.read_reg(2), 0x02)