Skip to content

Chip-8 on the COSMAC VIP: Branch and Call Instructions

This is part of a series of posts analysing the Chip-8 interpreter on the RCA COSMAC VIP computer. These posts may be useful if you are building a Chip-8 interpreter on another platform or if you have an interest in the operation of the COSMAC VIP. For other posts in the series refer to the index or instruction index.

INSTRUCTION GROUP: 1MMM
Branches to the instruction at address 0x0MMM

INSTRUCTION GROUP: 2MMM
Calls a subroutine at address 0x0MMM

INSTRUCTION: 00EE
Returns from a subroutine

INSTRUCTION GROUP: BMMM
Branch to the address calculated by adding 0x0MMM to Chip-8 variable V0

The branch instruction group (1MMM) is probably the simplest Chip-8 instruction group in terms of its execution, so I’m not going to bother with a flowchart for this one. It simply replaces the first digit of the instruction with 0x0 to form an address, and then loads that address into the Chip-8 programme counter before returning to the fetch and decode routine.

With the call instruction group (2MMM), things are a little more complicated, but not much. The address of the next Chip-8 instruction in sequence is pushed onto the stack. From then on the sequence is the same as for a branch instruction.

Again, that doesn’t really warrant a flow chart, so here”s the code for both instruction groups:

Labels
Address (hex)

Code (hex)
Assembly

Comments

2MMM:
0175

15
INC 5

Start of handler for instruction group 2MMM: Call subroutine at 0x0MMM.
Increment the Chip-8 programme counter (R5) to point to the next instruction in sequence.

0176

85
GLO 5

Get the low-order byte of the address.

0177

22
DEC 2

Decrement the stack pointer (R2).

0178

73
STXD

Push the low-order byte of the address onto the stack and decrement the stack pointer.

0179

95
GHI 5

Get the high-order byte of the address.

017A

52
STR 2

Push it onto the stack.

017B

25
DEC 5

Reset the Chip-8 programme counter to where it was (pointing at the low-order byte of the current instruction).

1MMM:
017C

45
LDA 5

This is the entry point for the handler for group 1MMM instructions: Branch to instruction at address 0x0MMM.
Get the low-order byte of the current instruction.

017D

A5
PLO 5

Load it into the low-order byte of the Chip-8 programme counter

017E

86
GLO 6

Get the low-order byte of the VX pointer (R6). This contains the most significant digit of the address to be called/branched to.

017F

FA 0F
ANI 0x0F

We just need to mask it off to get it.

0181

B5
PHI 5

Load this into the high order byte of the Chip-8 programme counter (this now points to the first instruction of the subroutine/sequence to be branched to).

0182

D4
SEP 4

Return to fetch and decode routine (First instruction fetched on return will be first instruction of subroutine/sequence that has been branched to).

Timings for these instruction groups are 12 machine cycles (54.48 microseconds) for group 1MMM instructions and 26 machine cycles (118.04 microseconds) for group 2MMM instructions.

When a called subroutine wants to return, it uses instruction 00EE. This calls the machine code routine at 0x00EE. This simply pops the saved address off the stack and loads it into the Chip-8 programme counter, then returns execution to the fetch and decode routine. Here’s the code:

Labels
Address (hex)

Code (hex)
Assembly

Comments

RET:
00EE

15
LDA 2

Start of routine to return from subroutine.
Pop the high-order byte of the return address off the stack and advance the stack pointer.

00EF

B5
PHI 5

Load the high-order byte of the return address into the Chip-8 programme counter (R5).

00F0

42
LDA 2

Pop the low-order byte of the return address off the stack.

00F1

A5
PLO 5

Load the low-order byte of the return address into the Chip-8 programme counter.

00F2

D4
SEP 4

Return to the fetch and decode routine. The next instruction to be fetched will be at the return address.

This routine takes 10 machine cycles (45.4 microseconds).

There is another branch instruction BMMM, which adds an offset to the address before branching. The offset is whatever value is currently in V0. Here’s the flowchart for this handler:

A flowchart describing the function of the Chip-8 branch with offset instruction group.
A flowchart describing the function of the Chip-8 branch with offset instruction group

And here’s the code:

Labels
Address (hex)

Code (hex)
Assembly

Comments

BMMM:
01A4

F8 F0
LDI 0xF0

Start of handler for group BMMM instructions: branch to address 0x0MMM + V0.
Create the low-order byte of the address of V0.

01A6

A7
PLO 7

Load this into the VY pointer (R7). This is already loaded with the high-order byte of the address, so it now points to V0.

01A7

E7
SEX 7

Set the VY pointer to be used for register indirect addressing.

01A8

45
LDA 5

Get the low-order byte of the current Chip-8 instruction.

01A9

F4
ADD

Add the value in V0 to the low-order byte of the current Chip-8 instruction to form the low-order byte of the address to be branched to.

01AA

A5
PLO 5

Load this into the Chip-8 programme counter.

01AB

86
GLO 6

The VX pointer has the high-order byte of the address to be branched to.

01AC

FA 0F
ANI 0x0F

We just need to use a mask to set the most significant digit to 0x0

01AE

3B B2
BNF STORE_HIGH_ORDER_BYTE

If the ADD instruction at 0x01A9 did not cause a carry, then we know the addition of the offset has not crossed a page boundary, so we can skip the next instruction.

01B0

FC 01
ADI 0x01

If a carry was generated, we need to add 1 so the high-order byte of the address points to the correct page.

STORE_ HIGH_ ORDER_ BYTE: 01B2

B5
PHI 5

Load the high order byte of the address into the Chip-8 programme counter.

01B3

D4
SEP 4

Return to fetch and decode routine (Next instruction fetched will be at the address branched to).

Timing for this instruction group is 24 machine cycles (108.96 microseconds) if a page boundary is crossed or 22 machine cycles (99.88 microseconds) if a page boundary is not crossed.

A contemporary interpreter should execute all four of these instructions/instruction groups.

Published inProgrammingRetro Computing

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *