; ***************************************************************************
; 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



