]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/microblaze/umodsi3.asm
f7fd00879659410e8a657a0b2ebbe2cdcdebfd93
[thirdparty/gcc.git] / libgcc / config / microblaze / umodsi3.asm
1 ###################################
2 #
3 # Copyright 2009, 2010 Free Software Foundation, Inc.
4 #
5 # Contributed by Michael Eager <eager@eagercon.com>.
6 #
7 # This file is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by the
9 # Free Software Foundation; either version 3, or (at your option) any
10 # later version.
11 #
12 # GCC is distributed in the hope that it will be useful, but WITHOUT
13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 # License for more details.
16 #
17 # Under Section 7 of GPL version 3, you are granted additional
18 # permissions described in the GCC Runtime Library Exception, version
19 # 3.1, as published by the Free Software Foundation.
20 #
21 # You should have received a copy of the GNU General Public License and
22 # a copy of the GCC Runtime Library Exception along with this program;
23 # see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 # <http://www.gnu.org/licenses/>.
25 #
26 # umodsi3.asm
27 #
28 # Unsigned modulo operation for 32 bit integers.
29 # Input : op1 in Reg r5
30 # op2 in Reg r6
31 # Output: op1 mod op2 in Reg r3
32 #
33 #######################################
34
35 .globl __umodsi3
36 .ent __umodsi3
37 .type __umodsi3,@function
38 __umodsi3:
39 .frame r1,0,r15
40
41 addik r1,r1,-12
42 swi r29,r1,0
43 swi r30,r1,4
44 swi r31,r1,8
45
46 BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
47 BEQId r5,$LaResult_Is_Zero # Result is Zero
48 ADDIK r3,r0,0 # Clear div
49 ADDIK r30,r0,0 # clear mod
50 ADDIK r29,r0,32 # Initialize the loop count
51
52 # Check if r6 and r5 are equal # if yes, return 0
53 rsub r18,r5,r6
54 beqi r18,$LaRETURN_HERE
55
56 # Check if (uns)r6 is greater than (uns)r5. In that case, just return r5
57 xor r18,r5,r6
58 bgeid r18,16
59 addik r3,r5,0
60 blti r6,$LaRETURN_HERE
61 bri $LCheckr6
62 rsub r18,r5,r6 # MICROBLAZEcmp
63 bgti r18,$LaRETURN_HERE
64
65 # If r6 [bit 31] is set, then return result as r5-r6
66 $LCheckr6:
67 bgtid r6,$LaDIV0
68 addik r3,r0,0
69 addik r18,r0,0x7fffffff
70 and r5,r5,r18
71 and r6,r6,r18
72 brid $LaRETURN_HERE
73 rsub r3,r6,r5
74 # First part: try to find the first '1' in the r5
75 $LaDIV0:
76 BLTI r5,$LaDIV2
77 $LaDIV1:
78 ADD r5,r5,r5 # left shift logical r5
79 BGEID r5,$LaDIV1 #
80 ADDIK r29,r29,-1
81 $LaDIV2:
82 ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
83 ADDC r3,r3,r3 # Move that bit into the Mod register
84 rSUB r31,r6,r3 # Try to subtract (r3 a r6)
85 BLTi r31,$LaMOD_TOO_SMALL
86 OR r3,r0,r31 # Move the r31 to mod since the result was positive
87 ADDIK r30,r30,1
88 $LaMOD_TOO_SMALL:
89 ADDIK r29,r29,-1
90 BEQi r29,$LaLOOP_END
91 ADD r30,r30,r30 # Shift in the '1' into div
92 BRI $LaDIV2 # Div2
93 $LaLOOP_END:
94 BRI $LaRETURN_HERE
95 $LaDiv_By_Zero:
96 $LaResult_Is_Zero:
97 or r3,r0,r0 # set result to 0
98 $LaRETURN_HERE:
99 # Restore values of CSRs and that of r3 and the divisor and the dividend
100 lwi r29,r1,0
101 lwi r30,r1,4
102 lwi r31,r1,8
103 rtsd r15,8
104 addik r1,r1,12
105 .end __umodsi3
106 .size __umodsi3, . - __umodsi3