;**************************************************************************
;
; Filename : CALCULATE.ASM
; ------------------------
;
; (c) 1991 by Thomas Lehmann
;
;
; Jackophone V5.00
;
;
; verschiedene Urechnungs Routinen
;
;
;**************************************************************************

MODUL_START	set	*	; Größe des Moduls berechnen



; =========================================================================
;
; Funktion	: 1 Byte erzeugen
;
; Eingang	: high Byte im Accu
;	: low Byte in Y-Reg.
;
; Ausgang	: merged Byte im Accu
;
; Register	: Accu
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

merge_val	asl		; high Byte ins obere Nibble schieben
	asl
	asl
	asl
	sty hlp_reg	; low Byte merken
	ora hlp_reg	; low Byte ins untere Nibble
	rts



; =========================================================================
;
; Funktion	: dezimal Wert in Hex wandeln
;
; Eingang	: dezimaler Wert im Accu
;
; Ausgang	: hex Byte im Accu
;
; Register	: Accu
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

deztohex
	block
	stz hlp_reg	; Hilfsregister

loop	cmp #16		; Wert ok ?
	bcc end		; ja, Hex dazu

	sec
	sbc #16		; Hex abziehen
	pha
	lda hlp_reg	; Dezimalwert laden
	clc
	adc #10		; Hexwert erzeugen
	sta hlp_reg	; und wieder ablegen
	pla
	bra loop	; neuer Durchlauf

end	clc
	adc hlp_reg	; errechneten Hexwert zum Rest addieren
	rts
	bend




; =========================================================================
;
; Funktion	: BIT erzeugen
;
; Eingang	: BIT Nr. im ACCU
;
; Ausgang	: BIT im ACCU nach BIT Nr. gesetzt
;
; Register	: Accu
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

mk_bit
	block
	phy		; Y-Reg. retten
	tay		; BIT Nr. nach Y

	lda #00
	sec		; BIT 0 einstellen
loop	rol a		; BIT in Position schieben
	dey		; BIT Nr. gefunden ?
	bpl loop	; nein, weiter schieben

	ply		; Y-Reg zurück
	rts		; BIT im ACCU
	bend


; =========================================================================
;
; Funktion	: BIT setzen, löschen und testen
;
; Eingang	: Zero-Page Adr. für BIT SET/CLR/TST in X-Reg.
;	  BIT Nr. im ACCU (0-7)
;
; Ausgang	: SEC/CLC bei TST_BIT
;
; Register	: --------
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

set_bit	pha		; BIT Nr. retten
	stx ind_adr	; Adr. für BIT set
	stz ind_adr+1
	jsr mk_bit	; BIT erzeugen
	ora (ind_adr)	; bereits gesetzte BIT`s dazugeben
	sta (ind_adr)	; BIT in angegebener Adr. setzen
	pla
	rts

clr_bit	pha		; BIT Nr. retten
	stx ind_adr	; Adr. für BIT clr
	stz ind_adr+1
	jsr mk_bit	; BIT erzeugen
	eor #$ff	; BIT`s drehen
	and (ind_adr)	; andere BIT`s beibehalten
	sta (ind_adr)	; BIT in angegebener Adr. löschen
	pla
	rts


tst_bit
	block
	pha		; BIT Nr. retten
	stx ind_adr	; Adr. für BIT Test
	stz ind_adr+1
	jsr mk_bit	; BIT erzeugen
	and (ind_adr)	; BIT in angegebener Adr. testen
	sec
	bne end		; BIT ist gesetzt

	clc		; BIT gelöscht
end	pla
	rts
	bend






; =========================================================================
;
; Funktion	: Addition
;
; Eingang	: 8 BIT + 8 BIT
;	  LSB ACCU + LSB Y
;	  Resultat: MSB Accu, LSB Y
;
;	  16 BIT + 8 BIT
;	  ( MSB ACCU, LSB X ) + LSB Y
;	  Resultat: MSB Accu, LSB Y
;
;	  16 BIT + 16 BIT
;	  ( MSB Accu, LSB X ) + ( MSB hlp_reg, LSB Y )
;	  Resultat: MSB Accu, LSB Y
;
; Ausgang	: Resulat MSB im ACCU
;		  LSB in X
;
; Register	: ACCU, X
;
; (c) by Thomas Lehmann Oktober 1991
;
; =========================================================================


	; 8 BIT + 8 BIT Addition, Accu + Y
	; --------------------------------
add8_8	ldx #$00	; MSB Source add Wert
	phx		; MSB add Wert
	stz calc_reg+1	; MSB
	bra add		; Addition durchführen


	; 16 BIT + 8 BIT Addition, (ACCU und X) + Y
	; -----------------------------------------
add16_8	pha		; MSB Source Wert
	stz calc_reg+1	; MSB
	txa		; LSB Source Wert
	bra add		; Addition durchführen


	; 16 BIT + 16 BIT Addition, (ACCU und X) + hlp_reg und Y
	; ------------------------------------------------------
add16_16	pha		; MSB Source Wert
	lda hlp_reg	; MSB add Wert
	sta calc_reg+1
	txa		; LSB Source Wert




	; 16 BIT Addition
	; ===============
add
	block
	sty calc_reg	; aufzuaddierender Wert, low

	; low Byte addieren
	; -----------------
	clc
	adc calc_reg	; low Byte des Werts + aufzuaddierender Wert
	tax

	; high Byte addieren
	; ------------------
	pla		; high Source Wert
	adc calc_reg+1	; Resultat high
	rts
	bend



; =========================================================================
;
; Funktion	: Multiplikation:
;
; Eingang	: 8 BIT * 8 BIT
;	  ACCU * Y
;
;	  16 BIT * 8 BIT
;	  ( MSB ACCU, LSB X ) * Y
;
;	  16 BIT * 16 BIT, nicht implementiert !!!
;	  ( MSB ACCU, LSB X ) * ( MSB hlp_reg, LSB Y )
;
;
; Ausgang	: Resulat MSB im ACCU
;		  LSB in X-Reg.
;
; Register	: ACCU, X
;
; (c) by Thomas Lehmann August 1991
;
; =========================================================================

; Offset auf "calc_reg"
; --------------------
	org	0
EXP1	sdo	2	; Multiplikant
EXP2	sdo	2	; Multiplikator
SCRATCH	sdo	2	; internes Hilfsregister


	; 8 BIT * 8 BIT Multiplikation, ACCU * Y
	; --------------------------------------
mul8_8	stz calc_reg+EXP1+1	; Multiplikant, MSB
	sta calc_reg+EXP1	; LSB
	stz calc_reg+EXP2+1	; Multiplikator, MSB
	sty calc_reg+EXP2	; LSB
	bra mult	; Multiplikation durchführen


	; 16 BIT * 8 BIT Multiplikation, (ACCU und X) * Y
	; -----------------------------------------------
mul16_8	sta calc_reg+EXP1+1	; Multiplikant, MSB
	stx calc_reg+EXP1	; LSB
	stz calc_reg+EXP2+1	; Multiplikator MSB
	sty calc_reg+EXP2	; LSB




	; 16 BIT Multiplikation
	; =====================
mult
	block
	phy
	stz calc_reg+SCRATCH	; MUL internes Hilfsregister
	stz calc_reg+SCRATCH+1
	ldy #16		; Anzahl der BIT`s
	bra mul_2
	
