[stella] lovely bit of code

Subject: [stella] lovely bit of code
From: "Andrew Davie" <adavie@xxxxxxxxxxx>
Date: Wed, 8 Jan 2003 02:41:17 +1100
Had to share this gem...
 
I have some very very tight code which needs to be in the form of a loop, repeated several times by block-code-copying (using different variables inside the loops)...  here's the basic loop shell...
 
.LAB1C       
            nop            ; 2
            nop            ; 2
            nop            ; 6 cycles MUST be here
 
    ; blah code here.... no free cycles
 
            dec LoopCount1  ; 5
            bpl .LAB1C     ; 3(2)
 
now I need to immediately have another like the above, and it has to happen with EXACT timing...
but the problem is, I've used one LESS cycle on the last iteration because the branch wasn't taken
 
So this code won't work...
 
.LAB1C       
            nop            ; 2
            nop            ; 2
            nop            ; 6 cycles MUST be here
 
    ; blah code here.... no free cycles
 
            dec LoopCount1 ; 5
            bpl .LAB1C     ; 3(2)
 
                ;<< NEED A 1-CYCLE (AND ONLY ONE CYCLE!) DELAY HERE!! - CANNOT DO!
                            ; WELL, ONE *CAN* BUT NOT WITH THE PAGE CONSTRAINT MENTIONED BELOW...
.LAB1D       
            nop
            nop
            nop                    ; 6 cycles MUST be here
 
    ; blah code here.... no free cycles
 
            dec LoopCount2
            bpl .LAB1D
 
 
Yes, I could put a .byte before the .lab1d to turn the 2 cycle NOP into a 3-cycle instruction... but that solution doesn't work for me because...  a further problem shows up.  The more of these blocks of code I put in, the more likely it is that one of those branches will end up having to branch over a page boundary, causing an extra cycle to be used and buggering things up.  And, basically, I need a fair few of these blocks of code running one after the other with NO cycles free. 
 
So the two problems are that each of the loops must be entirely contained within a page... AND I need to somehow get an extra cycle after the end of each of the loops... but *ONLY* one extra cycle.
 
Here's the solution...
 
 
            jmp .LAB1C
            ALIGN 256      ; align this loop to a page boundary
 
.LAB1C      nop            ; 2
            nop            ; 2
            nop            ; 6 cycles MUST be here
 
    ; blah code here.... no free cycles
 
            dec LoopCount1 ; 5
            bpl .LAB1C     ; 3(2)        won't branch over a page!
 
            jmp NEAT       ; 3
            ALIGN 256      ; align the next loop to a page boundary     
 
.LAB1D       
            nop            ; 2
NEAT        nop            ; 2
            nop            ; 6 cycles MUST be here
 
    ; blah code here.... no free cycles
 
            dec LoopCount2 ; 5
            bpl .LAB1D     ; 3(2)
 
 
 
The addition of the "jmp NEAT" after the loop terminates allows the insertion of the ALIGN to a page boundary... guaranteeing the 2nd loop (or nth loop) won't be crossing a page.... and the jump jumps right into the middle of the subsequent loop, skipping the first nop (2 cycles).  So the jump + the remaining 2 nops gives 7 cycles which is  (6+1) ie: we've added just one cycle for the first iteration of the loop only.
 
It's lovely - I just had to share it.
 
Cheers
A
 
Current Thread