udivsi3.S revision 1.1.1.7
1###################################-
2#
3#  Copyright (C) 2009-2018 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#  udivsi3.S
27#
28#  Unsigned divide operation.
29#	Input :	Divisor in Reg r5
30#		Dividend in Reg r6
31#	Output: Result in Reg r3
32#
33#######################################
34
35/* An executable stack is *not* required for these functions.  */
36#ifdef __linux__
37.section .note.GNU-stack,"",%progbits
38.previous
39#endif
40
41	.globl	__udivsi3
42	.ent	__udivsi3
43	.type	__udivsi3,@function
44__udivsi3:
45	.frame	r1,0,r15
46
47	ADDIK   r1,r1,-12
48    	SWI     r29,r1,0
49	SWI     r30,r1,4
50	SWI     r31,r1,8
51
52	BEQI    r6,$LaDiv_By_Zero           # Div_by_Zero   # Division Error
53	BEQID   r5,$LaResult_Is_Zero        # Result is Zero
54	ADDIK   r30,r0,0                    # Clear mod
55	ADDIK   r29,r0,32                   # Initialize the loop count
56
57        # Check if r6 and r5 are equal # if yes, return 1
58	RSUB 	r18,r5,r6
59	BEQID	r18,$LaRETURN_HERE
60	ADDIK	r3,r0,1
61
62        # Check if (uns)r6 is greater than (uns)r5. In that case, just return 0
63	XOR	r18,r5,r6
64	BGEID	r18,16
65	ADD	r3,r0,r0                    # We would anyways clear r3
66	BLTI	r6,$LaRETURN_HERE           # r6[bit 31 = 1] hence is greater
67	BRI	$LCheckr6
68	RSUB	r18,r6,r5                   # MICROBLAZEcmp
69	BLTI	r18,$LaRETURN_HERE
70
71        # If r6 [bit 31] is set, then return result as 1
72$LCheckr6:
73	BGTI	r6,$LaDIV0
74	BRID	$LaRETURN_HERE
75	ADDIK	r3,r0,1
76
77        # First part try to find the first '1' in the r5
78$LaDIV0:
79	BLTI    r5,$LaDIV2
80$LaDIV1:
81	ADD     r5,r5,r5                    # left shift logical r5
82	BGTID   r5,$LaDIV1
83	ADDIK   r29,r29,-1
84$LaDIV2:
85	ADD     r5,r5,r5                    # left shift logical  r5 get the '1' into the Carry
86	ADDC    r30,r30,r30                 # Move that bit into the Mod register
87	RSUB    r31,r6,r30                  # Try to subtract (r30 a r6)
88    	BLTI    r31,$LaMOD_TOO_SMALL
89	OR      r30,r0,r31                  # Move the r31 to mod since the result was positive
90	ADDIK   r3,r3,1
91$LaMOD_TOO_SMALL:
92	ADDIK   r29,r29,-1
93	BEQi    r29,$LaLOOP_END
94	ADD     r3,r3,r3 # Shift in the '1' into div
95	BRI     $LaDIV2   # Div2
96$LaLOOP_END:
97	BRI     $LaRETURN_HERE
98$LaDiv_By_Zero:
99$LaResult_Is_Zero:
100	OR      r3,r0,r0 # set result to 0
101$LaRETURN_HERE:
102        # Restore values of CSRs and that of r3 and the divisor and the dividend
103	LWI     r29,r1,0
104	LWI     r30,r1,4
105	LWI     r31,r1,8
106	RTSD    r15,8
107	ADDIK   r1,r1,12
108        .end __udivsi3
109	.size	__udivsi3, . - __udivsi3
110