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