; *************************************************************************** ; 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 Utils_Divu16_16_16: mov r16, r20 ; r17:r16=result (intitially: dividend) mov r17, r21 clr r18 ; r19:r18=remainder clr r19 ldi r26, 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 r26 brne Utils_Divu16_16_16_loop ret ; @end