Commit | Line | Data |
---|---|---|
086e9dc0 JH |
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 |