xref: /netbsd-src/external/gpl3/gcc.old/dist/libgcc/config/microblaze/moddi3.S (revision 1580a27b92f58fcdcb23fdfbc04a7c2b54a0b7c8)
1###################################
2#
3#  Copyright (C) 2009-2015 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 64 bit integers.
29#
30#######################################
31
32
33	.globl	__moddi3
34	.ent	__moddi3
35__moddi3:
36	.frame	r1,0,r15
37
38#Change the stack pointer value and Save callee saved regs
39	addik	r1,r1,-24
40	swi	r25,r1,0
41	swi	r26,r1,4
42	swi	r27,r1,8	# used for sign
43	swi	r28,r1,12	# used for loop count
44	swi	r29,r1,16	# Used for div value High
45	swi	r30,r1,20	# Used for div value Low
46
47#Check for Zero Value in the divisor/dividend
48	OR	r9,r5,r6			# Check for the op1 being zero
49	BEQID	r9,$LaResult_Is_Zero		# Result is zero
50	OR	r9,r7,r8			# Check for the dividend being zero
51	BEQI	r9,$LaDiv_By_Zero	        # Div_by_Zero   # Division Error
52	BGEId	r5,$La1_Pos
53	XOR	r27,r5,r7			# Get the sign of the result
54	RSUBI	r6,r6,0				# Make dividend positive
55	RSUBIC	r5,r5,0				# Make dividend positive
56$La1_Pos:
57	BGEI	r7,$La2_Pos
58	RSUBI	r8,r8,0				# Make Divisor Positive
59	RSUBIC	r9,r9,0				# Make Divisor Positive
60$La2_Pos:
61	ADDIK	r4,r0,0				# Clear mod low
62	ADDIK	r3,r0,0                	        # Clear mod high
63	ADDIK	r29,r0,0			# clear div high
64	ADDIK	r30,r0,0			# clear div low
65	ADDIK	r28,r0,64			# Initialize the loop count
66   # First part try to find the first '1' in the r5/r6
67$LaDIV1:
68	ADD	r6,r6,r6
69	ADDC	r5,r5,r5			# left shift logical r5
70	BGEID	r5,$LaDIV1
71	ADDIK	r28,r28,-1
72$LaDIV2:
73	ADD	r6,r6,r6
74	ADDC	r5,r5,r5	# left shift logical r5/r6 get the '1' into the Carry
75	ADDC	r4,r4,r4	# Move that bit into the Mod register
76	ADDC	r3,r3,r3	# Move carry into high mod register
77	rsub	r18,r7,r3	# Compare the High Parts of Mod and Divisor
78	bnei	r18,$L_High_EQ
79	rsub	r18,r6,r4	# Compare Low Parts only if Mod[h] == Divisor[h]
80$L_High_EQ:
81	rSUB	r26,r8,r4	# Subtract divisor[L] from Mod[L]
82	rsubc	r25,r7,r3	# Subtract divisor[H] from Mod[H]
83	BLTi	r25,$LaMOD_TOO_SMALL
84	OR	r3,r0,r25	# move r25 to mod [h]
85	OR	r4,r0,r26	# move r26 to mod [l]
86	ADDI	r30,r30,1
87	ADDC	r29,r29,r0
88$LaMOD_TOO_SMALL:
89	ADDIK	r28,r28,-1
90	BEQi	r28,$LaLOOP_END
91	ADD	r30,r30,r30		# Shift in the '1' into div [low]
92	ADDC	r29,r29,r29		# Move the carry generated into high
93	BRI	$LaDIV2   # Div2
94$LaLOOP_END:
95	BGEI	r27,$LaRETURN_HERE
96	rsubi	r30,r30,0
97	rsubc	r29,r29,r0
98	BRI	$LaRETURN_HERE
99$LaDiv_By_Zero:
100$LaResult_Is_Zero:
101	or	r29,r0,r0	# set result to 0 [High]
102	or	r30,r0,r0	# set result to 0 [Low]
103$LaRETURN_HERE:
104# Restore values of CSRs and that of r29 and the divisor and the dividend
105
106	lwi	r25,r1,0
107	lwi	r26,r1,4
108	lwi	r27,r1,8
109	lwi	r28,r1,12
110	lwi	r29,r1,16
111	lwi	r30,r1,20
112	rtsd	r15,8
113	addik r1,r1,24
114        .end __moddi3
115
116