                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: Utils1  { utilities, continued }
;>
;>      PROCEDURE Move4C( Source : PTR { !!r2 }
;>                       Destination : PTR { !!rE }
;>                      )
;>      PROCEDURE Init_ExtStack
;>      PROCEDURE Ext_Push
;>      PROCEDURE Ext_Pop
;>      FUNCTION Load_TOS : PTR { !!r2 }
;>      PROCEDURE Store_TOS( Ptr : PTR { !!r2 }
;>      PROCEDURE ZeroBlock
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Move4
;>
;>      This procedure is used to move 4 bytes from the souce to the
;>      destination.
;>
;>      Inputs:
;>              Source : PTR { !!r2 }
;>              Destination : PTR { !!rE }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       FOR i := 0 TO 3 DO
;>        @Destination( i ) := @Source( i )
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Move4:
                Ld      !r1,#4
Move4_Lp:       Lde     !r0,@!!r2
                Lde     @!!rE,!r0
                Incw    !!r2
                Incw    !!rE
                Djnz    !r1,Move4_Lp
                
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Move4C { move from program space to data space }
;>
;>      This procedure is used to move 4 bytes from the souce to the
;>      destination.
;>
;>      Inputs:
;>              Source : PTR { !!r2 }
;>              Destination : PTR { !!rE }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       FOR i := 0 TO 3 DO
;>        @Destination( i ) := @Source( i )
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Move4C:
                Ld      !r1,#4
Move4C_Lp:      Ldc     !r0,@!!r2
                Lde     @!!rE,!r0
                Incw    !!r2
                Incw    !!rE
                Djnz    !r1,Move4C_Lp
                
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Init_ExtStack
;>
;>      This procedure initializes Widget's external stack. This
;>      stack is a software implemented structure, and as such does not
;>      use the Z8's external stack capabilities.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Global Variables Changed:
;>              StackPtr
;>
;>      Algorithm:
;>
;>      BEGIN
;>       StackPtr := TopOfStack
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Init_ExtStack:
                Ld      !r2,#.HIBYTE. StackPtr
                Ld      !r3,#.LOWBYTE. StackPtr
                Ld      !r0,#.HIBYTE. TopOfStack
                Lde     @!!r2,!r0
                Incw    !!r2
                Ld      !r0,#.LOWBYTE. TopOfStack
                Lde     @!!r2,!r0
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Ext_Push
;>
;>      This procedure pushes the current working register set
;>      onto the external stack.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       FOR i := 0 TO 15 DO
;>        @StackPtr := WorkingRegister[ 15 - i ]
;>        StackPtr := StackPtr - 1
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Ext_Push:
                Ld      ScrReg4,Rp ;save context
                Srp     #Wrk_Scr
                
                Call    Load_TOS
                
                Ld      !r0,!r4 ; save context
                Add     !r0,#$0F ; start at register $F
                
                Ld      !r1,#16 ;load 16 registers
Ext_Push_Lp:    Ld      !rF,@!r0
                Lde     @!!r2,!rF
                Dec     !r0
                Decw    !!r2
                Djnz    !r1,Ext_Push_Lp
                
                Call    Store_TOS
                
                Ld      Rp,!r4 ;restore context
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Ext_Pop
;>
;>      This procedure pops 16 locations from the external stack 
;>      into the current working register set.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       FOR i := 0 TO 15 DO
;>        StackPtr := StackPtr + 1
;>        WorkingRegisterSet[ i ] := @StackPtr
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Ext_Pop:
                Ld      ScrReg4,Rp ;save context
                Srp     #Wrk_Scr
                
                Call    Load_TOS
                
                Ld      !r0,!r4 ; save context
                
                Ld      !r1,#16 ;load 16 registers
                
                Incw    !!r2 ; StackPtr := StackPtr + 1
                
Ext_Pop_Lp:     Ldei    @!r0,@!!r2
                Djnz    !r1,Ext_Pop_LP
                
                Decw    !!r2 ;point at TOS
                
                Call    Store_TOS
                
                Ld      Rp,!r4 ;restore context
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Load_TOS
;>
;>      This functions returns a ptr to the current top
;>      of the external stack.
;>
;>      Inputs: { None }
;>
;>      Outputs:
;>              Load_TOS : PTR { !!r2 }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Load_TOS := StackPtr
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Load_TOS:
                Ld      !r0,#.HIBYTE. StackPtr
                Ld      !r1,#.LOWBYTE. StackPtr
                Lde     !r2,@!!r0
                Incw    !!r0
                Lde     !r3,@!!r0
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Store_TOS
;>
;>      This procedure stores the contents of Ptr into StackPtr
;>
;>      Inputs:
;>              Ptr : PTR { !!r2 }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       StackPtr := Ptr
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Store_TOS:
                Cp      !r3,#.LOWBYTE. StackPtr ;check for stack underflow
                Jr      Ugt,St_TOS
                
                Srp     #Wrk_Sys
                Pop     !r4 ;save some history of stack frame
                Pop     !r5
                Pop     !r6
                Pop     !r7
                Call    Abort
                
St_TOS:         Ld      !r0,#.HIBYTE. StackPtr
                Ld      !r1,#.LOWBYTE. StackPtr
                Lde     @!!r0,!r2
                Incw    !!r0
                Lde     @!!r0,!r3
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: ZeroBlock
;>
;>      This procedure zeros out the 532 blocks pointed to by the
;>      input parameter
;>
;>      Inputs:
;>              BlockPtr : PTR { !!r2 }
;>
;>      Outputs: { none }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

ZeroBlock:
                Ld      !rE,#.HIBYTE. 532
                Ld      !rF,#.LOWBYTE. 532
                
                Clr     !r0
                
ZeroBlk_Lp:     Lde     @!!r2,!r0
                Incw    !!r2
                Decw    !!rE
                Jr      Nz,ZeroBlk_Lp
                
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: ZeroHeader
;>
;>      This procedure zeros the sector gap, header sync gap,
;>      header field, and data sync field.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

ZeroHeader:
                Ld      !r1,#( WBuffer1 - WriteArray )
                Ld      !r2,#.HIBYTE. WriteArray
                Ld      !r3,#.LOWBYTE. WriteArray
                Clr     !r0
                
ZeroHdr_Lp:     Lde     @!!r2,!r0
                Incw    !!r2
                Djnz    !r1,ZeroHdr_Lp
                
                And     Excpt_Stat,#$FF-Nzero_Stat-Buf_Damage
                Jp      Bank_Ret
                
                .LSTOFF

