kolibrios-fun/contrib/toolchain/avra/examples/throttle_divide.asm

136 lines
5.7 KiB
NASM
Raw Normal View History

;throttle_divide.asm
;
;********************************************************************************
;* div16u *
;* Second Level Subroutine *
;* *
;* Program from Atmel file avr200.asm *
;* *
;* Since the 25kHz pwm cycle is 64 clock cycles long, this subroutine *
;* requires 3.67 to 3.92 25kHz clock cycles. *
;* *
;* A single line was added which adds 3 to Cycle_count *
;* *
;* Inputs: HILOCAL2:HILOCAL1 and B_TEMPLOCAL1:B_TEMPLOCAL *
;* Returns: HILOCAL2:HILOCAL1 = HILOCAL2:HILOCAL1 / B_TEMPLOCAL1:B_TEMPLOCAL *
;* LOLOCAL2:LOLOCAL1 = remainder *
;* Changed: B_TEMPLOCAL2 *
;* *
;* Calls: Not allowed *
;********************************************************************************
B_TEMPLOCAL2 dcnt16u ; Local counter
HILOCAL1 dd16uL ; 16 bit Innput
HILOCAL2 dd16uH
B_TEMPLOCAL dv16uL ; 16 bit Input
B_TEMPLOCAL1 dv16uH
HILOCAL1 dres16uL ; 16 bit Output
HILOCAL2 dres16uH
LOWLOCAL1 drem16uL ; 16 bit Remainder
LOWLOCAL2 drem16uH ;
;<ATMEL ROUTINE>
;***************************************************************************
;*
;* "div16u" - 16/16 Bit Unsigned Division
;*
;* This subroutine divides the two 16-bit numbers
;* "dd16uH:dd16uL" (dividend) and "dv16uH: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 :5 (dres16uL/dd16uL,dres16uH/dd16uH,dv16uL,dv16uH,
;* dcnt16u)
;*
;***************************************************************************
;***** Subroutine Register Variables
;.def drem16uL= r14 ; Reassigned
;.def drem16uH= r15
;.def dres16uL= r16
;.def dres16uH= r17
;.def dd16uL= r16
;.def dd16uH= r17
;.def dv16uL= r18
;.def dv16uH= r19
;.def dcnt16u= r20
;***** Code
div16u:
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
subi Cycle_count,256-3 ; Add 3 to Cycle_count
ret ; return
d16u_2:
rol drem16uL ; shift dividend into remainder
rol drem16uH
sub drem16uL,dv16uL ; remainder = remainder - divisor
sbc drem16uH,dv16uH ;
brcc d16u_3 ;
add drem16uL,dv16uL ; if result negative
adc drem16uH,dv16uH ; restore remainder
clc ; clear carry to be shifted into result
rjmp d16u_1 ;
d16u_3: ; if result NOT negative
sec ; set carry to be shifted into result
rjmp d16u_1
;<END ATMEL ROUTINE>
;********************************************************************************
;* DIVIDE_16_SIMPLE *
;* Second Level Subroutine *
;* *
;* Inputs: dd16uH:dd16ul and dv16uL *
;* Returns: dres16uH:dres16uL = dd8uH:dd8uL / 2^dv16uL *
;* *
;* Changed: nothing else *
;* N.B that dd16uH, dd16uL, dv16uH and dv16uL are aliases for: *
;* dd16uH=error_hi *
;* dd16uL=error_lo *
;* dv16uH=B_TempX *
;* dv16uL=B_TempX *
;* dcnt16u=B_TempX *
;* Calls: Not allowed *
;********************************************************************************
DIVIDE_16_SIMPLE:
inc dv16uL
DIVIDE_16_SIMPLE_LOOP:
dec dv16uL ; decrement counter
brne DIVIDE_BY_2
ret
DIVIDE_BY_2:
asr dd16uH ; divide by two
ror dd16uL
rjmp DIVIDE_16_SIMPLE_LOOP