linux/arch/metag/lib/divsi3.S
<<
>>
Prefs
   1! Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
   2!               Imagination Technologies Ltd
   3!
   4! Integer divide routines.
   5!
   6
   7        .text
   8        .global ___udivsi3
   9        .type   ___udivsi3,function
  10        .align  2
  11___udivsi3:
  12!!
  13!! Since core is signed divide case, just set control variable
  14!!
  15        MOV     D1Re0,D0Ar2             ! Au already in A1Ar1, Bu -> D1Re0
  16        MOV     D0Re0,#0                ! Result is 0
  17        MOV     D0Ar4,#0                ! Return positive result
  18        B       $LIDMCUStart
  19        .size   ___udivsi3,.-___udivsi3
  20
  21!!
  22!! 32-bit division signed i/p - passed signed 32-bit numbers
  23!!
  24        .global ___divsi3
  25        .type   ___divsi3,function
  26        .align  2
  27___divsi3:
  28!!
  29!! A already in D1Ar1, B already in D0Ar2 -> make B abs(B)
  30!!
  31        MOV     D1Re0,D0Ar2             ! A already in A1Ar1, B -> D1Re0
  32        MOV     D0Re0,#0                ! Result is 0
  33        XOR     D0Ar4,D1Ar1,D1Re0       ! D0Ar4 -ive if result is -ive
  34        ABS     D1Ar1,D1Ar1             ! abs(A) -> Au
  35        ABS     D1Re0,D1Re0             ! abs(B) -> Bu
  36$LIDMCUStart:
  37        CMP     D1Ar1,D1Re0             ! Is ( Au > Bu )?
  38        LSR     D1Ar3,D1Ar1,#2          ! Calculate (Au & (~3)) >> 2
  39        CMPHI   D1Re0,D1Ar3             ! OR ( (Au & (~3)) <= (Bu << 2) )?
  40        LSLSHI  D1Ar3,D1Re0,#1          ! Buq = Bu << 1
  41        BLS     $LIDMCUSetup            ! Yes: Do normal divide
  42!!
  43!! Quick divide setup can assume that CurBit only needs to start at 2
  44!!
  45$LIDMCQuick:
  46        CMP     D1Ar1,D1Ar3             ! ( A >= Buq )?
  47        ADDCC   D0Re0,D0Re0,#2          ! If yes result += 2
  48        SUBCC   D1Ar1,D1Ar1,D1Ar3       !        and A -= Buq
  49        CMP     D1Ar1,D1Re0             ! ( A >= Bu )?
  50        ADDCC   D0Re0,D0Re0,#1          ! If yes result += 1
  51        SUBCC   D1Ar1,D1Ar1,D1Re0       !        and A -= Bu
  52        ORS     D0Ar4,D0Ar4,D0Ar4       ! Return neg result?
  53        NEG     D0Ar2,D0Re0             ! Calulate neg result
  54        MOVMI   D0Re0,D0Ar2             ! Yes: Take neg result
  55$LIDMCRet:
  56        MOV     PC,D1RtP
  57!!
  58!!  Setup for general unsigned divide code
  59!!
  60!!      D0Re0 is used to form the result, already set to Zero
  61!!      D1Re0 is the input Bu value, this gets trashed
  62!!      D0Ar6 is curbit which is set to 1 at the start and shifted up
  63!!      D0Ar4 is negative if we should return a negative result
  64!!      D1Ar1 is the input Au value, eventually this holds the remainder
  65!!
  66$LIDMCUSetup:
  67        CMP     D1Ar1,D1Re0             ! Is ( Au < Bu )?
  68        MOV     D0Ar6,#1                ! Set curbit to 1
  69        BCS     $LIDMCRet               ! Yes: Return 0 remainder Au
  70!!
  71!! Calculate alignment using FFB instruction
  72!!
  73        FFB     D1Ar5,D1Ar1             ! Find first bit of Au
  74        ANDN    D1Ar5,D1Ar5,#31         ! Handle exceptional case.
  75        ORN     D1Ar5,D1Ar5,#31         ! if N bit set, set to 31
  76        FFB     D1Ar3,D1Re0             ! Find first bit of Bu
  77        ANDN    D1Ar3,D1Ar3,#31         ! Handle exceptional case.
  78        ORN     D1Ar3,D1Ar3,#31         ! if N bit set, set to 31
  79        SUBS    D1Ar3,D1Ar5,D1Ar3       ! calculate diff, ffbA - ffbB
  80        MOV     D0Ar2,D1Ar3             ! copy into bank 0
  81        LSLGT   D1Re0,D1Re0,D1Ar3       ! ( > 0) ? left shift B
  82        LSLGT   D0Ar6,D0Ar6,D0Ar2       ! ( > 0) ? left shift curbit
  83!!
  84!! Now we start the divide proper, logic is
  85!!
  86!!       if ( A >= B ) add curbit to result and subtract B from A
  87!!       shift curbit and B down by 1 in either case
  88!!
  89$LIDMCLoop:
  90        CMP     D1Ar1, D1Re0            ! ( A >= B )?
  91        ADDCC   D0Re0, D0Re0, D0Ar6     ! If yes result += curbit
  92        SUBCC   D1Ar1, D1Ar1, D1Re0     ! and A -= B
  93        LSRS    D0Ar6, D0Ar6, #1        ! Shift down curbit, is it zero?
  94        LSR     D1Re0, D1Re0, #1        ! Shift down B
  95        BNZ     $LIDMCLoop               ! Was single bit in curbit lost?
  96        ORS     D0Ar4,D0Ar4,D0Ar4       ! Return neg result?
  97        NEG     D0Ar2,D0Re0             ! Calulate neg result
  98        MOVMI   D0Re0,D0Ar2             ! Yes: Take neg result
  99        MOV     PC,D1RtP
 100        .size   ___divsi3,.-___divsi3
 101