Add .type and .size directives to riscv libgcc functions.
[official-gcc.git] / libgcc / config / riscv / div.S
blob4366c5ce1dca20424d06997a72e6f51f7b0197a8
1 /* Integer division routines for RISC-V.
3    Copyright (C) 2016-2017 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 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 #include "riscv-asm.h"
28   .text
29   .align 2
31 #if __riscv_xlen == 32
32 /* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines.  */
33 # define __udivdi3 __udivsi3
34 # define __umoddi3 __umodsi3
35 # define __divdi3 __divsi3
36 # define __moddi3 __modsi3
37 #else
38 FUNC_BEGIN (__udivsi3)
39   /* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t.  */
40   sll    a0, a0, 32
41   sll    a1, a1, 32
42   move   t0, ra
43   jal    __udivdi3
44   sext.w a0, a0
45   jr     t0
46 FUNC_END (__udivsi3)
48 FUNC_BEGIN (__umodsi3)
49   /* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t.  */
50   sll    a0, a0, 32
51   sll    a1, a1, 32
52   srl    a0, a0, 32
53   srl    a1, a1, 32
54   move   t0, ra
55   jal    __udivdi3
56   sext.w a0, a1
57   jr     t0
58 FUNC_END (__umodsi3)
60 FUNC_ALIAS (__modsi3, __moddi3)
62 FUNC_BEGIN( __divsi3)
63   /* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3.  */
64   li    t0, -1
65   beq   a1, t0, .L20
66 #endif
68 FUNC_BEGIN (__divdi3)
69   bltz  a0, .L10
70   bltz  a1, .L11
71   /* Since the quotient is positive, fall into __udivdi3.  */
73 FUNC_BEGIN (__udivdi3)
74   mv    a2, a1
75   mv    a1, a0
76   li    a0, -1
77   beqz  a2, .L5
78   li    a3, 1
79   bgeu  a2, a1, .L2
80 .L1:
81   blez  a2, .L2
82   slli  a2, a2, 1
83   slli  a3, a3, 1
84   bgtu  a1, a2, .L1
85 .L2:
86   li    a0, 0
87 .L3:
88   bltu  a1, a2, .L4
89   sub   a1, a1, a2
90   or    a0, a0, a3
91 .L4:
92   srli  a3, a3, 1
93   srli  a2, a2, 1
94   bnez  a3, .L3
95 .L5:
96   ret
97 FUNC_END (__udivdi3)
99 FUNC_BEGIN (__umoddi3)
100   /* Call __udivdi3(a0, a1), then return the remainder, which is in a1.  */
101   move  t0, ra
102   jal   __udivdi3
103   move  a0, a1
104   jr    t0
105 FUNC_END (__umoddi3)
107   /* Handle negative arguments to __divdi3.  */
108 .L10:
109   neg   a0, a0
110   bgez  a1, .L12      /* Compute __udivdi3(-a0, a1), then negate the result.  */
111   neg   a1, a1
112   j     __udivdi3     /* Compute __udivdi3(-a0, -a1).  */
113 .L11:                 /* Compute __udivdi3(a0, -a1), then negate the result.  */
114   neg   a1, a1
115 .L12:
116   move  t0, ra
117   jal   __udivdi3
118   neg   a0, a0
119   jr    t0
120 FUNC_END (__divdi3)
122 FUNC_BEGIN (__moddi3)
123   move   t0, ra
124   bltz   a1, .L31
125   bltz   a0, .L32
126 .L30:
127   jal    __udivdi3    /* The dividend is not negative.  */
128   move   a0, a1
129   jr     t0
130 .L31:
131   neg    a1, a1
132   bgez   a0, .L30
133 .L32:
134   neg    a0, a0
135   jal    __udivdi3    /* The dividend is hella negative.  */
136   neg    a0, a1
137   jr     t0
138 FUNC_END (__moddi3)
140 #if __riscv_xlen == 64
141   /* continuation of __divsi3 */
142 .L20:
143   sll   t0, t0, 31
144   bne   a0, t0, __divdi3
145   ret
146 FUNC_END (__divsi3)
147 #endif