#
# audioPPC.s
#
# Written by Frank Wille <frank@phoenix.owl.de> in 1999
#
        .text
        .sdreg  r2

.set	MAX_AUDIOBUFFER_SIZE,0x2000

# struct AudioBuffer
.set	databuffer,0
.set	next,4


# external variables from audio.c
	.extern	_ab_current
	.extern	_ab_feed
	.extern	_ab_free
	.extern _readOffset
	.extern	_feedOffset
	.extern _audioBufferSize



###################################################################
 	.align	3
	.globl	_audio_pollbuffer
_audio_pollbuffer:
# r3 = unsigned char *buf
# r4 = int nbytes

#  if (ab_current) {
#    while (nbytes>=0) {
#      if ((ab_current==ab_feed) && (readOffset>=feedOffset))
#        break;
	lwz	r5,_ab_current(r2)
	add	r3,r3,r4
	lwz	r6,_ab_feed(r2)
	mr.	r5,r5
	lwz	r7,_readOffset(r2)
	lwz	r8,_feedOffset(r2)
	lwz	r9,_audioBufferSize(r2)
	beq	apoll_zero
	lwz	r10,databuffer(r5)
apoll_loop:
	cmpw	r5,r6
	bne	apoll_1
	cmpw	r7,r8
	bge	apoll_zero

apoll_1:
#      if (readOffset >= MAX_AUDIOBUFFER_SIZE) {
#        struct AudioBuffer *temp = ab_current->next;
#
#        if (!temp) break;
#        ab_current->next = ab_free;
#        ab_free = ab_current;
#        ab_current = temp;      
#        readOffset = 0;
#      }
	cmpwi	r7,MAX_AUDIOBUFFER_SIZE
	blt	apoll_2
	lwz	r11,next(r5)
	mr.	r11,r11
	beq	apoll_zero
	lwz	r12,_ab_free(r2)
	stw	r12,next(r5)
	stw	r5,_ab_free(r2)
	li	r7,0
	mr	r5,r11
	lwz	r10,databuffer(r5)
	stw	r5,_ab_current(r2)

apoll_2:
#      if (audioBufferSize) {
#        audioBufferSize--;
#        buf[--nbytes] = ab_current->databuffer[readOffset++];
#      }
	mr.	r9,r9
	beq	apoll_zero
	lbzx	r0,r10,r7
	addi	r7,r7,1
	subi	r9,r9,1
	subic.	r4,r4,1
	stbu	r0,-1(r3)
	bne	apoll_loop
	stw	r7,_readOffset(r2)
	stw	r9,_audioBufferSize(r2)
	blr

apoll_zero:
	stw	r7,_readOffset(r2)
	stw	r9,_audioBufferSize(r2)
	li	r0,0
apoll_zeroloop:
	stbu	r0,-1(r3)
	subic.	r4,r4,1
	bne	apoll_zeroloop
	blr
