;* --------------------------------------------------------------------------------------
;*  Copyright (C) 2004 Dallas Semiconductor Corporation, All Rights Reserved.
;* 
;*  Permission is hereby granted, free of charge, to any person obtaining a
;*  copy of this software and associated documentation files (the "Software"),
;*  to deal in the Software without restriction, including without limitation
;*  the rights to use, copy, modify, merge, publish, distribute, sublicense,
;*  and/or sell copies of the Software, and to permit persons to whom the
;*  Software is furnished to do so, subject to the following conditions:
;* 
;*  The above copyright notice and this permission notice shall be included
;*  in all copies or substantial portions of the Software.
;* 
;*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
;*  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
;*  MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
;*  IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
;*  OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
;*  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
;*  OTHER DEALINGS IN THE SOFTWARE.
;* 
;*  Except as contained in this notice, the name of Dallas Semiconductor
;*  shall not be used except as stated in the Dallas Semiconductor
;*  Branding Policy.
;*
;*  Module:        divide32
;*  Description:   32/32-bit divide routines
;*  Filename:      divide32.asm
;*  Date:          October 13, 2004
;*  Version:       1.00
;*
;*  Implementations for 32 bit divide.  Provides both the remainder and the result, which
;*  are both very useful for translating numbers to decimal representations, and for 
;*  parsing a number of seconds into a human readable time.
;*
;*  The only function that should be called by applications is 'DIV32'.
;*
;* --------------------------------------------------------------------------------------
  .code
;********************************************************************
;*
;* Function:    DIV32, Unsigned_Divide32
;*
;* Description: Divides 32 bit number by 32 bit number
;*
;* Input:       A[1:0] - Dividend
;*              A[3:2] - Divisor
;*
;* Output:      A[3:2] - Remainder
;*              A[1:0] - Quotient
;*
;* Destroys:    A[8:4], PSF, LC[0], AP/APC=0
;*
;********************************************************************
Div32::
Q20_Unsigned_Divide32::
  move  AP, #7                          ;
  move  acc, A[2]                       ; test for zero divisor
  or    A[3]                            ;
  move  C, #1                           ; preset error condition
  sjump NZ, M32_Q20Div_Begin            ;
  sjump M32_Q20Div_Done                 ; divide by zero detected

M32_Q20Div_Begin:
;
; speed up with AP/APC
;
  move  A[7], A[3]                      ; move divisor to make room
  move  A[6], A[2]                      ; for remainder
  move  A[5], #0                        ;
  move  A[4], #0                        ;
  move  A[3], #0                        ; clear remainder
  move  A[2], #0                        ;
;
; we should not have to worry about overflow
; since that condition occurs when
; "the high order half of the dividend is
;  greater or equal to the divisor"
; and our high order half is always hard coded
; to zero (A[3:2] <- 0).
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  call  Q20_Divide32_Raw                ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  move  C, #0                           ; no error

M32_Q20Div_Done:
  move  APC, #80h                       ;
  ret                                   ;

;********************************************************************
;*
;* Function:    Divide32_Raw
;*
;* Description: Divides 32 bit number by 32 bit number
;*
;* Input:       A[3:0]   - Dividend
;*              A[7:6] - Divisor
;*              A[5:4]  - DivisorBar
;*
;* Output:      A[3:2] - Remainder
;*              A[1:0] - Quotient
;*
;* Destroys:    A[7:4]
;*
;********************************************************************
Q20_Divide32_Raw:
  move  C, #1                           ;
  move  LC[0], #32                      ;
  move  AP, #0                          ;
  move  APC, #3                         ; modulo 8

M32_Q20DR_Loop:
  ;
  ; shift left remainder:quotient
  ;
  rlc                                   ;
  rlc                                   ;
  rlc                                   ;
  rlc                                   ;
  rlc                                   ;
  move  AP, #2                          ; point to remainder
  move  C, A[0].0                       ;
  sjump C, M32_Q20DR_Sub                ;
  ;
  ; add divisor to remainder
  ;
  add   A[6]                            ;
  addc  A[7]                            ;
  addc  #0                              ;
  sjump M32_Q20DR_LoopEnd               ;

M32_Q20DR_Sub:
  ;
  ; sub divisor from remainder
  ;
  sub   A[6]                            ;
  subb  A[7]                            ;
  subb  #0                              ;
  cpl   C                               ;

M32_Q20DR_LoopEnd:
  move  AP, #0                          ; carry into lsbit
  move  Acc.0, C                        ;
  djnz LC[0], M32_Q20DR_Loop           ;

  move  C, A[0].0                       ;
  sjump C, M32_Q20DR_Done               ;
  ;
  ; final restore
  ;
  move  AP, #2                          ; point to remainder
  add   A[6]                            ;
  addc  A[7]                            ;

M32_Q20DR_Done:
  move  APC, #80h                       ; reset AP/APC
  ret                                   ;


end
