;***
; двухбайтное сравнение
	ldi	r16,low(777)
	cpi	zh,high(777)
	cpc	zl,r16

==========

.def dataL = r4		; multiplicand low byte
.def dataH = r5		; multiplicand high byte
.def KoeffL = r2	; multiplier low byte
.def koeffH = r3	; multiplier high byte
.def temp = r16		; result byte 0 (LSD)
.def temp1 = r17	; result byte 1
.def temp2 = r18	; result byte 2 (MSD)

;**************************************************************************
; умножение двух 16-разрядных величин, только для Mega
; исходные величины dataH-dataL и KoeffH-KoeffL
; результат 3 байта temp2:temp1:temp
Mul16:
	clr	temp2		; очистить старший
	mul	dataL,KoeffL	; умножаем младшие
	mov	temp,r0		; в R0 младший результата операции mul
	mov	temp1,r1	; в R1 старший результата операции mul
	mul	dataH,KoeffL	; умножаем старший на младший
	add	temp1,r0	; в R0 младший результата операции mul
	adc	temp2,r1	; в R1 старший результата операции mul
	mul	dataL,KoeffH	; умножаем младший на старший
	add	temp1,r0	; в R0 младший результата операции mul
	adc	temp2,r1	; в R1 старший результата операции mul
	mul	dataH,KoeffH	; умножаем старший на старший
	add	temp2,r0	; 4-й разряд нам тут не требуется, но он - в R1
	ret
;**************************************************************************

==================================

;***************************************************************************
; перемножение двух 16-разрядных величин,
; результат 3 байта
mpy16u:	clr	tmp2
	ldi	count,16	;init loop counter
m16u_1:	lsr	KoeffH
	ror	KoeffL

	brcc	noad8		;if bit 0 of multiplier set
	add	tmpm,IzmL	;add multiplicand Low to byte 2 of res
	adc	tmp2,IzmH	;add multiplicand high to byte 3 of res
noad8:	ror	tmp2		;rotate right result byte 2
	ror	tmpm		;rotate result byte 1 and multiplier High
	ror	temp		;rotate result byte 0 and multiplier Low
	dec	count		;decrement loop counter
	brne	m16u_1		;if not done, loop more
	ret

;***************************************************************************
; перемножение двух 16-разрядных величин, результат 4 байта, рабочая
; множимое KoeffH:KoeffL, множитель IzmH:IzmL, результат tmp3:tmp2:tmpm:temp
; использует count
; слов:	14 + return. циклов: 153 + return + rcall
mpy16u:	clr	tmp3		;clear 2 highest bytes of result
	clr	tmp2
	ldi	count,16	;init loop counter
m16u_1:	lsr	KoeffH
	ror	KoeffL
	brcc	noad8		;if bit 0 of multiplier set
	add	tmp2,IzmL	;add multiplicand Low to byte 2 of res
	adc	tmp3,IzmH	;add multiplicand high to byte 3 of res
noad8:	ror	tmp3		;shift right result byte 3
	ror	tmp2		;rotate right result byte 2
	ror	tmpm		;rotate result byte 1 and multiplier High
	ror	temp		;rotate result byte 0 and multiplier Low
	dec	count		;decrement loop counter
	brne	m16u_1		;if not done, loop more
	ret

