]>
Commit | Line | Data |
---|---|---|
36387fad | 1 | /* Integer division routines for RISC-V. |
2 | ||
fbd26352 | 3 | Copyright (C) 2016-2019 Free Software Foundation, Inc. |
36387fad | 4 | |
5 | This file is part of GCC. | |
6 | ||
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. | |
11 | ||
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. | |
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 | ||
1817431e | 26 | #include "riscv-asm.h" |
27 | ||
36387fad | 28 | .text |
29 | .align 2 | |
30 | ||
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 | |
1817431e | 38 | FUNC_BEGIN (__udivsi3) |
36387fad | 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 | |
1817431e | 46 | FUNC_END (__udivsi3) |
36387fad | 47 | |
1817431e | 48 | FUNC_BEGIN (__umodsi3) |
36387fad | 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 | |
1817431e | 58 | FUNC_END (__umodsi3) |
36387fad | 59 | |
1817431e | 60 | FUNC_ALIAS (__modsi3, __moddi3) |
36387fad | 61 | |
1817431e | 62 | FUNC_BEGIN( __divsi3) |
36387fad | 63 | /* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3. */ |
64 | li t0, -1 | |
65 | beq a1, t0, .L20 | |
66 | #endif | |
67 | ||
1817431e | 68 | FUNC_BEGIN (__divdi3) |
36387fad | 69 | bltz a0, .L10 |
70 | bltz a1, .L11 | |
71 | /* Since the quotient is positive, fall into __udivdi3. */ | |
72 | ||
1817431e | 73 | FUNC_BEGIN (__udivdi3) |
36387fad | 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 | |
1817431e | 97 | FUNC_END (__udivdi3) |
36387fad | 98 | |
1817431e | 99 | FUNC_BEGIN (__umoddi3) |
36387fad | 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 | |
1817431e | 105 | FUNC_END (__umoddi3) |
36387fad | 106 | |
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 | |
1817431e | 120 | FUNC_END (__divdi3) |
36387fad | 121 | |
1817431e | 122 | FUNC_BEGIN (__moddi3) |
36387fad | 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 | |
1817431e | 138 | FUNC_END (__moddi3) |
36387fad | 139 | |
140 | #if __riscv_xlen == 64 | |
141 | /* continuation of __divsi3 */ | |
142 | .L20: | |
143 | sll t0, t0, 31 | |
144 | bne a0, t0, __divdi3 | |
145 | ret | |
1817431e | 146 | FUNC_END (__divsi3) |
36387fad | 147 | #endif |