2015-05-06 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgcc / config / microblaze / moddi3.S
blob631b8a5e650153d10bc9cb07450cd5b0f3214d36
1 ###################################
2
3 #  Copyright (C) 2009-2015 Free Software Foundation, Inc.
5 #  Contributed by Michael Eager <eager@eagercon.com>.
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.
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.
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.
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/>. 
26 #  modsi3.S
27
28 #  modulo operation for 64 bit integers.
29
30 #######################################
33         .globl  __moddi3
34         .ent    __moddi3
35 __moddi3:
36         .frame  r1,0,r15        
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
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