;_Title B2B: transfers data from one buffer to another (very fast)
;
;_ARGS	  TYPE	     VARIABLE    I/O       DESCRIPTION
;
;        logical*1    IBUF        I        Input  buffer
;        logical*1    OBUF        O        Output buffer
;        integer*4    NS          I        number of bytes to transfer
;
;_DESC   CALL B2B (IBUF, OBUF, NS)
;
;        Transfers the contents of the source buffer (IBUF) to the
;        destination buffer (OBUF) for the number of bytes specified
;        by NS. If NS is negative, the source operand is treated as
;        a constant to fill the destination buffer (OBUF).
;
;_HIST   84Feb17  Eric M. Eliason  U.S.G.S. Flagstaff  Original Version
;        86Sept22 Joni L. Bauers   updated  documentation
;        87May29  Kris J. Becker   Added code to allow for more than 32767
;                                  bytes to be moved/filled.
;
;
;_END
;*******************************************************************************
          .TITLE  B2B
          .IDENT  /VERSION: 29-MAY-1987/
	  .PSECT  B2B,NOWRT,EXE,LONG
	  .ENTRY  B2B,^M<R2,R3,R4,R5>
	  MOVL    @12(AP),R0            ;R0=number of samples to move
	  BEQL    B2B_DONE              ;If zero samples then we are done
	  MOVL    4(AP),R1              ;R1=address of source buffer
	  MOVL    8(AP),R2		;R2=address of destination buffer
	  TSTL    R0                    ;if NS is <0 then treatsource as
	  BLSS    B2B_FILL              ;a constant to fill destination buffer
                        ;******************************************************
                        ;Determine the way B2B is to move destination to
			;source, backward or forward movement. Three cases
			;occur which decide backward or forward movement:
			;1) Source and Destination buffers do not overlap
			;   (use forward movement, it's faster)
			;2) Source and Destination buffers overlap and 
			;   the source begining address is greater than
			;   the destination address (use forward movement
			;   so samples do not overlap)
			;3) Source and Destination buffers overlap and the
			;   source begining address is less than the
			;   destination address. (use backward movement
			;   so samples do not overlap)
			;******************************************************
          CMPL    R1,R2                 ;Which address has the greater value
          BGTRU   B2B_FOR               ;if src addr. > des. addr. then forward
	  ADDL3   R1,R0,R3              ;R3=ending addr. of src. buffer
 	  CMPL    R3,R2                 ;is ending src. addr. > des. addr.?
	  BGTR    B2B_BCK               ;need to go fill buffer backwards
	  JMP     B2B_FOR               ;go fill buffers forwards
 		        ;******************************************************
                        ;move bytes in forward direction
	                ;******************************************************
B2B_FOR:  CMPL    #32767,R0             ;if > 32767 then cannot use MOVC3 (KJB)
	  BLSS    B2B_FLP               ;use the slow forward loop        (KJB)
	  MOVC3   R0,(R1),(R2)          ;fill des. buffer in forward direction
          JMP     B2B_DONE              ;done for <= 32767                (KJB)
B2B_FLP:  MOVB    (R1)+,(R2)+           ;move byte to the dest. buffer    (KJB)
   	  SOBGTR  R0,B2B_FLP            ;subtract and branch              (KJB)
B2B_DONE: RET                           ;return to caller                
                        ;******************************************************
			;move bytes in backward direction
			;******************************************************
B2B_BCK:  ADDL    R0,R1                 ;R1=addr. of last element in src. + 1
	  ADDL    R0,R2                 ;R2=addr. of last element in des. + 1
BCK_LOOP: MOVB    -(R1),-(R2)		;move src. to des. auto-decrement
	  SOBGTR  R0,BCK_LOOP 		;test for end of loop
	  RET				;return to caller
			;******************************************************
			;fill des. buffer with a constant
			;******************************************************
B2B_FILL: MNEGL   R0,R0			;make NS positive
	  MOVB	  @4(AP),R1 		;R1=fill constant
	  MOVL	  8(AP),R2		;R2=addr. of des. buffer
	  CMPL	  #32767,R0		;# bytes > 32767? 		  (KJB)
	  BLSS	  B2B_FBIG		;if so, use loop to fill buffer   (KJB)
 	  MOVC5   #0,(R2),R1,R0,(R2)	;fill with a constant
	  RET				;return to caller
B2B_FBIG: MOVB	  R1,(R2)+		;move constant to dest. buffer    (KJB)
	  SOBGTR  R0,B2B_FBIG 		;branch until # bytes	          (KJB)
	  RET
	  .END
