;	
;	cliptiaa.s
;
;	P/ECE TIA (Television Interface Adapter) Emulator
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Thu Mar 24 03:00:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;
#define TIA_DEFINE_OFFSET
#include "cliptiaa.h"
#ifdef TIA_ASM

	.code
	.align	1

;****************************************************************************
;	
;****************************************************************************

;			       3210
;	4-bit LFSR:	+----> xxxx -> output
;			|        ||
;			+- xor <-++
;
#macro	UPDATE_LFSR4	$1
	ld.w	%r9, $1				; x = (lfsr4 ^ (lfsr4 >> 1)) & 1
	srl	%r9, 1
	xor	%r9, $1
	xand	%r9, %r9, 1
	xsrl	$1, 1				; lfsr4 = (lfsr4 >> 1) | (x << (4 - 1))
	xsll	%r9, (4-1)
	or	$1, %r9
#endm

;			        43210
;	5-bit LFSR:	+-----> xxxxx -> output
;			|        |  |
;			+- xor <-+--+
;
#macro	UPDATE_LFSR5	$1
	ld.w	%r9, $1				; x = (LFSR5 ^ (LFSR5 >> 3)) & 1
	srl	%r9, 3
	xor	%r9, $1
	xand	%r9, %r9, 1
	xsrl	$1, 1				; LFSR5 = (LFSR5 >> 1) | (x << (5 - 1))
	xsll	%r9, (5-1)
	or	$1, %r9
#endm

;			      876543210
;	5-bit LFSR:	+---> xxxxxxxxx -> output
;			|        |    |
;			+- xor <-+----+
;
#macro	UPDATE_LFSR9	$1
	ld.w	%r9, $1				; x = (LFSR9 ^ (LFSR9 >> 5)) & 1
	srl	%r9, 5
	xor	%r9, $1
	xand	%r9, %r9, 1
	xsrl	$1, 1				; LFSR9 = (LFSR9 >> 1) | (x << (9 - 1))
	xsll	%r9, (9-1)
	or	$1, %r9
#endm

;			         0
;	Polar:		+------> x -> output
;			|        |
;			+- not <-+
;
#macro	UPDATE_POLAR	$1
	xxor	$1, $1, 1
#endm

;			   0
;	LFSR/Polar:	...x -> output +-> 1: +volume
;			               +-> 0: -volume
;
#macro	UPDATE_OUTPUT	$1, $2, $3		; $1=lfsr/polar, $2=output, $3=volume
	xand	%r9, $1, 1			; output = (lfsr/polar & 1) ? volume : -volume
	jrne.d	4
	ld.w	$2, $3				; *delay*
	not	$2, $2				; (skip?)
	add	$2, 1				; (skip?)
#endm

;****************************************************************************
;	
;****************************************************************************

;
;	30KHz/Freq pulse ----------------> Polar toggle ->
;
	.global	tia_audio_mix4
tia_audio_mix4:
	xld.w	%r14, TIA_CLOCK/114
	xjp	tia_audio_mix4C

;
;	10KHz/Freq pulse ----------------> Polar toggle ->
;
	.global	tia_audio_mixC
tia_audio_mixC:
	xld.w	%r14, VCS_CLOCK/114
	xjp	tia_audio_mix4C