==================================
;***************************************************
;* Mutiply 32x32 -> 64 bit
;*     A        B         C
;*  R24:R21 x R5:R2 -> R15:R8
;*
;*  88 cycles + 4 (RET) = 92 Cycles
;*
mult32:
		clr	R16
		mul	R21,R2	; умножили A1 на Б1
		movw	R8,R0	; рез положили в Ц1-2
		clr	R10
		clr	R11
		clr	R12
		clr	R13
		clr	R14
		clr	R15
		mul	R22,R2	; умн А2 на Б1
		add	R9,R0	; рез1 доб к Ц2
		adc	R10,R1	; рез2 доб к Ц3
		mul	R23,R2	; умн А3 на Б1
		add	R10,R0	; рез1 доб к Ц3
		adc	R11,R1	; рез2 доб к Ц4
		mul	R24,R2	; А4 умн на Б1
		add	R11,R0  ; рез1 доб к Ц4
		adc	R12,R1  ; рез2 доб к Ц5

		mul	R21,R3
		add	R9,R0
		adc	R10,R1
		adc	R11,R16
		adc	R12,R16
		adc	R13,R16
		mul	R22,R3
		add	R10,R0
		adc	R11,R1
		adc	R12,R16
		adc	R13,R16
		mul	R23,R3
		add	R11,R0
		adc	R12,R1
		adc	R13,R16
		mul	R24,R3
		add	R12,R0
		adc	R13,R1

		mul	R21,R4
		add	R10,R0
		adc	R11,R1
		adc	R12,R16
		adc	R13,R16
		adc	R14,R16
		mul	R22,R4
		add	R11,R0
		adc	R12,R1
		adc	R13,R16
		adc	R14,R16
		mul	R23,R4
		add	R12,R0
		adc	R13,R1
		adc	R14,R16
		mul	R24,R4
		add	R13,R0
		adc	R14,R1

		mul	R21,R5
		add	R11,R0
		adc	R12,R1
		adc	R13,R16
		adc	R14,R16
		adc	R15,R16
		mul	R22,R5
		add	R12,R0
		adc	R13,R1
		adc	R14,R16
		adc	R15,R16
		mul	R23,R5
		add	R13,R0
		adc	R14,R1
		adc	R15,R16
		mul	R24,R5
		add	R14,R0
		adc	R15,R1
		ret
==================================
;***************************************************
;* Mutiply 24x16 -> 40 bit (3*2=5 Bytes)
;*     A        B         C
;*  R23:R21 x R3:R2 -> R12:R8
;*
;*  30 cycles + 4 (RET) = 34 Cycles
;*
mul24x16:
		clr	R16
		mul	R21,R2	; A1*B1
		movw	R8,R0	; Rez->C1C2
		clr	R10
		clr	R11
		clr	R12
		mul	R22,R2	; A2*B1
		add	R9,R0	; C2+=Rez1
		adc	R10,R1	; C3+=Rez2
		mul	R23,R2	; A3*B1
		add	R10,R0	; C3+=Rez1
		adc	R11,R1	; C4+=Rez2

		mul	R21,R3	; A1*B2
		add	R9,R0	; C2+=Rez1
		adc	R10,R1	; C3+=Rez2
		adc	R11,R16	; C4+=C flag
		adc	R12,R16 ; C5+=C flag
		mul	R22,R3	; A2*B2
		add	R10,R0	; C3+=Rez1
		adc	R11,R1	; C4+=Rez2
		adc	R12,R16	; C5+=C flag
		mul	R23,R3	; A3*B2
		add	R11,R0	; C4+=Rez1
		adc	R12,R1	; C5+=Rez2
		ret

;***************************************************************************
;*
;* "mpy16u8" - 16x8 Bit Unsigned Multiplication
;*
;* This subroutine multiplies 16-bit and 8-bit register variables
;* mp16uH:mp16uL and mc16uL
;* The result is placed in m16u2:m16u1:m16u0.
;*
;* Number of words	:13 + return
;* Number of cycles	:137? + return
;* Low registers used	:1 (R0)
;* High registers used  :5 (mc16uL,mp16uL/m16u0,mp16uH/m16u1,m16u2,mcnt16u)
;*
;***************************************************************************

;***** Subroutine Register Variables

.def	mc16uL	=r16		;multiplicand low byte
.def	mp16uL	=r18		;multiplier low byte
.def	mp16uH	=r19		;multiplier high byte
.def	m16u0	=r18		;result byte 0 (LSB)
.def	m16u1	=r19		;result byte 1
.def	m16u2	=r20		;result byte 2
.def	mcnt16u	=r22		;loop counter

;***** Code

mpy16u8:clr	R0
	clr	m16u2		;clear high byte of result
	ldi	mcnt16u,16	;init loop counter
m16u_1:	lsr	mp16uH
	ror	mp16uL

	brcc	noad8		;if bit 0 of multiplier set
	add	m16u1,mc16uL	;add multiplicand Low to byte 1 of res
	adc	m16u2,R0	;add multiplicand high to byte 2 of res
