James Hogan | 086e9dc | 2012-10-05 17:02:09 +0100 | [diff] [blame] | 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 |