1 /* Integer division routines for RISC-V. 2 3 Copyright (C) 2016-2024 Free Software Foundation, Inc. 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 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 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 HIDDEN_JUMPTARGET(__udivdi3) 44 sext.w a0, a0 45 jr t0 46 FUNC_END (__udivsi3) 47 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 HIDDEN_JUMPTARGET(__udivdi3) 56 sext.w a0, a1 57 jr t0 58 FUNC_END (__umodsi3) 59 60 FUNC_ALIAS (__modsi3, __moddi3) 61 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 67 68 FUNC_BEGIN (__divdi3) 69 bltz a0, .L10 70 bltz a1, .L11 71 /* Since the quotient is positive, fall into __udivdi3. */ 72 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) 98 HIDDEN_DEF (__udivdi3) 99 100 FUNC_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 106 FUNC_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 123 FUNC_END (__divdi3) 124 125 FUNC_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 141 FUNC_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 149 FUNC_END (__divsi3) 150 #endif 151