1###################################
2#
3#  Copyright (C) 2009-2022 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#  modsi3.S
27#
28#  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/* 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	__modsi3
42	.ent	__modsi3
43	.type	__modsi3,@function
44__modsi3:
45	.frame	r1,0,r15
46
47	addik	r1,r1,-16
48	swi	r28,r1,0
49	swi	r29,r1,4
50	swi	r30,r1,8
51	swi	r31,r1,12
52
53	BEQI	r6,$LaDiv_By_Zero       # Div_by_Zero   # Division Error
54	BEQI	r5,$LaResult_Is_Zero    # Result is Zero
55	BGEId	r5,$LaR5_Pos
56	ADD	r28,r5,r0               # Get the sign of the result [ Depends only on the first arg]
57	RSUBI	r5,r5,0	                # Make r5 positive
58$LaR5_Pos:
59	BGEI	r6,$LaR6_Pos
60	RSUBI	r6,r6,0	    # Make r6 positive
61$LaR6_Pos:
62	ADDIK	r3,r0,0      # Clear mod
63	ADDIK	r30,r0,0     # clear div
64	BLTId	r5,$LaDIV2   # If r5 is still negative (0x80000000), skip
65			     # the first bit search.
66	ADDIK	r29,r0,32    # Initialize the loop count
67   # First part try to find the first '1' in the r5
68$LaDIV1:
69	ADD	r5,r5,r5         # left shift logical r5
70	BGEID	r5,$LaDIV1       #
71	ADDIK	r29,r29,-1
72$LaDIV2:
73	ADD	r5,r5,r5         # left shift logical  r5 get the '1' into the Carry
74	ADDC	r3,r3,r3         # Move that bit into the Mod register
75	rSUB	r31,r6,r3        # Try to subtract (r30 a r6)
76	BLTi	r31,$LaMOD_TOO_SMALL
77	OR	r3,r0,r31       # Move the r31 to mod since the result was positive
78	ADDIK	r30,r30,1
79$LaMOD_TOO_SMALL:
80	ADDIK	r29,r29,-1
81	BEQi	r29,$LaLOOP_END
82	ADD	r30,r30,r30         # Shift in the '1' into div
83	BRI	$LaDIV2          # Div2
84$LaLOOP_END:
85	BGEI	r28,$LaRETURN_HERE
86	BRId	$LaRETURN_HERE
87	rsubi	r3,r3,0 # Negate the result
88$LaDiv_By_Zero:
89$LaResult_Is_Zero:
90	or	r3,r0,r0        # set result to 0 [Both mod as well as div are 0]
91$LaRETURN_HERE:
92# Restore values of CSRs and that of r3 and the divisor and the dividend
93	lwi	r28,r1,0
94	lwi	r29,r1,4
95	lwi	r30,r1,8
96	lwi	r31,r1,12
97	rtsd	r15,8
98	addik	r1,r1,16
99        .end __modsi3
100	.size	__modsi3, . - __modsi3
101
102