Files
aqhomecontrol/avr/common/divide.asm
2026-03-15 20:20:33 +01:00

65 lines
1.9 KiB
NASM

; ***************************************************************************
; copyright : (C) 2025 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
#ifndef COMMON_DIVIDE_H
#define COMMON_DIVIDE_H
; ---------------------------------------------------------------------------
; @routine Utils_Divu16_16_16
;
; Divides two unsigned 16 bit values resulting in one 16 bit value.
; This is a rather simple but reasonable fast routine working just like you would
; when doing divisions with pen and paper.
;
; R17:R16 = R21:R20 / R23:R22
; R19:R18 = R21:R20 mod R23:R22
; TODO: adapt for signed values
;
; @param R21:R20 16 bit value A
; @param R23:R22 16 bit value B
; @return R17:R16 16 bit result
; @return R19:R18 16 bit remainder
; @clobbers R25
Utils_Divu16_16_16:
mov r16, r20 ; r17:r16=result (intitially: dividend)
mov r17, r21
clr r18 ; r19:r18=remainder
clr r19
ldi r25, 16 ; 16 bits to divide
Utils_Divu16_16_16_loop:
lsl r16 ; shift 0 bit into result
rol r17
rol r18
rol r19
sub r18, r22 ; try to subtract divisor from value
sbc r19, r23
brcs Utils_Divu16_16_16_nofit ; jmp if dividend < divisor
ori r16, 1 ; otherwise set bit in result
rjmp Utils_Divu16_16_16_loop_end
Utils_Divu16_16_16_nofit:
add r18, r22 ; undo subtraction
adc r19, r23
; r17:r16=result
Utils_Divu16_16_16_loop_end:
dec r25
brne Utils_Divu16_16_16_loop
ret
; @end
#endif