xref: /netbsd-src/external/gpl3/gcc.old/dist/libgcc/config/riscv/div.S (revision 4ac76180e904e771b9d522c7e57296d371f06499)
1/* Integer division routines for RISC-V.
2
3   Copyright (C) 2016-2020 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24<http://www.gnu.org/licenses/>.  */
25
26#include "riscv-asm.h"
27
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
38FUNC_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    HIDDEN_JUMPTARGET(__udivdi3)
44  sext.w a0, a0
45  jr     t0
46FUNC_END (__udivsi3)
47
48FUNC_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    HIDDEN_JUMPTARGET(__udivdi3)
56  sext.w a0, a1
57  jr     t0
58FUNC_END (__umodsi3)
59
60FUNC_ALIAS (__modsi3, __moddi3)
61
62FUNC_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
67
68FUNC_BEGIN (__divdi3)
69  bltz  a0, .L10
70  bltz  a1, .L11
71  /* Since the quotient is positive, fall into __udivdi3.  */
72
73FUNC_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
97FUNC_END (__udivdi3)
98HIDDEN_DEF (__udivdi3)
99
100FUNC_BEGIN (__umoddi3)
101  /* Call __udivdi3(a0, a1), then return the remainder, which is in a1.  */
102  move  t0, ra
103  jal   HIDDEN_JUMPTARGET(__udivdi3)
104  move  a0, a1
105  jr    t0
106FUNC_END (__umoddi3)
107
108  /* Handle negative arguments to __divdi3.  */
109.L10:
110  neg   a0, a0
111  /* Zero is handled as a negative so that the result will not be inverted.  */
112  bgtz  a1, .L12     /* Compute __udivdi3(-a0, a1), then negate the result.  */
113
114  neg   a1, a1
115  j     HIDDEN_JUMPTARGET(__udivdi3)     /* Compute __udivdi3(-a0, -a1).  */
116.L11:                /* Compute __udivdi3(a0, -a1), then negate the result.  */
117  neg   a1, a1
118.L12:
119  move  t0, ra
120  jal   HIDDEN_JUMPTARGET(__udivdi3)
121  neg   a0, a0
122  jr    t0
123FUNC_END (__divdi3)
124
125FUNC_BEGIN (__moddi3)
126  move   t0, ra
127  bltz   a1, .L31
128  bltz   a0, .L32
129.L30:
130  jal    HIDDEN_JUMPTARGET(__udivdi3)    /* The dividend is not negative.  */
131  move   a0, a1
132  jr     t0
133.L31:
134  neg    a1, a1
135  bgez   a0, .L30
136.L32:
137  neg    a0, a0
138  jal    HIDDEN_JUMPTARGET(__udivdi3)    /* The dividend is hella negative.  */
139  neg    a0, a1
140  jr     t0
141FUNC_END (__moddi3)
142
143#if __riscv_xlen == 64
144  /* continuation of __divsi3 */
145.L20:
146  sll   t0, t0, 31
147  bne   a0, t0, __divdi3
148  ret
149FUNC_END (__divsi3)
150#endif
151