;
;	clock/Freq pulse ----------------> Polar toggle ->
;
tia_audio_mix4C:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mix4C_EXIT		; if(!volume) goto EXIT
	;
	xld.ub	%r11, [%r12+AUDIO_FREQUENCY]	; %r11 = period = SPEAKER_FREQUENCY * audio->frequency
	xld.w	%r9, SPEAKER_FREQUENCY		; *anti-interlock*
	mlt.h	%r11, %r9			; (16000×(1..32)なので、mlt.hで充分)
	ld.w	%r11, %alr
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = count = audio->count /* 取り出し */
	xld.ub	%r6, [%r12+AUDIO_POLAR]		; %r6 = polar = audio->polar /* 取り出し */
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		; Update output
	;
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mix4C_DO:				; do {
	sub	%r4, %r14			;   count -= clock
	xjruge	tia_audio_mix4C_NO_ADVANCE	;   if(count < 0) { /*!NonCarry*/
tia_audio_mix4C_ADVANCE_DO:			;     do {
	UPDATE_POLAR	%r6			;         Update polar
	add	%r4, %r11			;     } while((count += period) < 0) /*NonCarry*/
	xjruge	tia_audio_mix4C_ADVANCE_DO
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		;     Update output
	;
tia_audio_mix4C_NO_ADVANCE:			;   }
	ld.h	%r9, [%r13]			;   *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mix4C_DO
	;
	xld.w	[%r12+AUDIO_COUNT], %r4		; audio->count = count /* 書き戻し */
	xld.b	[%r12+AUDIO_POLAR], %r6		; audio->polar = polar /* 書き戻し */
tia_audio_mix4C_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

;
;	30KHz/Freq pulse -> Div31 pulse -> Polar toggle ->
;
	.global	tia_audio_mix6
tia_audio_mix6:
	xld.w	%r14, TIA_CLOCK/114
	xjp	tia_audio_mix6E

;
;	10KHz/Freq pulse -> Div31 pulse -> Polar toggle ->
;
	.global	tia_audio_mixE
tia_audio_mixE:
	xld.w	%r14, VCS_CLOCK/114
	xjp	tia_audio_mix6E

;
;	clock/Freq pulse -> Div31 pulse -> Polar toggle ->
;
tia_audio_mix6E:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mix6E_EXIT		; if(!volume) goto EXIT
	;
	xld.ub	%r11, [%r12+AUDIO_FREQUENCY]	; %r11 = period = SPEAKER_FREQUENCY * audio->frequency
	xld.w	%r9, SPEAKER_FREQUENCY		; *anti-interlock*
	mlt.h	%r11, %r9			; (16000×(1..32)なので、mlt.hで充分)
	ld.w	%r11, %alr
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = count = audio->count /* 取り出し */
	xld.ub	%r5, [%r12+AUDIO_DIV31]		; %r5 = div31 = audio->div31 /* 取り出し */
	xld.ub	%r6, [%r12+AUDIO_POLAR]		; %r6 = polar = audio->polar /* 取り出し */
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		; Update output
	;
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mix6E_DO:				; do {
	sub	%r4, %r14			;   count -= clock
	xjruge	tia_audio_mix6E_NO_ADVANCE	;   if(count < 0) { /*!NonCarry*/
tia_audio_mix6E_ADVANCE_DO:			;     do {
	xsub	%r5, %r5, 1			;       if(--div31 < 0) div31 += 31
	jruge	2
	add	%r5, 31				;       (skip?)
	jreq	2
	cmp	%r5, 13				;       (skip?)
	xjrne	tia_audio_mix6E_ADVANCE_LOOP	;       if(div31 == 0 || div31 == 13) {
	UPDATE_POLAR	%r6			;         Update polar
tia_audio_mix6E_ADVANCE_LOOP:			;       }
	add	%r4, %r11			;     } while((count += period) < 0) /*NonCarry*/
	xjruge	tia_audio_mix6E_ADVANCE_DO
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		;     Update output
	;
tia_audio_mix6E_NO_ADVANCE:			;   }
	ld.h	%r9, [%r13]			;   *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mix6E_DO
	;
	xld.w	[%r12+AUDIO_COUNT], %r4		; audio->count = count /* 書き戻し */
	xld.b	[%r12+AUDIO_DIV31], %r5		; audio->div31 = div31 /* 書き戻し */
	xld.b	[%r12+AUDIO_POLAR], %r6		; audio->polar = polar /* 書き戻し */
	;
tia_audio_mix6E_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

;
;	30KHz/Freq pulse -> Poly5 pulse -> Polar toggle ->
;
	.global	tia_audio_mix7
tia_audio_mix7:
	xld.w	%r14, TIA_CLOCK/114
	xjp	tia_audio_mix7F

;
;	10KHz/Freq pulse -> Poly5 pulse -> Polar toggle ->
;
	.global	tia_audio_mixF
tia_audio_mixF:
	xld.w	%r14, VCS_CLOCK/114
	xjp	tia_audio_mix7F

;
;	clock/Freq pulse -> Poly5 pulse -> Polar toggle ->
;
tia_audio_mix7F:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mix7F_EXIT		; if(!volume) goto EXIT
	;
	xld.ub	%r11, [%r12+AUDIO_FREQUENCY]	; %r11 = period = SPEAKER_FREQUENCY * audio->frequency
	xld.w	%r9, SPEAKER_FREQUENCY		; *anti-interlock*
	mlt.h	%r11, %r9			; (16000×(1..32)なので、mlt.hで充分)
	ld.w	%r11, %alr
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = count = audio->count /* 取り出し */
	xld.ub	%r5, [%r12+AUDIO_LFSR5]		; %r5 = lfsr5 = audio->lfsr5 /* 取り出し */
	xld.ub	%r6, [%r12+AUDIO_POLAR]		; %r6 = polar = audio->polar /* 取り出し */
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		; Update output
	;
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mix7F_DO:				; do {
	sub	%r4, %r14			;   count -= clock
	xjruge	tia_audio_mix7F_NO_ADVANCE	;   if(count < 0) { /*!NonCarry*/
tia_audio_mix7F_ADVANCE_DO:			;     do {
	UPDATE_LFSR5	%r5			;       Update LFSR
	xand	%r9, %r5, 1			;       if(lfsr5 & 1) {
	xjreq	tia_audio_mix7F_ADVANCE_LOOP
	UPDATE_POLAR	%r6			;         Update polar
tia_audio_mix7F_ADVANCE_LOOP:			;       }
	add	%r4, %r11			;     } while((count += period) < 0) /*NonCarry*/
	xjruge	tia_audio_mix7F_ADVANCE_DO
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		;     Update output
	;
tia_audio_mix7F_NO_ADVANCE:			;   }
	ld.h	%r9, [%r13]			;   *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mix7F_DO
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = audio->count = count /* 書き戻し */
	xld.b	%r5, [%r12+AUDIO_LFSR5]		; %r5 = audio->lfsr5 = lfsr5 /* 書き戻し */
	xld.b	%r6, [%r12+AUDIO_POLAR]		; %r6 = audio->polar = polar /* 書き戻し */
	;
tia_audio_mix7F_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

;
;	                                              1 ->
;
	.global	tia_audio_mix0
tia_audio_mix0:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mix0_EXIT		; if(!volume) goto EXIT
	;
	xld.w	%r14, TIA_CLOCK/114		; %r14 = clock = TIA_CLOCK / 114
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mix0_DO:				; do {
	ld.h	%r9, [%r13]			;   *wbuff++ += volume
	add	%r9, %r10
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mix0_DO
tia_audio_mix0_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

;
;	30KHz/Freq pulse ----------------> Poly4 output ->
;
	.global	tia_audio_mix1
tia_audio_mix1:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mix1_EXIT		; if(!volume) goto EXIT
	;
	xld.ub	%r11, [%r12+AUDIO_FREQUENCY]	; %r11 = period = SPEAKER_FREQUENCY * audio->frequency
	xld.w	%r9, SPEAKER_FREQUENCY		; *anti-interlock*
	mlt.h	%r11, %r9			; (16000×(1..32)なので、mlt.hで充分)
	ld.w	%r11, %alr
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = count = audio->count /* 取り出し */
	xld.ub	%r6, [%r12+AUDIO_LFSR4]		; %r6 = lfsr4 = audio->lfsr4 /* 取り出し */
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		; Update output
	;
	xld.w	%r14, TIA_CLOCK/114		; %r14 = clock = TIA_CLOCK / 114
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mix1_DO:				; do {
	sub	%r4, %r14			;   count -= clock
	xjruge	tia_audio_mix1_NO_ADVANCE	;   if(count < 0) { /*!NonCarry*/
tia_audio_mix1_ADVANCE_DO:			;     do {
	UPDATE_LFSR4	%r6			;         Update LFSR
	add	%r4, %r11			;     } while((count += period) < 0) /*NonCarry*/
	xjruge	tia_audio_mix1_ADVANCE_DO
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		;     Update output
	;
tia_audio_mix1_NO_ADVANCE:			;   }
	ld.h	%r9, [%r13]			;   *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mix1_DO
	;
	xld.w	[%r12+AUDIO_COUNT], %r4		; audio->count = count /* 書き戻し */
	xld.b	[%r12+AUDIO_LFSR4], %r6		; audio->lfsr4 = lfsr4 /* 書き戻し */
tia_audio_mix1_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

;
;	30KHz/Freq pulse -> Div31 pulse -> Poly4 output ->
;
	.global	tia_audio_mix2
tia_audio_mix2:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mix2_EXIT		; if(!volume) goto EXIT
	;
	xld.ub	%r11, [%r12+AUDIO_FREQUENCY]	; %r11 = period = SPEAKER_FREQUENCY * audio->frequency
	xld.w	%r9, SPEAKER_FREQUENCY		; *anti-interlock*
	mlt.h	%r11, %r9			; (16000×(1..32)なので、mlt.hで充分)
	ld.w	%r11, %alr
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = count = audio->count /* 取り出し */
	xld.ub	%r5, [%r12+AUDIO_DIV31]		; %r5 = div31 = audio->div31 /* 取り出し */
	xld.ub	%r6, [%r12+AUDIO_LFSR4]		; %r6 = lfsr4 = audio->lfsr4 /* 取り出し */
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		; Update output
	;
	xld.w	%r14, TIA_CLOCK/114		; %r14 = clock = TIA_CLOCK / 114
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mix2_DO:				; do {
	sub	%r4, %r14			;   count -= clock
	xjruge	tia_audio_mix2_NO_ADVANCE	;   if(count < 0) { /*!NonCarry*/
tia_audio_mix2_ADVANCE_DO:			;     do {
	xsub	%r5, %r5, 1			;       if(--div31 < 0) div31 += 31
	jruge	2
	add	%r5, 31				;       (skip?)
	jreq	2
	cmp	%r5, 13				;       (skip?)
	xjrne	tia_audio_mix2_ADVANCE_LOOP	;       if(div31 == 0 || div31 == 13) {
	UPDATE_LFSR4	%r6			;         Update LFSR
tia_audio_mix2_ADVANCE_LOOP:			;       }
	add	%r4, %r11			;     } while((count += period) < 0) /*NonCarry*/
	xjruge	tia_audio_mix2_ADVANCE_DO
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		;     Update output
	;
tia_audio_mix2_NO_ADVANCE:			;   }
	ld.h	%r9, [%r13]			;   *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mix2_DO
	;
	xld.w	[%r12+AUDIO_COUNT], %r4		; audio->count = count /* 書き戻し */
	xld.b	[%r12+AUDIO_DIV31], %r5		; audio->div31 = div31 /* 書き戻し */
	xld.b	[%r12+AUDIO_LFSR4], %r6		; audio->lfsr4 = lfsr4 /* 書き戻し */
tia_audio_mix2_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

;
;	30KHz/Freq pulse -> Poly5 pulse -> Poly4 output ->
;
	.global	tia_audio_mix3
tia_audio_mix3:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mix3_EXIT		; if(!volume) goto EXIT
	;
	xld.ub	%r11, [%r12+AUDIO_FREQUENCY]	; %r11 = period = SPEAKER_FREQUENCY * audio->frequency
	xld.w	%r9, SPEAKER_FREQUENCY		; *anti-interlock*
	mlt.h	%r11, %r9			; (16000×(1..32)なので、mlt.hで充分)
	ld.w	%r11, %alr
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = count = audio->count /* 取り出し */
	xld.ub	%r5, [%r12+AUDIO_LFSR5]		; %r5 = lfsr5 = audio->lfsr5 /* 取り出し */
	xld.ub	%r6, [%r12+AUDIO_LFSR4]		; %r6 = lfsr4 = audio->lfsr4 /* 取り出し */
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		; Update output
	;
	xld.w	%r14, TIA_CLOCK/114		; %r14 = clock = TIA_CLOCK / 114
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mix3_DO:				; do {
	sub	%r4, %r14			;   count -= clock
	xjruge	tia_audio_mix3_NO_ADVANCE	;   if(count < 0) { /*!NonCarry*/
tia_audio_mix3_ADVANCE_DO:			;     do {
	UPDATE_LFSR5	%r5			;       Update LFSR
	xand	%r9, %r5, 1			;       if(lfsr5 & 1) {
	xjreq	tia_audio_mix3_ADVANCE_LOOP
	UPDATE_LFSR4	%r6			;         Update LFSR
tia_audio_mix3_ADVANCE_LOOP:			;       }
	add	%r4, %r11			;     } while((count += period) < 0) /*NonCarry*/
	xjruge	tia_audio_mix3_ADVANCE_DO
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		;     Update output
	;
tia_audio_mix3_NO_ADVANCE:			;   }
	ld.h	%r9, [%r13]			;   *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mix3_DO
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = audio->count = count /* 書き戻し */
	xld.b	%r5, [%r12+AUDIO_LFSR5]		; %r5 = audio->lfsr5 = lfsr5 /* 書き戻し */
	xld.b	%r6, [%r12+AUDIO_LFSR4]		; %r6 = audio->lfsr4 = lfsr4 /* 書き戻し */
tia_audio_mix3_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

;
;	30KHz/Freq pulse ----------------> Poly9 output ->
;
	.global	tia_audio_mix8
tia_audio_mix8:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mix8_EXIT		; if(!volume) goto EXIT
	;
	xld.ub	%r11, [%r12+AUDIO_FREQUENCY]	; %r11 = period = SPEAKER_FREQUENCY * audio->frequency
	xld.w	%r9, SPEAKER_FREQUENCY		; *anti-interlock*
	mlt.h	%r11, %r9			; (16000×(1..32)なので、mlt.hで充分)
	ld.w	%r11, %alr
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = count = audio->count /* 取り出し */
	xld.uh	%r6, [%r12+AUDIO_LFSR9]		; %r6 = lfsr9 = audio->lfsr9 /* 取り出し */	9-bit LFSRフィールドはHalfWordです。要注意!!
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		; Update output
	;
	xld.w	%r14, TIA_CLOCK/114		; %r14 = clock = TIA_CLOCK / 114
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mix8_DO:				; do {
	sub	%r4, %r14			;   count -= clock
	xjruge	tia_audio_mix8_NO_ADVANCE	;   if(count < 0) { /*!NonCarry*/
tia_audio_mix8_ADVANCE_DO:			;     do {
	UPDATE_LFSR9	%r6			;         Update LFSR
	add	%r4, %r11			;     } while((count += period) < 0) /*NonCarry*/
	xjruge	tia_audio_mix8_ADVANCE_DO
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		;     Update output
	;
tia_audio_mix8_NO_ADVANCE:			;   }
	ld.h	%r9, [%r13]			;   *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mix8_DO
	;
	xld.w	[%r12+AUDIO_COUNT], %r4		; audio->count = count /* 書き戻し */
	xld.h	[%r12+AUDIO_LFSR9], %r6		; audio->lfsr9 = lfsr9 /* 書き戻し */		9-bit LFSRフィールドはHalfWordです。要注意!!
tia_audio_mix8_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

;
;	30KHz/Freq pulse ----------------> Poly5 output ->
;
	.global	tia_audio_mix9
tia_audio_mix9:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mix9_EXIT		; if(!volume) goto EXIT
	;
	xld.ub	%r11, [%r12+AUDIO_FREQUENCY]	; %r11 = period = SPEAKER_FREQUENCY * audio->frequency
	xld.w	%r9, SPEAKER_FREQUENCY		; *anti-interlock*
	mlt.h	%r11, %r9			; (16000×(1..32)なので、mlt.hで充分)
	ld.w	%r11, %alr
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = count = audio->count /* 取り出し */
	xld.ub	%r6, [%r12+AUDIO_LFSR5]		; %r6 = lfsr5 = audio->lfsr5 /* 取り出し */
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		; Update output
	;
	xld.w	%r14, TIA_CLOCK/114		; %r14 = clock = TIA_CLOCK / 114
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mix9_DO:				; do {
	sub	%r4, %r14			;   count -= clock
	xjruge	tia_audio_mix9_NO_ADVANCE	;   if(count < 0) { /*!NonCarry*/
tia_audio_mix9_ADVANCE_DO:			;     do {
	UPDATE_LFSR5	%r6			;         Update LFSR
	add	%r4, %r11			;     } while((count += period) < 0) /*NonCarry*/
	xjruge	tia_audio_mix9_ADVANCE_DO
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		;     Update output
	;
tia_audio_mix9_NO_ADVANCE:			;   }
	ld.h	%r9, [%r13]			;   *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mix9_DO
	;
	xld.w	[%r12+AUDIO_COUNT], %r4		; audio->count = count /* 書き戻し */
	xld.b	[%r12+AUDIO_LFSR5], %r6		; audio->lfsr5 = lfsr5 /* 書き戻し */
tia_audio_mix9_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

;
;	30KHz/Freq pulse -> Div31 pulse -> Poly5 output ->
;
	.global	tia_audio_mixA
tia_audio_mixA:
	xld.ub	%r10, [%r12+AUDIO_VOLUME]	; %r10 = volume = audio->volume
	cmp	%r10, 0				; !INTERLOCK!
	xjreq	tia_audio_mixA_EXIT		; if(!volume) goto EXIT
	;
	xld.ub	%r11, [%r12+AUDIO_FREQUENCY]	; %r11 = period = SPEAKER_FREQUENCY * audio->frequency
	xld.w	%r9, SPEAKER_FREQUENCY		; *anti-interlock*
	mlt.h	%r11, %r9			; (16000×(1..32)なので、mlt.hで充分)
	ld.w	%r11, %alr
	;
	xld.w	%r4, [%r12+AUDIO_COUNT]		; %r4 = count = audio->count /* 取り出し */
	xld.ub	%r5, [%r12+AUDIO_DIV31]		; %r5 = div31 = audio->div31 /* 取り出し */
	xld.ub	%r6, [%r12+AUDIO_LFSR5]		; %r6 = lfsr5 = audio->lfsr5 /* 取り出し */
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		; Update output
	;
	xld.w	%r14, TIA_CLOCK/114		; %r14 = clock = TIA_CLOCK / 114
	xld.w	%r15, TIABUFLEN			; %r15 = i = TIABUFLEN
tia_audio_mixA_DO:				; do {
	sub	%r4, %r14			;   count -= clock
	xjruge	tia_audio_mixA_NO_ADVANCE	;   if(count < 0) { /*!NonCarry*/
tia_audio_mixA_ADVANCE_DO:			;     do {
	xsub	%r5, %r5, 1			;       if(--div31 < 0) div31 += 31
	jruge	2
	add	%r5, 31				;       (skip?)
	jreq	2
	cmp	%r5, 13				;       (skip?)
	xjrne	tia_audio_mixA_ADVANCE_LOOP	;       if(div31 == 0 || div31 == 13) {
	UPDATE_LFSR5	%r6			;         Update LFSR
tia_audio_mixA_ADVANCE_LOOP:			;       }
	add	%r4, %r11			;     } while((count += period) < 0) /*NonCarry*/
	xjruge	tia_audio_mixA_ADVANCE_DO
	;
	UPDATE_OUTPUT	%r6, %r7, %r10		;     Update output
	;
tia_audio_mixA_NO_ADVANCE:			;   }
	ld.h	%r9, [%r13]			;   *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	xsub	%r15, %r15, 1			; } while(--i)
	xjrne	tia_audio_mixA_DO
	;
	xld.w	[%r12+AUDIO_COUNT], %r4		; audio->count = count /* 書き戻し */
	xld.b	[%r12+AUDIO_DIV31], %r5		; audio->div31 = div31 /* 書き戻し */
	xld.b	[%r12+AUDIO_LFSR5], %r6		; audio->lfsr5 = lfsr5 /* 書き戻し */
tia_audio_mixA_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

#endif /*TIA_ASM*/
