123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- ;***
- ; двухбайтное сравнение
- 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
|