Alive
News Team Current issue History Online Support Download Forum @Pouet

01 - 02 - SE - 03 - 04 - 05 - 06 - 07 - 08 - 09 - 10 - 11 - 12 - 13 - 14

Alive 9
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

Alive 9