mul_1	clc
	lda calc_reg+SCRATCH
	adc calc_reg+EXP2
	sta calc_reg+SCRATCH
	lda calc_reg+SCRATCH+1
	adc calc_reg+EXP2+1
	sta calc_reg+SCRATCH+1

mul_2	lsr calc_reg+SCRATCH+1
	ror calc_reg+SCRATCH
	ror calc_reg+EXP1+1
	ror calc_reg+EXP1
	dey
	bmi mul_end	; alle BIT`s multipliziert, Ende
	bcc mul_2	; kein Überlauf
	bcs mul_1

mul_end	lda calc_reg+EXP1+1	; MSB des Resultats
	ldx calc_reg+EXP1	; LSB des Resultats
	ply
	rts
	bend



; =========================================================================
;
; Funktion	: Division: 8BIT * 8BIT, 16BIT * 8BIT, 16BIT * 16BIT
;
; Eingang	: 8 BIT * 8 BIT
;	  ACCU / Y
;
;	  16 BIT / 8 BIT
;	  ( MSB ACCU, LSB X) / Y
;
;	  16 BIT / 16 BIT, nicht implementiert !!!
;	  ( MSB ACCU, LSB X) / ( MSB hlp_reg, LSB Y )
;
;
; Ausgang	: Resulat MSB im ACCU
;		  LSB in X
;		  Rest in Y
;
; Register	: ACCU, X, Y
;
; (c) by Thomas Lehmann Oktober 1991
;
; =========================================================================

; Offset auf "calc_reg"
; --------------------
	org	0
EXP1	sdo	2	; Wert
EXP2	sdo	2	; Divisor
REMAIN	sdo	2	; internes Hilfsregister


	; 8 BIT / 8 BIT Divison, ACCU / Y
	; -------------------------------
div8_8	stz calc_reg+EXP1+1	; Divident, MSB
	sta calc_reg+EXP1		; LSB
	stz calc_reg+EXP2+1	; Divisor, MSB
	sty calc_reg+EXP2		; LSB
	bra div			; Division durchführen


	; 16 BIT / 8 BIT Division, (ACCU und X) / Y
	; -----------------------------------------
div16_8	sta calc_reg+EXP1+1	; Divident, MSB
	stx calc_reg+EXP1		; LSB
	stz calc_reg+EXP2+1	; Divisor, MSB
	sty calc_reg+EXP2		; LSB




	; 16 BIT Division
	; ---------------
div
	block
	stz calc_reg+REMAIN	; DIV internes Hilfsregister
	stz calc_reg+REMAIN+1
	ldy #16			; Anzahl der BIT`s

div_1	asl calc_reg+EXP1
	rol calc_reg+EXP1+1
	rol calc_reg+REMAIN
	rol calc_reg+REMAIN+1

	sec
	lda calc_reg+REMAIN
	sbc calc_reg+EXP2
	tax	
	lda calc_reg+REMAIN+1
	sbc calc_reg+EXP2+1
	bcc div_2		; kein Überlauf

	stx calc_reg+REMAIN
	sta calc_reg+REMAIN+1
	inc calc_reg+EXP1

div_2	dey
	bne div_1

	lda calc_reg+EXP1+1	; MSB des Resultats
	ldx calc_reg+EXP1		; LSB des Resultats
	ldy calc_reg+REMAIN	; low Rest der Division
	rts
	bend








; =========================================================================
;
; Funktion	: Multiplikation: 8BIT * 8BIT + 16BIT Addition
;
; Eingang	: ( Accu * Y ) + ( MSB hlp_reg, LSB X )
;
; Ausgang	: Resulat MSB im ACCU
;		  LSB in X-Reg.
;
; Register	: ACCU, X, Y
;
; (c) by Thomas Lehmann August 1991
;
; =========================================================================

mul_add	phx		; LSB add Wert
	jsr mul8_8	; Accu * Y == Accu, X
	ply
	jmp add16_16	; (ACCU, X) + (hlp_reg, Y) == (Accu, X)





; --------------------------------------------------------------------------

HLP	set	*
_CALCULATE	equ	HLP-MODUL_START		; Größe des Moduls