noad8:	ror	m16u2		;rotate right result byte 2
	ror	m16u1		;rotate result byte 1 and multiplier High
	ror	m16u0		;rotate result byte 0 and multiplier Low
	dec	mcnt16u		;decrement loop counter
	brne	m16u_1		;if not done, loop more
	ret

==================================

;*************************************************************************
; div32x8 - 32/8 деление беззнаковых чисел
; Делимое и результат в countHH (старший), countTH,
; countTM, countTL (младший)
; делитель в cikle
; требуется четыре рабочих регистра dremL — dremHH
; из диапазона R16-R31 для хранения остатка
div32x8:
	clr	temp 		; "ZERO"
	clr	dremL		;clear remainder Low byte
	clr	dremM		;clear remainder
	clr	dremH		;clear remainder
	sub	dremHH,dremHH	;clear remainder High byte and carry
	ldi	cnt,33		;init loop counter
d_1:	rol	countTL		;shift left dividend
	rol	countTM
	rol	countTH
	rol	countHH
	dec	cnt		;decrement counter
	brne	d_2		;if done
	ret			;return
d_2:	rol	dremL		;shift dividend into remainder
	rol	dremM
	rol	dremH
	rol	dremHH
	sub	dremL,cikle	;remainder = remainder — divisor
	sbc	dremM,temp
	sbc	dremH,temp
	sbc	dremHH,temp
	brcc	d_3		;if result negative
	add	dremL,cikle	;restore remainder
	adc	dremM,temp
	adc	dremH,temp
	adc	dremHH,temp
	clc			;clear carry to be shifted into result
	rjmp d_1		;else
d_3:	sec			; set carry to be shifted into result
	rjmp d_1
; ************************************************************** конец 32/8

====================================
;***************************************************************************
;*
;* "div24u16" - 24/16 Bit Unsigned Division
;* (по сути это 24/24)
;* Эта процедура делит 3-х байтное число на 2-х байтное
;* "dd16uH:dd16uM:dd16uL" (dividend) and "dv16uH:dv16uL" (divisor).
;* The result is placed in "dres16uH:dres16uM:dres16uL" and the remainder in
;* "drem16uH:drem16uM:drem16uL".
;*
;* Number of words	:25 (50 bytes)
;* Number of cycles	:?/? (Min/Max)
;* Low registers used	:7 (drem16uL,drem16uM,drem16uH,dres16uL/dd16uL,dres16uM/dd16uM,dres16uH/dd16uH,ZERO)
;* High registers used  :3 (dv16uL,dv16uH,dcnt16u)
;*
;***************************************************************************

;***** Subroutine Register Variables

.def	ZERO	=R12
.def	drem16uL=r13
.def	drem16uM=r14
.def	drem16uH=r15
.def	dres16uL=r16
.def	dres16uM=r17
.def	dres16uH=r18
.def	dd16uL	=r16
.def	dd16uM	=r17
.def	dd16uH	=r18
.def	dv16uL	=r19
.def	dv16uH	=r20
.def	dcnt16u	=r21

;***** Code

div24u:	clr	ZERO
	clr	drem16uL	;clear remainder Low byte
	clr	drem16uM	;clear remainder Middle byte
	sub	drem16uH,drem16uH;clear remainder High byte and carry
	ldi	dcnt16u,25	;init loop counter
d24u_1:	rol	dd16uL		;shift left dividend
	rol	dd16uM
	rol	dd16uH
	dec	dcnt16u		;decrement counter
	brne	d24u_2		;if done
	ret			;    return
d24u_2:	rol	drem16uL	;shift dividend into remainder
	rol	drem16uM
	rol	drem16uH
	sub	drem16uL,dv16uL	;remainder = remainder - divisor
	sbc	drem16uM,dv16uH
	sbc	drem16uH,ZERO
	brcc	d24u_3		;if result negative
	add	drem16uL,dv16uL	;    restore remainder
	adc	drem16uM,dv16uH
	adc	drem16uH,ZERO
	clc			;    clear carry to be shifted into result
	rjmp	d24u_1		;else
