Calculating 6502 Execution Time - Part 2

gusmccallum

gus

Posted on February 2, 2022

Calculating 6502 Execution Time - Part 2

This is part 2 of a series on introductory concepts of assembly language on the MOS 6502 processor, part 1 of which you can find here and part 3 of which you can find here. Last time I covered setting up a table to track the number of cycles an operation takes as well as how to find the number of cycles an operation take. Picking up from there I'll cover some final considerations to make sure we're getting an accurate cycle count, and then dive into the specifics of my lab's code and add those all up.

Page ranges for 6502 memory

Many of the instructions for the 6502 have conditions that accessing certain memory locations will add to the cycle count for that operation. In the case of BNE, which we're using in this program, branching to the same page will incur a cost of 1 cycle while a branch to another page adds 2. Operations like this can be added to the "alt cycle" column, or vice versa, to keep track of control paths that deviate from the average when adding up our cycles. Where in memory we're branching to can be determined by taking a look at the disassembly on the emulator, at the top of the page. When we do we see that execution occurs exclusively on the first page of program data, so we'll just add the 1 cycle to our execution for BNE when adding that up.

Single page branch

With that in mind, let's get to the program itself, starting with a breakdown of the code.

LDA #$00    ; Load accumulator with value 00
STA $40     ; Store value of accumulator at $0040
LDA #$02    ; Load accumulator with value 02
STA $41     ; Store value of accumulator at $0041
Enter fullscreen mode Exit fullscreen mode

This block of code creates a pointer by storing the 2 byte address in the locations $0040 and $0041. When the processor puts the two bytes together it will get $0200 which is the location of the bmp display.

LDA #$07    ; Load accumulator with value 07 (colour yellow)

LDY #$00    ; Set the Y register, which is acting as the index 
              in our loop, to 0

LOOP:   
STA ($40),Y ; Store value of accumulator (yellow - $07) in 
              address $0040 + Y (currently 0)

INY         ; Increment Y (index)

BNE LOOP    ; Return to LOOP statement and keep repeating 
              until Y overflow occurs (end of page)

INC $41     ; Increment the value at address 41 (from page 
              $0200 to $0300)
LDX $41     ; Load value of 41 to X register
CPX #$06    ; Compare value of X register (page number) to 06
BNE LOOP    ; Continue looping while Zero flag isn’t set 
              (while prior comparison is false)
Enter fullscreen mode Exit fullscreen mode

With the prior breakdown in mind, we can look at the cycle counts for each instruction and begin to get an idea of how long execution of our program should take.

Starting with the more straightforward instructions, we have the following count:

Image description

All of these instructions are performed a single time to set up the following loop, so getting their totals is just a matter of looking up their mnemonics and the type of address they're using for their operations.

The loop that follows after is performed for each memory location of each page of the display, so we get a cycle count of 1024 for each instruction save for the last, which branches 1020 times and doesn't branch on the last iteration of each loop, at which point execution progresses to the next block of code.

Image description

Finally, we have the end of the program which iterates the page number we're looping through. These instructions run 4 times (page $0200-$02FF, $0300-$03FF, $0400-$04FF and $0500-$05FF)

Image description

Summing our cycle count gives us the following:

Image description

We know:

  • The given instructions will take 11327 cycles to execute
  • 6502s can run at around 1 MHz
  • We get the microseconds per clock cycle by calculating 1,000,000/(CPU Speed*1,000,000)

Thus the time is equal to the number of cycles * microseconds per clock, which comes out to 11327uS of execution time or 0.011327 seconds.

💖 💪 🙅 🚩
gusmccallum
gus

Posted on February 2, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Calculating 6502 Execution Time - Part 2
opensource Calculating 6502 Execution Time - Part 2

February 2, 2022