|
@@ -0,0 +1,450 @@
|
|
|
+;***
|
|
|
+; двухбайтное сравнение
|
|
|
+ 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
|