d24u_3:	sec			;    set carry to be shifted into result
	rjmp	d24u_1

; *************************************************************************
; процедура деления 24/8 отличается от 24/16 только тем,
; что старший байт делителя всегда равен 0
; *************************************************************************
; div24u8 - 24/8 деление беззнаковых чисел
; Делимое и результат в countH (старший), countTM, countTL (младший)
; делитель в divisor, использует R0, cnt
; требуется три рабочих регистра dremL — dremH для хранения остатка
; 25 слов, 5+24*(17-19)+5+4=(408-456)+14=422--470 тактов
; + 3 такта на rcall :-)
div24u8:clr	R0
	clr	dremL		;clear remainder Low byte
	clr	dremM		;clear remainder Midle byte
	sub	dremH,dremH	;clear remainder High byte and carry
	ldi	cnt,25		;init loop counter
d_1:	rol	countTL		;shift left dividend
	rol	countTM
	rol	countTH
	dec	cnt		;decrement counter
	brne	d_2		;if done
	ret			;return
d_2:	rol	dremL		;shift dividend into remainder
	rol	dremM
	rol	dremH
	sub	dremL,divisor	;remainder = remainder — divisor
	sbc	dremM,R0
	sbc	dremH,R0
	brcc	d_3		;if result negative
	add	dremL,divisor	;restore remainder
	adc	dremM,R0
	adc	dremH,R0
	clc			;clear carry to be shifted into result
	rjmp d_1		;else
d_3:	sec			; set carry to be shifted into result
	rjmp d_1
; ************************************************************** конец 24/8


;***************************************************************************
;*
;* "div16u8" - 16/8 Bit Unsigned Division
;*
;* This subroutine divides the 16-bit / 8-bit numbers
;* "dd16uH:dd16uL" (dividend) and "dv16uL" (divisor).
;* The result is placed in "dres16uH:dres16uL" and the remainder in
;* "drem16uH:drem16uL".
;*
;* Number of words	:19
;* Number of cycles	:235/251 (Min/Max)
;* Low registers used	:2 (drem16uL,drem16uH)
;* High registers used  :4 (dres16uL/dd16uL,dres16uH/dd16uH,dv16uL,dcnt16u)
;*
;***************************************************************************

;***** Subroutine Register Variables

.def	drem16uL=r14
.def	drem16uH=r15
.def	dres16uL=r16
.def	dres16uH=r17
.def	dd16uL	=r16
.def	dd16uH	=r17
.def	dv16uL	=r18
.def	dcnt16u	=r19

;***** Code

div16u:	clr	R0
	clr	drem16uL	;clear remainder Low byte
	sub	drem16uH,drem16uH;clear remainder High byte and carry
	ldi	dcnt16u,17	;init loop counter
d16u_1:	rol	dd16uL		;shift left dividend
	rol	dd16uH
	dec	dcnt16u		;decrement counter
	brne	d16u_2		;if done
	ret			;    return
d16u_2:	rol	drem16uL	;shift dividend into remainder
	rol	drem16uH
	sub	drem16uL,dv16uL	;remainder = remainder - divisor
	sbc	drem16uH,R0	;
	brcc	d16u_3		;if result negative
	add	drem16uL,dv16uL	;    restore remainder
	adc	drem16uH,R0
	clc			;    clear carry to be shifted into result
	rjmp	d16u_1		;else
d16u_3:	sec			;    set carry to be shifted into result
	rjmp	d16u_1


====================================
;******************************
; делим двубайтное число на 10
; вход: JobH:JobL
; выход: XH:XL, остаток может быть в JobL
; использует:
DIV16_10:
	clr	XL		; инициируем счётчик десятков
	clr	XH
	sbiw	X,1
DIV16_10_l1:
	adiw	X,1		; увеличили счётчик
	sbiw	JobL,10		; уменьшили исходное число
	brsh	DIV16_10_l1	; если остаток > 0 -- ещё на круг
;	inc	JobL		; если нужен остаток

	ret
