	.sect	".AltProg"
	.align 32
	.global	TestAndSet
    .global AtomicSet      ; entry label
    .global AtomicClear    ; entry label
    .global _AtomicSet16      ; entry label
    .global _AtomicClear16    ; entry label

;******************************************************************************
;* FUNCTION NAME: TestAndSet                                                 *
;*                                                                            *
;*   Regs Modified     : A1,A4                                                *
;*   Regs Used         : A1,A4,B3,B4                                          *
;*   Local Frame Size  : 0 Args + 0 Auto + 0 Save = 0 byte                    *
;******************************************************************************

;******************************************************************************
;*                                                                            *
;* Using -g (debug) with optimization (-o3) may disable key optimizations!    *
;*                                                                            *
;******************************************************************************
TestAndSet:
;** --------------------------------------------------------------------------*
           B       .S2     B3                
||         LDW     .D1T1   *A4,A1           
           NOP             4
   [!A1]   STW     .D1T2   B4,*A4            
||         MV      .L1     A1,A4

	.sect	".AltProg"
	.align 32
	.global	SetBarrier

SetBarrier:
;** --------------------------------------------------------------------------*
           B       .S2     B3                
||         MVK     .S1     1,A3    
		   STW     .D1     A3,*A4            
		   NOP			   4

	.sect	".AltProg"
	.align 32
	.global	ReadAndClear

;******************************************************************************
; Reads a double and clears it without being interrupted
;******************************************************************************

ReadAndClear:
           RET     .S2     B3                
||         LDDW    .D1     *A4,A5:A4        
||		   ZERO    .L2     B4
           STW     .D1     B4,*A4          
           STW     .D1     B4,*+A4(4)      
           NOP             3



	.sect	".AltProg"
	.align 32
	.global	ReadSnapAmpxx



ReadSnapAmpxx:
			MVKL    .S2     0x60000000+12*2,B4
			MVKH    .S2     0x60000000+12*2,B4
			B     	LOOP                    ; do continuous branches to prevent interrupts
||			STB     .D2T1   A4,*B4            
||			MVK		.S1		600,A1

LOOP:
			MV		A1,B1
			SUB		A1,1,A1
	[!B1]	B 		JUMP2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fetch packet
	[!A1]   B		JUMP
	[A1]	B		LOOP

JUMP:		MVKL    .S1     0x60000000+12*2,A3

         	MVKH    .S1     0x60000000+12*2,A3

           	LDBU    .D1T1   *A3,A4            
           	LDBU    .D1T1   *+A3[2],A5
JUMP2:		RET     .S2     B3  
           	NOP     3            
			EXTU    A5,24,16,A5
			OR		A5,A4,A4
		              


;******************************************************************************
;* FUNCTION NAME: ReadSnap8CheckEmpty                                        *
;******************************************************************************


	.sect	".AltProg"
	.align 32
	.global	ReadSnap8CheckEmpty


; don't start time consuming reads if we don't have to
; compiler tends to generate "conditional" reads that
; still take a long time even though results are
; discarded

ReadSnap8CheckEmpty:
           MVKL    .S1     0x60000000+12*2,A7
           MVKH    .S1     0x60000000+12*2,A7
		   MVK     .S2     0x800,B1          ; timeout
Empty:     LDBU    .D1T1   *A7,A4            ; read the byte 
           MVKL    .S1     0x60000000+16*2,A6
           MVKH    .S1     0x60000000+16*2,A6
           MVK     .S1     0xaa,A3
		   NOP             1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fetch packet
     	   CMPEQ   .L1     A3,A4,A1          ; any "exception" ? 
      [!A1]RET     .S2     B3   			 ;no, quick exit             
           SUB     .L2     B1,1,B1
		   NOP			   4				 ; don't start time consuming read if we don't have to
      [B1] LDBU    .D1T1   *A6,A1            ; read empty 
     [!B1] MVK     .S1     0,A1              ; trick not empty on timeout 
           NOP             2
           NOP             1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fetch packet
     [!A1] RET     .S2     B3                ; not empty, return the value
||    [A1] B       .S1     Empty             ; was empty, loop back
		   NOP             5




;******************************************************************************
;* FUNCTION NAME: ReadSnap16CheckEmpty                                        *
;******************************************************************************


	.sect	".AltProg"
	.align 32
	.global	ReadSnap16CheckEmpty

ReadSnap16CheckEmpty:
           MVKL    .S1     0x60000000+12*2,A7
           MVKH    .S1     0x60000000+12*2,A7
||		   MVK     .S2     0x800,B1          ; timeout
Empty16:   LDBU    .D1T1   *A7,A5         	 ; read the LSbyte
		   LDBU    .D1T1   *A7[2],A4         ; read the MSbyte
           MVKL    .S1     0x60000000+16*2,A6
           MVKH    .S1     0x60000000+16*2,A6
           MVK     .S1     0xaa,A3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fetch packet
		   NOP
		   SHL     .S1     A4,8,A4 
		   OR      .S1	   A5,A4,A4  
     	   CMPEQ   .L1     A3,A5,A1          ; any "exception" ? 
      [!A1]RET     .S2     B3   			 ;no, quick exit             
           SUB     .L2     B1,1,B1
		   NOP			   4				 ; don't start time consuming read if we don't have to
      [B1] LDBU    .D1T1   *A6,A1            ; read empty 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fetch packet
     [!B1] MVK     .S1     0,A1              ; trick not empty on timeout 
           NOP             3
     [!A1] RET     .S2     B3                ; not empty, return the value
