The
lost
Adress Register
Just a small coding tip... maybe well known... no idea... maybe someone can
use it.
Well it's always the same. when you are doing complex innerloops after some time
you always have too less adress registers. there is one adress register A7 you
can use because of the stack. but your innerloop does not need the stack...
But using A7 normally forces the computer to crash hardly...
so the first idea is of course to use:
loop:
exg Ax,Dx
do stuff
exg Ax,Dx
do stuff
dbf Dx,loop
But even exg needs 4 clockcyles... so in all 8 clockcycles... A real pain in the
ass. 8 clockcyles for nothing...
Some days ago... one night i was thinking about this... remembered there was a
USP register... hm USP means user stack pointer(USP)... of course there is
a supervisor stack pointer (SSP)... then i had an idea...
When you normally do a intro/demo what ever you are in the supervisor mode so
the SSP is used... the USP is unused until you return to the user mode...
When you use the A7 reg in your innerloop and an interrupt appears it will crash
because the irq writes the return adress and status register to the stack. so
the normal way is to disable all irqs to use A7 in your innerloops...but that of
course doesn't work with sid voices or vbl or rasters...
So why not execute the innerloop in user mode? And just use A7?
How does it work?
Before you do your innerloop just change to user mode and write your value to
A7. and use it the user mode has its own stack. when an irq appears the 68k
switches to the SSP (because irqs are always executed in supervisor mode) so A7
has a valid pointer to keep up all stuff... at the end of the interrupt the rte
pops the return adress and sr from stack (which switches back to user mode) and
A7 has the value you need to in your innerloop... without waste of clockcycles
to restore A7 and stuff.
When you are done with your innerloop you need to switch back to to supervisor
mode et voila... Here is the code:
;switch into supervisor mode
MOVEM.L D0-A6,-(SP)
PEA PRG(PC)
MOVE.W #$0026,-(SP)
TRAP #$0E
ADDA.L #6,SP
;return to TOS
MOVEM.L (SP)+,D0-A6
CLR.W -(SP)
TRAP #1
RTS
PRG:
;save USP
MOVE USP,A0
MOVE.L A0,OLDUSP
;save old $80 (trap 0 vector) and install supervisor
;switcher
MOVE.L $00000080,OLD80
MOVE.L #TRAP0,$00000080
;---------------------------------------------------------
;the pseudo innerloop
;it just counting up the dummy variable...
;as you can see A7 is used to access it indirect
;of course during execution time irqs are popping up
;and all works fine...
;switch to user mode
MOVE #$0300,SR
MOVEA.L #DUMMY,SP
MOVE.L #$000FFFFF,D0
INNERLOOP:
;use A7
ADDI.L #1,(SP)
SUBQ.L #$01,D0
BNE.S INNERLOOP
;and switch back to super visor mode
TRAP #0
;---------------------------------------------------------
;restore all
MOVE.L OLD80,$00000080
MOVEA.L OLDUSP,A0
MOVE A0,USP
RTS
;this is my way to switch back to supervisor mode
;when a trap is called the 68k pushes the sr and return
;adress to stack...here i am just doing what rte is doing
;but rte would change back to user mode... as you can
;see the sr is not used...so i am in supervisor mode after it
;a0 is lost after it...anyway
TRAP0:
MOVEA.W (SP)+,A0 ;pop sr
MOVEA.L (SP)+,A0 ;get return adress
JMP (A0) ;jump to return adress
;for restoring
DUMMY: DC.L 0
OLDUSP: DC.L 0
OLD80: DC.L 0
END
Of course you can't use jsr or move.l Dx,-(A7) in your innerloop... but anyway
normally you don't need it...and you can't access memory < $800 and hmm no
hardware regs... but this should be clear anyway, I just wanted to say it again
;))
greetz
ultra\cream 2004
|