#------------------------------------------------------------------------------
#
# Copyright (c) 2011, ARM. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution.  The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#------------------------------------------------------------------------------

#include "edk2asm.h"

.text
.align 2
GCC_ASM_EXPORT(__aeabi_uidiv)
GCC_ASM_EXPORT(__aeabi_uidivmod)
GCC_ASM_EXPORT(__aeabi_idiv)
GCC_ASM_EXPORT(__aeabi_idivmod)

#    AREA  Math, CODE, READONLY

#
#UINT32
#EFIAPI
#__aeabi_uidivmode (
#  IN UINT32  Dividen
#  IN UINT32  Divisor
#  );
#

ASM_PFX(__aeabi_uidiv):
ASM_PFX(__aeabi_uidivmod):
  rsbs    r12, r1, r0, LSR #4
  mov     r2, #0
  bcc     ASM_PFX(__arm_div4)
  rsbs    r12, r1, r0, LSR #8
  bcc     ASM_PFX(__arm_div8)
  mov     r3, #0
  b       ASM_PFX(__arm_div_large)

#
#INT32
#EFIAPI
#__aeabi_idivmode (
#  IN INT32  Dividen
#  IN INT32  Divisor
#  );
#
ASM_PFX(__aeabi_idiv):
ASM_PFX(__aeabi_idivmod):
  orrs    r12, r0, r1
  bmi     ASM_PFX(__arm_div_negative)
  rsbs    r12, r1, r0, LSR #1
  mov     r2, #0
  bcc     ASM_PFX(__arm_div1)
  rsbs    r12, r1, r0, LSR #4
  bcc     ASM_PFX(__arm_div4)
  rsbs    r12, r1, r0, LSR #8
  bcc     ASM_PFX(__arm_div8)
  mov     r3, #0
  b       ASM_PFX(__arm_div_large)
ASM_PFX(__arm_div8):
  rsbs    r12, r1, r0, LSR #7
  subcs   r0, r0, r1, LSL #7
  adc     r2, r2, r2
  rsbs    r12, r1, r0,LSR #6
  subcs   r0, r0, r1, LSL #6
  adc     r2, r2, r2
  rsbs    r12, r1, r0, LSR #5
  subcs   r0, r0, r1, LSL #5
  adc     r2, r2, r2
  rsbs    r12, r1, r0, LSR #4
  subcs   r0, r0, r1, LSL #4
  adc     r2, r2, r2
ASM_PFX(__arm_div4):
  rsbs    r12, r1, r0, LSR #3
  subcs   r0, r0, r1, LSL #3
  adc     r2, r2, r2
  rsbs    r12, r1, r0, LSR #2
  subcs   r0, r0, r1, LSL #2
  adcs    r2, r2, r2
  rsbs    r12, r1, r0, LSR #1
  subcs   r0, r0, r1, LSL #1
  adc     r2, r2, r2
ASM_PFX(__arm_div1):
  subs    r1, r0, r1
  movcc   r1, r0
  adc     r0, r2, r2
  bx      r14
ASM_PFX(__arm_div_negative):
  ands    r2, r1, #0x80000000
  rsbmi   r1, r1, #0
  eors    r3, r2, r0, ASR #32
  rsbcs   r0, r0, #0
  rsbs    r12, r1, r0, LSR #4
  bcc     label1
  rsbs    r12, r1, r0, LSR #8
  bcc     label2
ASM_PFX(__arm_div_large):
  lsl     r1, r1, #6
  rsbs    r12, r1, r0, LSR #8
  orr     r2, r2, #0xfc000000
  bcc     label2
  lsl     r1, r1, #6
  rsbs    r12, r1, r0, LSR #8
  orr     r2, r2, #0x3f00000
  bcc     label2
  lsl     r1, r1, #6
  rsbs    r12, r1, r0, LSR #8
  orr     r2, r2, #0xfc000
  orrcs   r2, r2, #0x3f00
  lslcs   r1, r1, #6
  rsbs    r12, r1, #0
  bcs     ASM_PFX(__aeabi_idiv0)
label3:
  lsrcs   r1, r1, #6
label2:
  rsbs    r12, r1, r0, LSR #7
  subcs   r0, r0, r1, LSL #7
  adc     r2, r2, r2
  rsbs    r12, r1, r0, LSR #6
  subcs   r0, r0, r1, LSL #6
  adc     r2, r2, r2
  rsbs    r12, r1, r0, LSR #5
  subcs   r0, r0, r1, LSL #5
  adc     r2, r2, r2
  rsbs    r12, r1, r0, LSR #4
  subcs   r0, r0, r1, LSL #4
  adc     r2, r2, r2
label1:
  rsbs    r12, r1, r0, LSR #3
  subcs   r0, r0, r1, LSL #3
  adc     r2, r2, r2
  rsbs    r12, r1, r0, LSR #2
  subcs   r0, r0, r1, LSL #2
  adcs    r2, r2, r2
  bcs     label3
  rsbs    r12, r1, r0, LSR #1
  subcs   r0, r0, r1, LSL #1
  adc     r2, r2, r2
  subs    r1, r0, r1
  movcc   r1, r0
  adc     r0, r2, r2
  asrs    r3, r3, #31
  rsbmi   r0, r0, #0
  rsbcs   r1, r1, #0
  bx      r14

  @ What to do about division by zero?  For now, just return.
ASM_PFX(__aeabi_idiv0):
  bx      r14