||    [A1] B       .S1     Empty16           ; was empty, loop back
		   NOP             5


; Send a read request and keep polling until there
; is a 16 bit word to read back.  Timeout if
; it takes too long.  Also make cont branches
; so we won't get interrupted


	.sect	".AltProg"
	.align 32
	.global	ReadSnapAmp

ReadSnapAmp:
           MVKL    .S1     0x60000000+12*2,A7
           MVKH    .S1     0x60000000+12*2,A7
		   B       .S1     Q01                ; do continuous branches to prevent interrupts
||		   STB     .D1     A4,*A7            
||		   MVK     .S2     0x800,B1          ; timeout

Q00:   	   LDBU    .D1     *A7,A5         	 ; read the LSbyte
||         B       .S1     Q02
		   LDBU    .D1     *A7[2],A4         ; read the MSbyte
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fetch packet
           MVKL    .S1     0x60000000+16*2,A6
		   B       .S1     Q03
           MVKH    .S1     0x60000000+16*2,A6
Q01:       MVK     .S1     0xaa,A3
Q02:	   SHL     .S1     A4,8,A4 
		   OR      .S1	   A5,A4,A4  
     	   CMPEQ   .L1     A3,A5,A1          ; any "exception" ? 
||		   B       .S1     Q04
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fetch packet
Q03: [!A1] RET     .S2     B3   			 ;no, quick exit             
           SUB     .L2     B1,1,B1
		   NOP			   2				 ; don't start time consuming read if we don't have to
      [A1] B       .S1     Q05
Q04:	   NOP
  	  [B1] LDBU    .D1T1   *A6,A1            ; read empty 
     [!B1] MVK     .S1     0,A1              ; trick not empty on timeout 
           NOP             1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fetch packet
		   B       .S1     Q06
Q05:       NOP             1
     [!A1] RET     .S2     B3                ; not empty, return the value
||    [A1] B       .S1     Q00               ; was empty, loop back
	       NOP             3	       
Q06:       NOP             1
	  [A1] B       .S1     Q01



;******************************************************************
;* FUNCTION NAME: Write32                                        *
;******************************************************************


	.sect	".AltProg"
	.align 32
	.global	Write32,Write16,Write8


Write32:
           STW     .D1T2   B4,*A4            
||         RET     .S2     B3               
           NOP             5
Write16:
           STH     .D1T2   B4,*A4           
||         RET     .S2     B3               
           NOP             5
Write8:
           STB     .D1T2   B4,*A4            
||         RET     .S2     B3                
           NOP             5




	.sect	".AltProg"
	.align 32
	.global	WriteSnapAmpNoDelay

;******************************************************************************
;* FUNCTION NAME: WriteSnapAmpNoDelay                                        *
;******************************************************************************

WriteSnapAmpNoDelay:
		   MPY     .M1     A4,2,A4
           RET     .S2     B3                
||         ZERO    .D1     A3               
           MVKH    .S1     0x60000000,A3
           STB     .D1T2   B4,*+A4[A3]       
||         MVKL    .S1     0x60000000+11*2,A3
           MVKH    .S1     0x60000000+11*2,A3
||         SHR     .S2     B4,8,B4          
           STB     .D1T2   B4,*A3            
		   NOP
		   
;----------------------------------------------------------------------
;  *p = *p | mask;                                                        
;----------------------------------------------------------------------

AtomicSet:
           LDW     .D1T1   *A4,A3 
||         B       .S2     RMS
           RET     .S2     B3      
		   NOP     3
           OR      .S2X    B4,A3,B4 
RMS:       STW     .D1T2   B4,*A4

;----------------------------------------------------------------------
;  *p = *p & mask;                                                        
;----------------------------------------------------------------------

AtomicClear:
           LDW     .D1T1   *A4,A3 
||         B       .S2     RMC
           RET     .S2     B3      
		   NOP     3
           AND     .S2X    B4,A3,B4 
RMC:       STW     .D1T2   B4,*A4
;----------------------------------------------------------------------
;  *p = *p | mask;                                                        
;----------------------------------------------------------------------

AtomicSet16:
           LDHU    .D1T1   *A4,A3 
||         B       .S2     RMS16
           RET     .S2     B3      
		   NOP     3
           OR      .S2X    B4,A3,B4 
RMS16:     STH     .D1T2   B4,*A4

;----------------------------------------------------------------------
;  *p = *p & mask;                                                        
;----------------------------------------------------------------------

AtomicClear16:
           LDHU    .D1T1   *A4,A3 
||         B       .S2     RMC16
           RET     .S2     B3      
		   NOP     3
           AND     .S2X    B4,A3,B4 
RMC16:     STH     .D1T2   B4,*A4
